blob: 8437545c0c946a1143236701f96d154187acc085 [file] [log] [blame]
Chris Lattner5b183d82006-11-10 05:03:26 +00001//===--- SemaExpr.cpp - Semantic Analysis for Expressions -----------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements semantic analysis for expressions.
11//
12//===----------------------------------------------------------------------===//
13
14#include "Sema.h"
Chris Lattnercb6a3822006-11-10 06:20:45 +000015#include "clang/AST/ASTContext.h"
Chris Lattner17ed4872006-11-20 04:58:19 +000016#include "clang/AST/Decl.h"
Chris Lattner5b183d82006-11-10 05:03:26 +000017#include "clang/AST/Expr.h"
18#include "clang/Lex/Preprocessor.h"
Steve Naroff09ef4742007-03-09 23:16:33 +000019#include "clang/Lex/LiteralSupport.h"
Steve Narofff2fb89e2007-03-13 20:29:44 +000020#include "clang/Basic/SourceManager.h"
Chris Lattner5b183d82006-11-10 05:03:26 +000021#include "clang/Basic/Diagnostic.h"
Chris Lattnerac18be92006-11-20 06:49:47 +000022#include "clang/Basic/LangOptions.h"
Chris Lattner5b183d82006-11-10 05:03:26 +000023#include "clang/Basic/TargetInfo.h"
24#include "llvm/ADT/SmallString.h"
Chris Lattner5b183d82006-11-10 05:03:26 +000025using namespace llvm;
26using namespace clang;
27
Steve Naroffdf7855b2007-02-21 23:46:25 +000028/// ParseStringLiteral - The specified tokens were lexed as pasted string
Chris Lattner5b183d82006-11-10 05:03:26 +000029/// fragments (e.g. "foo" "bar" L"baz"). The result string has to handle string
30/// concatenation ([C99 5.1.1.2, translation phase #6]), so it may come from
31/// multiple tokens. However, the common case is that StringToks points to one
32/// string.
33///
34Action::ExprResult
Steve Naroffdf7855b2007-02-21 23:46:25 +000035Sema::ParseStringLiteral(const LexerToken *StringToks, unsigned NumStringToks) {
Chris Lattner5b183d82006-11-10 05:03:26 +000036 assert(NumStringToks && "Must have at least one string!");
37
Steve Naroff4f88b312007-03-13 22:37:02 +000038 StringLiteralParser Literal(StringToks, NumStringToks, PP, Context.Target);
39 if (Literal.hadError)
40 return ExprResult(true);
Chris Lattner5b183d82006-11-10 05:03:26 +000041
Chris Lattner5b183d82006-11-10 05:03:26 +000042 SmallVector<SourceLocation, 4> StringTokLocs;
43 for (unsigned i = 0; i != NumStringToks; ++i)
44 StringTokLocs.push_back(StringToks[i].getLocation());
Steve Narofff1e53692007-03-23 22:27:02 +000045
46 // FIXME: handle wchar_t
47 TypeRef t = Context.getPointerType(Context.CharTy);
48
Chris Lattner5b183d82006-11-10 05:03:26 +000049 // FIXME: use factory.
Chris Lattner5b183d82006-11-10 05:03:26 +000050 // Pass &StringTokLocs[0], StringTokLocs.size() to factory!
Steve Naroff4f88b312007-03-13 22:37:02 +000051 return new StringLiteral(Literal.GetString(), Literal.GetStringLength(),
Steve Narofff1e53692007-03-23 22:27:02 +000052 Literal.AnyWide, t);
Chris Lattner5b183d82006-11-10 05:03:26 +000053}
54
Chris Lattnere168f762006-11-10 05:29:30 +000055
Chris Lattnerac18be92006-11-20 06:49:47 +000056/// ParseIdentifierExpr - The parser read an identifier in expression context,
57/// validate it per-C99 6.5.1. HasTrailingLParen indicates whether this
58/// identifier is used in an function call context.
59Sema::ExprResult Sema::ParseIdentifierExpr(Scope *S, SourceLocation Loc,
60 IdentifierInfo &II,
61 bool HasTrailingLParen) {
Chris Lattner17ed4872006-11-20 04:58:19 +000062 // Could be enum-constant or decl.
Chris Lattner9561a0b2007-01-28 08:20:04 +000063 Decl *D = LookupScopedDecl(&II, Decl::IDNS_Ordinary, Loc, S);
Chris Lattner17ed4872006-11-20 04:58:19 +000064 if (D == 0) {
Bill Wendling4073ed52007-02-13 01:51:42 +000065 // Otherwise, this could be an implicitly declared function reference (legal
Chris Lattner9561a0b2007-01-28 08:20:04 +000066 // in C90, extension in C99).
Chris Lattnerac18be92006-11-20 06:49:47 +000067 if (HasTrailingLParen &&
68 // Not in C++.
Steve Narofff1e53692007-03-23 22:27:02 +000069 !getLangOptions().CPlusPlus)
Chris Lattnerac18be92006-11-20 06:49:47 +000070 D = ImplicitlyDefineFunction(Loc, II, S);
Steve Narofff1e53692007-03-23 22:27:02 +000071 else
Chris Lattnerac18be92006-11-20 06:49:47 +000072 // If this name wasn't predeclared and if this is not a function call,
73 // diagnose the problem.
Steve Narofff1e53692007-03-23 22:27:02 +000074 return Diag(Loc, diag::err_undeclared_var_use, II.getName());
Chris Lattner17ed4872006-11-20 04:58:19 +000075 }
76
Steve Narofff1e53692007-03-23 22:27:02 +000077 if (ObjectDecl *OD = dyn_cast<ObjectDecl>(D)) {
78 return new DeclRefExpr(OD);
79 } else if (isa<TypedefDecl>(D))
80 return Diag(Loc, diag::err_unexpected_typedef, II.getName());
81
82 assert(0 && "Invalid decl");
Chris Lattner17ed4872006-11-20 04:58:19 +000083}
Chris Lattnere168f762006-11-10 05:29:30 +000084
Chris Lattner17ed4872006-11-20 04:58:19 +000085Sema::ExprResult Sema::ParseSimplePrimaryExpr(SourceLocation Loc,
86 tok::TokenKind Kind) {
Chris Lattnere168f762006-11-10 05:29:30 +000087 switch (Kind) {
88 default:
89 assert(0 && "Unknown simple primary expr!");
Chris Lattnere168f762006-11-10 05:29:30 +000090 case tok::char_constant: // constant: character-constant
Chris Lattner17ed4872006-11-20 04:58:19 +000091 // TODO: MOVE this to be some other callback.
Chris Lattnere168f762006-11-10 05:29:30 +000092 case tok::kw___func__: // primary-expression: __func__ [C99 6.4.2.2]
93 case tok::kw___FUNCTION__: // primary-expression: __FUNCTION__ [GNU]
94 case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU]
Chris Lattner17ed4872006-11-20 04:58:19 +000095 return 0;
Chris Lattnere168f762006-11-10 05:29:30 +000096 }
97}
98
Steve Naroff8160ea22007-03-06 01:09:46 +000099Action::ExprResult Sema::ParseNumericConstant(const LexerToken &Tok) {
Steve Narofff2fb89e2007-03-13 20:29:44 +0000100 // fast path for a single digit (which is quite common). A single digit
101 // cannot have a trigraph, escaped newline, radix prefix, or type suffix.
102 if (Tok.getLength() == 1) {
103 const char *t = PP.getSourceManager().getCharacterData(Tok.getLocation());
104 return ExprResult(new IntegerLiteral(*t-'0', Context.IntTy));
105 }
Steve Naroff8160ea22007-03-06 01:09:46 +0000106 SmallString<512> IntegerBuffer;
107 IntegerBuffer.resize(Tok.getLength());
108 const char *ThisTokBegin = &IntegerBuffer[0];
109
110 // Get the spelling of the token, which eliminates trigraphs, etc. Notes:
111 // - We know that ThisTokBuf points to a buffer that is big enough for the
112 // whole token and 'spelled' tokens can only shrink.
113 // - In practice, the local buffer is only used when the spelling doesn't
114 // match the original token (which is rare). The common case simply returns
115 // a pointer to a *constant* buffer (avoiding a copy).
116
117 unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin);
Steve Naroff09ef4742007-03-09 23:16:33 +0000118 NumericLiteralParser Literal(ThisTokBegin, ThisTokBegin+ActualLength,
Steve Naroff451d8f162007-03-12 23:22:38 +0000119 Tok.getLocation(), PP);
Steve Narofff2fb89e2007-03-13 20:29:44 +0000120 if (Literal.hadError)
121 return ExprResult(true);
122
Steve Naroff09ef4742007-03-09 23:16:33 +0000123 if (Literal.isIntegerLiteral()) {
124 TypeRef t;
125 if (Literal.hasSuffix()) {
126 if (Literal.isLong)
127 t = Literal.isUnsigned ? Context.UnsignedLongTy : Context.LongTy;
128 else if (Literal.isLongLong)
129 t = Literal.isUnsigned ? Context.UnsignedLongLongTy : Context.LongLongTy;
130 else
131 t = Context.UnsignedIntTy;
132 } else {
133 t = Context.IntTy; // implicit type is "int"
134 }
Steve Naroff451d8f162007-03-12 23:22:38 +0000135 uintmax_t val;
136 if (Literal.GetIntegerValue(val)) {
Steve Narofff2fb89e2007-03-13 20:29:44 +0000137 return new IntegerLiteral(val, t);
Steve Naroff09ef4742007-03-09 23:16:33 +0000138 }
139 } else if (Literal.isFloatingLiteral()) {
Steve Narofff1e53692007-03-23 22:27:02 +0000140 // FIXME: fill in the value and compute the real type...
141 return new FloatingLiteral(7.7, Context.FloatTy);
Steve Naroff09ef4742007-03-09 23:16:33 +0000142 }
Steve Narofff2fb89e2007-03-13 20:29:44 +0000143 return ExprResult(true);
Chris Lattnere168f762006-11-10 05:29:30 +0000144}
145
146Action::ExprResult Sema::ParseParenExpr(SourceLocation L, SourceLocation R,
147 ExprTy *Val) {
148 return Val;
149}
150
151
152// Unary Operators. 'Tok' is the token for the operator.
153Action::ExprResult Sema::ParseUnaryOp(SourceLocation OpLoc, tok::TokenKind Op,
154 ExprTy *Input) {
155 UnaryOperator::Opcode Opc;
156 switch (Op) {
157 default: assert(0 && "Unknown unary op!");
158 case tok::plusplus: Opc = UnaryOperator::PreInc; break;
159 case tok::minusminus: Opc = UnaryOperator::PreDec; break;
160 case tok::amp: Opc = UnaryOperator::AddrOf; break;
161 case tok::star: Opc = UnaryOperator::Deref; break;
162 case tok::plus: Opc = UnaryOperator::Plus; break;
163 case tok::minus: Opc = UnaryOperator::Minus; break;
164 case tok::tilde: Opc = UnaryOperator::Not; break;
165 case tok::exclaim: Opc = UnaryOperator::LNot; break;
166 case tok::kw_sizeof: Opc = UnaryOperator::SizeOf; break;
167 case tok::kw___alignof: Opc = UnaryOperator::AlignOf; break;
168 case tok::kw___real: Opc = UnaryOperator::Real; break;
169 case tok::kw___imag: Opc = UnaryOperator::Imag; break;
170 case tok::ampamp: Opc = UnaryOperator::AddrLabel; break;
171 case tok::kw___extension__:
172 return Input;
173 //Opc = UnaryOperator::Extension;
174 //break;
175 }
Steve Naroff95af0132007-03-30 23:47:58 +0000176 if (Opc == UnaryOperator::PreInc || Opc == UnaryOperator::PreDec)
177 return CheckIncrementDecrementOperand((Expr *)Input, OpLoc, Opc);
178
179 // when all the check functions are written, this will go away...
180 return new UnaryOperator((Expr*)Input, Opc, 0);
Chris Lattnere168f762006-11-10 05:29:30 +0000181}
182
183Action::ExprResult Sema::
184ParseSizeOfAlignOfTypeExpr(SourceLocation OpLoc, bool isSizeof,
185 SourceLocation LParenLoc, TypeTy *Ty,
186 SourceLocation RParenLoc) {
Chris Lattner0d8b1a12006-11-20 04:34:45 +0000187 // If error parsing type, ignore.
188 if (Ty == 0) return true;
Chris Lattner6531c102007-01-23 22:29:49 +0000189
190 // Verify that this is a valid expression.
191 TypeRef ArgTy = TypeRef::getFromOpaquePtr(Ty);
192
193 if (isa<FunctionType>(ArgTy) && isSizeof) {
194 // alignof(function) is allowed.
195 Diag(OpLoc, diag::ext_sizeof_function_type);
Steve Naroff26c8ea52007-03-21 21:08:52 +0000196 return new IntegerLiteral(1, Context.IntTy);
Chris Lattner6531c102007-01-23 22:29:49 +0000197 } else if (ArgTy->isVoidType()) {
198 Diag(OpLoc, diag::ext_sizeof_void_type, isSizeof ? "sizeof" : "__alignof");
199 } else if (ArgTy->isIncompleteType()) {
200 std::string TypeName;
201 ArgTy->getAsString(TypeName);
202 Diag(OpLoc, isSizeof ? diag::err_sizeof_incomplete_type :
203 diag::err_alignof_incomplete_type, TypeName);
Steve Naroff26c8ea52007-03-21 21:08:52 +0000204 return new IntegerLiteral(0, Context.IntTy);
Chris Lattner6531c102007-01-23 22:29:49 +0000205 }
206
Steve Narofff1e53692007-03-23 22:27:02 +0000207 return new SizeOfAlignOfTypeExpr(isSizeof, ArgTy, Context.IntTy);
Chris Lattnere168f762006-11-10 05:29:30 +0000208}
209
210
211Action::ExprResult Sema::ParsePostfixUnaryOp(SourceLocation OpLoc,
212 tok::TokenKind Kind,
213 ExprTy *Input) {
214 UnaryOperator::Opcode Opc;
215 switch (Kind) {
216 default: assert(0 && "Unknown unary op!");
217 case tok::plusplus: Opc = UnaryOperator::PostInc; break;
218 case tok::minusminus: Opc = UnaryOperator::PostDec; break;
219 }
Steve Naroff95af0132007-03-30 23:47:58 +0000220 return CheckIncrementDecrementOperand((Expr *)Input, OpLoc, Opc);
Chris Lattnere168f762006-11-10 05:29:30 +0000221}
222
223Action::ExprResult Sema::
224ParseArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc,
225 ExprTy *Idx, SourceLocation RLoc) {
Steve Narofff1e53692007-03-23 22:27:02 +0000226 TypeRef t1 = ((Expr *)Base)->getTypeRef();
227 TypeRef t2 = ((Expr *)Idx)->getTypeRef();
228
229 assert(!t1.isNull() && "no type for array base expression");
Steve Naroffc1aadb12007-03-28 21:49:40 +0000230 assert(!t2.isNull() && "no type for array index expression");
Steve Narofff1e53692007-03-23 22:27:02 +0000231
Steve Naroffc1aadb12007-03-28 21:49:40 +0000232 // C99 6.5.2.1p2: the expression e1[e2] is by definition precisely equivalent
233 // to the expression *((e1)+(e2)). This means the array "Base" may actually be
Steve Narofff1e53692007-03-23 22:27:02 +0000234 // in the subscript position. As a result, we need to derive the array base
235 // and index from the expression types.
236
237 TypeRef baseType, indexType;
238 if (isa<ArrayType>(t1) || isa<PointerType>(t1)) {
239 baseType = t1;
240 indexType = t2;
241 } else if (isa<ArrayType>(t2) || isa<PointerType>(t2)) { // uncommon case
242 baseType = t2;
243 indexType = t1;
244 } else
245 return Diag(LLoc, diag::err_typecheck_subscript_value);
246
Steve Naroffc1aadb12007-03-28 21:49:40 +0000247 // C99 6.5.2.1p1
248 if (!indexType->isIntegralType())
Steve Narofff1e53692007-03-23 22:27:02 +0000249 return Diag(LLoc, diag::err_typecheck_subscript);
Steve Naroffc1aadb12007-03-28 21:49:40 +0000250
Steve Naroff95af0132007-03-30 23:47:58 +0000251 // FIXME: need to deal with const...
Steve Naroffc1aadb12007-03-28 21:49:40 +0000252 TypeRef resultType;
253 if (ArrayType *ary = dyn_cast<ArrayType>(baseType)) {
254 resultType = ary->getElementType();
255 } else if (PointerType *ary = dyn_cast<PointerType>(baseType)) {
256 resultType = ary->getPointeeType();
257 // in practice, the following check catches trying to index a pointer
258 // to a function (e.g. void (*)(int)). Functions are not objects in c99.
Steve Naroffbc2f0992007-03-30 20:09:34 +0000259 if (!resultType->isObjectType())
260 return Diag(LLoc, diag::err_typecheck_subscript_not_object, baseType);
Steve Naroffc1aadb12007-03-28 21:49:40 +0000261 }
262 return new ArraySubscriptExpr((Expr*)Base, (Expr*)Idx, resultType);
Chris Lattnere168f762006-11-10 05:29:30 +0000263}
264
265Action::ExprResult Sema::
266ParseMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
267 tok::TokenKind OpKind, SourceLocation MemberLoc,
268 IdentifierInfo &Member) {
Steve Naroffca8f7122007-04-01 01:41:35 +0000269 TypeRef qualifiedType = ((Expr *)Base)->getTypeRef();
270
271 assert(!qualifiedType.isNull() && "no type for member expression");
272
273 Type *canonType = qualifiedType->getCanonicalType();
Steve Narofff1e53692007-03-23 22:27:02 +0000274
275 if (OpKind == tok::arrow) {
Steve Naroffca8f7122007-04-01 01:41:35 +0000276 if (PointerType *PT = dyn_cast<PointerType>(canonType)) {
277 qualifiedType = PT->getPointeeType();
278 canonType = qualifiedType->getCanonicalType();
279 } else
Steve Narofff1e53692007-03-23 22:27:02 +0000280 return Diag(OpLoc, diag::err_typecheck_member_reference_arrow);
281 }
Steve Naroffca8f7122007-04-01 01:41:35 +0000282 if (isa<RecordType>(canonType)) {
283 // get the struct/union definition from the type.
284 RecordDecl *RD = cast<RecordType>(canonType)->getDecl();
Steve Naroffcc321422007-03-26 23:09:51 +0000285
Steve Naroffca8f7122007-04-01 01:41:35 +0000286 if (canonType->isIncompleteType())
Steve Naroffcc321422007-03-26 23:09:51 +0000287 return Diag(OpLoc, diag::err_typecheck_incomplete_tag, RD->getName());
288
289 if (FieldDecl *MemberDecl = RD->getMember(&Member))
290 return new MemberExpr((Expr*)Base, OpKind == tok::arrow, MemberDecl);
291 else
292 return Diag(OpLoc, diag::err_typecheck_no_member, Member.getName());
293 }
294 return Diag(OpLoc, diag::err_typecheck_member_reference_structUnion);
Chris Lattnere168f762006-11-10 05:29:30 +0000295}
296
297/// ParseCallExpr - Handle a call to Fn with the specified array of arguments.
298/// This provides the location of the left/right parens and a list of comma
299/// locations.
300Action::ExprResult Sema::
301ParseCallExpr(ExprTy *Fn, SourceLocation LParenLoc,
302 ExprTy **Args, unsigned NumArgs,
303 SourceLocation *CommaLocs, SourceLocation RParenLoc) {
304 return new CallExpr((Expr*)Fn, (Expr**)Args, NumArgs);
305}
306
307Action::ExprResult Sema::
308ParseCastExpr(SourceLocation LParenLoc, TypeTy *Ty,
309 SourceLocation RParenLoc, ExprTy *Op) {
Chris Lattner0d8b1a12006-11-20 04:34:45 +0000310 // If error parsing type, ignore.
311 if (Ty == 0) return true;
312 return new CastExpr(TypeRef::getFromOpaquePtr(Ty), (Expr*)Op);
Chris Lattnere168f762006-11-10 05:29:30 +0000313}
314
315
316
317// Binary Operators. 'Tok' is the token for the operator.
318Action::ExprResult Sema::ParseBinOp(SourceLocation TokLoc, tok::TokenKind Kind,
319 ExprTy *LHS, ExprTy *RHS) {
320 BinaryOperator::Opcode Opc;
321 switch (Kind) {
322 default: assert(0 && "Unknown binop!");
323 case tok::star: Opc = BinaryOperator::Mul; break;
324 case tok::slash: Opc = BinaryOperator::Div; break;
325 case tok::percent: Opc = BinaryOperator::Rem; break;
326 case tok::plus: Opc = BinaryOperator::Add; break;
327 case tok::minus: Opc = BinaryOperator::Sub; break;
328 case tok::lessless: Opc = BinaryOperator::Shl; break;
329 case tok::greatergreater: Opc = BinaryOperator::Shr; break;
330 case tok::lessequal: Opc = BinaryOperator::LE; break;
331 case tok::less: Opc = BinaryOperator::LT; break;
332 case tok::greaterequal: Opc = BinaryOperator::GE; break;
333 case tok::greater: Opc = BinaryOperator::GT; break;
334 case tok::exclaimequal: Opc = BinaryOperator::NE; break;
335 case tok::equalequal: Opc = BinaryOperator::EQ; break;
336 case tok::amp: Opc = BinaryOperator::And; break;
337 case tok::caret: Opc = BinaryOperator::Xor; break;
338 case tok::pipe: Opc = BinaryOperator::Or; break;
339 case tok::ampamp: Opc = BinaryOperator::LAnd; break;
340 case tok::pipepipe: Opc = BinaryOperator::LOr; break;
341 case tok::equal: Opc = BinaryOperator::Assign; break;
342 case tok::starequal: Opc = BinaryOperator::MulAssign; break;
343 case tok::slashequal: Opc = BinaryOperator::DivAssign; break;
344 case tok::percentequal: Opc = BinaryOperator::RemAssign; break;
345 case tok::plusequal: Opc = BinaryOperator::AddAssign; break;
346 case tok::minusequal: Opc = BinaryOperator::SubAssign; break;
347 case tok::lesslessequal: Opc = BinaryOperator::ShlAssign; break;
348 case tok::greatergreaterequal: Opc = BinaryOperator::ShrAssign; break;
349 case tok::ampequal: Opc = BinaryOperator::AndAssign; break;
350 case tok::caretequal: Opc = BinaryOperator::XorAssign; break;
351 case tok::pipeequal: Opc = BinaryOperator::OrAssign; break;
352 case tok::comma: Opc = BinaryOperator::Comma; break;
353 }
Steve Narofff1e53692007-03-23 22:27:02 +0000354
355 // perform implicit conversions (C99 6.3)
356 Expr *e1 = ImplicitConversion((Expr*)LHS);
357 Expr *e2 = ImplicitConversion((Expr*)RHS);
Chris Lattnere168f762006-11-10 05:29:30 +0000358
Steve Naroff26c8ea52007-03-21 21:08:52 +0000359 if (BinaryOperator::isMultiplicativeOp(Opc))
360 CheckMultiplicativeOperands((Expr*)LHS, (Expr*)RHS);
361 else if (BinaryOperator::isAdditiveOp(Opc))
362 CheckAdditiveOperands((Expr*)LHS, (Expr*)RHS);
363 else if (BinaryOperator::isShiftOp(Opc))
364 CheckShiftOperands((Expr*)LHS, (Expr*)RHS);
365 else if (BinaryOperator::isRelationalOp(Opc))
366 CheckRelationalOperands((Expr*)LHS, (Expr*)RHS);
367 else if (BinaryOperator::isEqualityOp(Opc))
368 CheckEqualityOperands((Expr*)LHS, (Expr*)RHS);
369 else if (BinaryOperator::isBitwiseOp(Opc))
370 CheckBitwiseOperands((Expr*)LHS, (Expr*)RHS);
371 else if (BinaryOperator::isLogicalOp(Opc))
372 CheckLogicalOperands((Expr*)LHS, (Expr*)RHS);
373
Chris Lattnere168f762006-11-10 05:29:30 +0000374 return new BinaryOperator((Expr*)LHS, (Expr*)RHS, Opc);
375}
376
377/// ParseConditionalOp - Parse a ?: operation. Note that 'LHS' may be null
378/// in the case of a the GNU conditional expr extension.
379Action::ExprResult Sema::ParseConditionalOp(SourceLocation QuestionLoc,
380 SourceLocation ColonLoc,
381 ExprTy *Cond, ExprTy *LHS,
382 ExprTy *RHS) {
383 return new ConditionalOperator((Expr*)Cond, (Expr*)LHS, (Expr*)RHS);
384}
385
Steve Narofff1e53692007-03-23 22:27:02 +0000386Expr *Sema::ImplicitConversion(Expr *E) {
387#if 0
388 TypeRef t = E->getTypeRef();
389 if (t != 0) t.dump();
390 else printf("no type for expr %s\n", E->getStmtClassName());
391#endif
392 return E;
393}
394
Steve Naroff95af0132007-03-30 23:47:58 +0000395Action::ExprResult Sema::CheckMultiplicativeOperands(Expr *op1, Expr *op2) {
396 return false;
Steve Naroff26c8ea52007-03-21 21:08:52 +0000397}
398
Steve Naroff95af0132007-03-30 23:47:58 +0000399Action::ExprResult Sema::CheckAdditiveOperands(Expr *op1, Expr *op2) {
400 return false;
Steve Naroff26c8ea52007-03-21 21:08:52 +0000401}
402
Steve Naroff95af0132007-03-30 23:47:58 +0000403Action::ExprResult Sema::CheckShiftOperands(Expr *op1, Expr *op2) {
404 return false;
Steve Naroff26c8ea52007-03-21 21:08:52 +0000405}
406
Steve Naroff95af0132007-03-30 23:47:58 +0000407Action::ExprResult Sema::CheckRelationalOperands(Expr *op1, Expr *op2) {
408 return false;
Steve Naroff26c8ea52007-03-21 21:08:52 +0000409}
410
Steve Naroff95af0132007-03-30 23:47:58 +0000411Action::ExprResult Sema::CheckEqualityOperands(Expr *op1, Expr *op2) {
412 return false;
Steve Naroff26c8ea52007-03-21 21:08:52 +0000413}
414
Steve Naroff95af0132007-03-30 23:47:58 +0000415Action::ExprResult Sema::CheckBitwiseOperands(Expr *op1, Expr *op2) {
416 return false;
Steve Naroff26c8ea52007-03-21 21:08:52 +0000417}
418
Steve Naroff95af0132007-03-30 23:47:58 +0000419Action::ExprResult Sema::CheckLogicalOperands(Expr *op1, Expr *op2) {
420 return false;
421}
422
423Action::ExprResult
424Sema::CheckIncrementDecrementOperand(Expr *op, SourceLocation OpLoc,
425 UnaryOperator::Opcode OpCode) {
426 TypeRef type = op->getTypeRef();
427
428 assert(!type.isNull() && "no type for increment/decrement expression");
429
430 if (const PointerType *pt = dyn_cast<PointerType>(type)) {
431 if (!pt->getPointeeType()->isObjectType()) // C99 6.5.6p2
432 return Diag(OpLoc, diag::err_typecheck_arithmetic_incomplete_type, type);
433 } else if (!type->isRealType()) // C99 6.5.2.4: isRealType excludes complex.
434 // FIXME: Allow Complex as a GCC extension.
435 return Diag(OpLoc, diag::err_typecheck_illegal_increment_decrement, type);
436
437 // At this point, we know we have a real or pointer type. As a result, the
438 // following predicate is overkill (i.e. it will check for types we know we
439 // don't have in this context). Nevertheless, we model the C99 spec closely.
440 if (!type.isModifiableLvalue())
441 return Diag(OpLoc, diag::err_typecheck_not_modifiable, type);
442
443 return new UnaryOperator(op, OpCode, type);
Steve Naroff26c8ea52007-03-21 21:08:52 +0000444}
445