blob: 3e4c06ea294676d4c476e062d3006469fa6436e1 [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"
Chris Lattner5b183d82006-11-10 05:03:26 +000020#include "clang/Basic/Diagnostic.h"
Chris Lattnerac18be92006-11-20 06:49:47 +000021#include "clang/Basic/LangOptions.h"
Chris Lattner5b183d82006-11-10 05:03:26 +000022#include "clang/Basic/TargetInfo.h"
23#include "llvm/ADT/SmallString.h"
24#include "llvm/ADT/StringExtras.h"
25using namespace llvm;
26using namespace clang;
27
Steve Naroff09ef4742007-03-09 23:16:33 +000028#include <iostream>
Chris Lattner5b183d82006-11-10 05:03:26 +000029
30/// HexDigitValue - Return the value of the specified hex digit, or -1 if it's
31/// not valid.
32static int HexDigitValue(char C) {
33 if (C >= '0' && C <= '9') return C-'0';
34 if (C >= 'a' && C <= 'f') return C-'a'+10;
35 if (C >= 'A' && C <= 'F') return C-'A'+10;
36 return -1;
37}
38
Steve Naroffdf7855b2007-02-21 23:46:25 +000039/// ParseStringLiteral - The specified tokens were lexed as pasted string
Chris Lattner5b183d82006-11-10 05:03:26 +000040/// fragments (e.g. "foo" "bar" L"baz"). The result string has to handle string
41/// concatenation ([C99 5.1.1.2, translation phase #6]), so it may come from
42/// multiple tokens. However, the common case is that StringToks points to one
43/// string.
44///
45Action::ExprResult
Steve Naroffdf7855b2007-02-21 23:46:25 +000046Sema::ParseStringLiteral(const LexerToken *StringToks, unsigned NumStringToks) {
Chris Lattner5b183d82006-11-10 05:03:26 +000047 assert(NumStringToks && "Must have at least one string!");
48
49 // Scan all of the string portions, remember the max individual token length,
50 // computing a bound on the concatenated string length, and see whether any
51 // piece is a wide-string. If any of the string portions is a wide-string
52 // literal, the result is a wide-string literal [C99 6.4.5p4].
53 unsigned MaxTokenLength = StringToks[0].getLength();
54 unsigned SizeBound = StringToks[0].getLength()-2; // -2 for "".
55 bool AnyWide = StringToks[0].getKind() == tok::wide_string_literal;
56
57 // The common case is that there is only one string fragment.
58 for (unsigned i = 1; i != NumStringToks; ++i) {
59 // The string could be shorter than this if it needs cleaning, but this is a
60 // reasonable bound, which is all we need.
61 SizeBound += StringToks[i].getLength()-2; // -2 for "".
62
63 // Remember maximum string piece length.
64 if (StringToks[i].getLength() > MaxTokenLength)
65 MaxTokenLength = StringToks[i].getLength();
66
67 // Remember if we see any wide strings.
68 AnyWide |= StringToks[i].getKind() == tok::wide_string_literal;
69 }
70
71
72 // Include space for the null terminator.
73 ++SizeBound;
74
75 // TODO: K&R warning: "traditional C rejects string constant concatenation"
76
77 // Get the width in bytes of wchar_t. If no wchar_t strings are used, do not
78 // query the target. As such, wchar_tByteWidth is only valid if AnyWide=true.
79 unsigned wchar_tByteWidth = ~0U;
80 if (AnyWide)
Chris Lattnerddc135e2006-11-10 06:34:16 +000081 wchar_tByteWidth =Context.Target.getWCharWidth(StringToks[0].getLocation());
Chris Lattner5b183d82006-11-10 05:03:26 +000082
83 // The output buffer size needs to be large enough to hold wide characters.
84 // This is a worst-case assumption which basically corresponds to L"" "long".
85 if (AnyWide)
86 SizeBound *= wchar_tByteWidth;
87
88 // Create a temporary buffer to hold the result string data.
89 SmallString<512> ResultBuf;
90 ResultBuf.resize(SizeBound);
91
92 // Likewise, but for each string piece.
93 SmallString<512> TokenBuf;
94 TokenBuf.resize(MaxTokenLength);
95
96 // Loop over all the strings, getting their spelling, and expanding them to
97 // wide strings as appropriate.
98 char *ResultPtr = &ResultBuf[0]; // Next byte to fill in.
99
100 for (unsigned i = 0, e = NumStringToks; i != e; ++i) {
101 const char *ThisTokBuf = &TokenBuf[0];
102 // Get the spelling of the token, which eliminates trigraphs, etc. We know
103 // that ThisTokBuf points to a buffer that is big enough for the whole token
104 // and 'spelled' tokens can only shrink.
Steve Naroff38d31b42007-02-28 01:22:02 +0000105 unsigned ThisTokLen = PP.getSpelling(StringToks[i], ThisTokBuf);
Chris Lattner5b183d82006-11-10 05:03:26 +0000106 const char *ThisTokEnd = ThisTokBuf+ThisTokLen-1; // Skip end quote.
107
108 // TODO: Input character set mapping support.
109
110 // Skip L marker for wide strings.
111 if (ThisTokBuf[0] == 'L') ++ThisTokBuf;
112
113 assert(ThisTokBuf[0] == '"' && "Expected quote, lexer broken?");
114 ++ThisTokBuf;
115
116 while (ThisTokBuf != ThisTokEnd) {
117 // Is this a span of non-escape characters?
118 if (ThisTokBuf[0] != '\\') {
119 const char *InStart = ThisTokBuf;
120 do {
121 ++ThisTokBuf;
122 } while (ThisTokBuf != ThisTokEnd && ThisTokBuf[0] != '\\');
123
124 // Copy the character span over.
125 unsigned Len = ThisTokBuf-InStart;
126 if (!AnyWide) {
127 memcpy(ResultPtr, InStart, Len);
128 ResultPtr += Len;
129 } else {
130 // Note: our internal rep of wide char tokens is always little-endian.
131 for (; Len; --Len, ++InStart) {
132 *ResultPtr++ = InStart[0];
133 // Add zeros at the end.
134 for (unsigned i = 1, e = wchar_tByteWidth; i != e; ++i)
135 *ResultPtr++ = 0;
136 }
137 }
138 continue;
139 }
140
141 // Otherwise, this is an escape character. Skip the '\' char.
142 ++ThisTokBuf;
143
144 // We know that this character can't be off the end of the buffer, because
145 // that would have been \", which would not have been the end of string.
146 unsigned ResultChar = *ThisTokBuf++;
147 switch (ResultChar) {
148 // These map to themselves.
149 case '\\': case '\'': case '"': case '?': break;
150
151 // These have fixed mappings.
152 case 'a':
153 // TODO: K&R: the meaning of '\\a' is different in traditional C
154 ResultChar = 7;
155 break;
156 case 'b':
157 ResultChar = 8;
158 break;
159 case 'e':
Chris Lattnercb6a3822006-11-10 06:20:45 +0000160 Diag(StringToks[i].getLocation(), diag::ext_nonstandard_escape, "e");
Chris Lattner5b183d82006-11-10 05:03:26 +0000161 ResultChar = 27;
162 break;
163 case 'f':
164 ResultChar = 12;
165 break;
166 case 'n':
167 ResultChar = 10;
168 break;
169 case 'r':
170 ResultChar = 13;
171 break;
172 case 't':
173 ResultChar = 9;
174 break;
175 case 'v':
176 ResultChar = 11;
177 break;
178
179 //case 'u': case 'U': // FIXME: UCNs.
180 case 'x': // Hex escape.
181 if (ThisTokBuf == ThisTokEnd ||
182 (ResultChar = HexDigitValue(*ThisTokBuf)) == ~0U) {
Chris Lattnercb6a3822006-11-10 06:20:45 +0000183 Diag(StringToks[i].getLocation(), diag::err_hex_escape_no_digits);
Chris Lattner5b183d82006-11-10 05:03:26 +0000184 ResultChar = 0;
185 break;
186 }
187 ++ThisTokBuf; // Consumed one hex digit.
188
189 assert(0 && "hex escape: unimp!");
190 break;
191 case '0': case '1': case '2': case '3':
192 case '4': case '5': case '6': case '7':
193 // Octal escapes.
194 assert(0 && "octal escape: unimp!");
195 break;
196
197 // Otherwise, these are not valid escapes.
198 case '(': case '{': case '[': case '%':
199 // GCC accepts these as extensions. We warn about them as such though.
Steve Naroff38d31b42007-02-28 01:22:02 +0000200 if (!PP.getLangOptions().NoExtensions) {
Chris Lattnercb6a3822006-11-10 06:20:45 +0000201 Diag(StringToks[i].getLocation(), diag::ext_nonstandard_escape,
202 std::string()+(char)ResultChar);
Chris Lattner5b183d82006-11-10 05:03:26 +0000203 break;
204 }
205 // FALL THROUGH.
206 default:
207 if (isgraph(ThisTokBuf[0])) {
Chris Lattnercb6a3822006-11-10 06:20:45 +0000208 Diag(StringToks[i].getLocation(), diag::ext_unknown_escape,
209 std::string()+(char)ResultChar);
Chris Lattner5b183d82006-11-10 05:03:26 +0000210 } else {
Chris Lattnercb6a3822006-11-10 06:20:45 +0000211 Diag(StringToks[i].getLocation(), diag::ext_unknown_escape,
212 "x"+utohexstr(ResultChar));
Chris Lattner5b183d82006-11-10 05:03:26 +0000213 }
214 }
215
216 // Note: our internal rep of wide char tokens is always little-endian.
217 *ResultPtr++ = ResultChar & 0xFF;
218
219 if (AnyWide) {
220 for (unsigned i = 1, e = wchar_tByteWidth; i != e; ++i)
221 *ResultPtr++ = ResultChar >> i*8;
222 }
223 }
224 }
225
226 // Add zero terminator.
227 *ResultPtr = 0;
228 if (AnyWide) {
229 for (unsigned i = 1, e = wchar_tByteWidth; i != e; ++i)
230 *ResultPtr++ = 0;
231 }
232
233 SmallVector<SourceLocation, 4> StringTokLocs;
234 for (unsigned i = 0; i != NumStringToks; ++i)
235 StringTokLocs.push_back(StringToks[i].getLocation());
236
237 // FIXME: use factory.
238
239 // Pass &StringTokLocs[0], StringTokLocs.size() to factory!
Steve Naroffdf7855b2007-02-21 23:46:25 +0000240 return new StringLiteral(&ResultBuf[0], ResultPtr-&ResultBuf[0], AnyWide);
Chris Lattner5b183d82006-11-10 05:03:26 +0000241}
242
Chris Lattnere168f762006-11-10 05:29:30 +0000243
Chris Lattnerac18be92006-11-20 06:49:47 +0000244/// ParseIdentifierExpr - The parser read an identifier in expression context,
245/// validate it per-C99 6.5.1. HasTrailingLParen indicates whether this
246/// identifier is used in an function call context.
247Sema::ExprResult Sema::ParseIdentifierExpr(Scope *S, SourceLocation Loc,
248 IdentifierInfo &II,
249 bool HasTrailingLParen) {
Chris Lattner17ed4872006-11-20 04:58:19 +0000250 // Could be enum-constant or decl.
Chris Lattner9561a0b2007-01-28 08:20:04 +0000251 Decl *D = LookupScopedDecl(&II, Decl::IDNS_Ordinary, Loc, S);
Chris Lattner17ed4872006-11-20 04:58:19 +0000252 if (D == 0) {
Bill Wendling4073ed52007-02-13 01:51:42 +0000253 // Otherwise, this could be an implicitly declared function reference (legal
Chris Lattner9561a0b2007-01-28 08:20:04 +0000254 // in C90, extension in C99).
Chris Lattnerac18be92006-11-20 06:49:47 +0000255 if (HasTrailingLParen &&
256 // Not in C++.
257 !getLangOptions().CPlusPlus) {
258 D = ImplicitlyDefineFunction(Loc, II, S);
259 } else {
260 // If this name wasn't predeclared and if this is not a function call,
261 // diagnose the problem.
262 Diag(Loc, diag::err_undeclared_var_use, II.getName());
263 return true;
264 }
Chris Lattner17ed4872006-11-20 04:58:19 +0000265 }
266
Chris Lattner32d920b2007-01-26 02:01:53 +0000267 if (isa<TypedefDecl>(D)) {
Chris Lattner17ed4872006-11-20 04:58:19 +0000268 Diag(Loc, diag::err_unexpected_typedef, II.getName());
269 return true;
270 }
271
Chris Lattner5efbb332006-11-20 05:01:40 +0000272 return new DeclRefExpr(D);
Chris Lattner17ed4872006-11-20 04:58:19 +0000273}
Chris Lattnere168f762006-11-10 05:29:30 +0000274
Chris Lattner17ed4872006-11-20 04:58:19 +0000275Sema::ExprResult Sema::ParseSimplePrimaryExpr(SourceLocation Loc,
276 tok::TokenKind Kind) {
Chris Lattnere168f762006-11-10 05:29:30 +0000277 switch (Kind) {
278 default:
279 assert(0 && "Unknown simple primary expr!");
Chris Lattnere168f762006-11-10 05:29:30 +0000280 case tok::char_constant: // constant: character-constant
Chris Lattner17ed4872006-11-20 04:58:19 +0000281 // TODO: MOVE this to be some other callback.
Chris Lattnere168f762006-11-10 05:29:30 +0000282 case tok::kw___func__: // primary-expression: __func__ [C99 6.4.2.2]
283 case tok::kw___FUNCTION__: // primary-expression: __FUNCTION__ [GNU]
284 case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU]
Chris Lattner17ed4872006-11-20 04:58:19 +0000285 return 0;
Chris Lattnere168f762006-11-10 05:29:30 +0000286 }
287}
288
Steve Naroff8160ea22007-03-06 01:09:46 +0000289Action::ExprResult Sema::ParseNumericConstant(const LexerToken &Tok) {
290 SmallString<512> IntegerBuffer;
291 IntegerBuffer.resize(Tok.getLength());
292 const char *ThisTokBegin = &IntegerBuffer[0];
293
294 // Get the spelling of the token, which eliminates trigraphs, etc. Notes:
295 // - We know that ThisTokBuf points to a buffer that is big enough for the
296 // whole token and 'spelled' tokens can only shrink.
297 // - In practice, the local buffer is only used when the spelling doesn't
298 // match the original token (which is rare). The common case simply returns
299 // a pointer to a *constant* buffer (avoiding a copy).
300
301 unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin);
Steve Naroff8160ea22007-03-06 01:09:46 +0000302
303 // This is an optimization for single digits (which are very common).
Steve Naroff09ef4742007-03-09 23:16:33 +0000304 if (ActualLength == 1)
305 return ExprResult(new IntegerLiteral(atoi(ThisTokBegin)));
Steve Naroffcf307552007-03-07 01:21:37 +0000306
Steve Naroff09ef4742007-03-09 23:16:33 +0000307 NumericLiteralParser Literal(ThisTokBegin, ThisTokBegin+ActualLength,
Steve Naroff451d8f162007-03-12 23:22:38 +0000308 Tok.getLocation(), PP);
309 Expr *literal_expr = 0;
Steve Naroff09ef4742007-03-09 23:16:33 +0000310
311 if (Literal.isIntegerLiteral()) {
312 TypeRef t;
313 if (Literal.hasSuffix()) {
314 if (Literal.isLong)
315 t = Literal.isUnsigned ? Context.UnsignedLongTy : Context.LongTy;
316 else if (Literal.isLongLong)
317 t = Literal.isUnsigned ? Context.UnsignedLongLongTy : Context.LongLongTy;
318 else
319 t = Context.UnsignedIntTy;
320 } else {
321 t = Context.IntTy; // implicit type is "int"
322 }
Steve Naroff451d8f162007-03-12 23:22:38 +0000323 uintmax_t val;
324 if (Literal.GetIntegerValue(val)) {
Steve Naroff09ef4742007-03-09 23:16:33 +0000325 literal_expr = new IntegerLiteral(val, t);
326 }
327 } else if (Literal.isFloatingLiteral()) {
328 // TODO: add floating point processing...
329 }
Steve Naroff451d8f162007-03-12 23:22:38 +0000330 return literal_expr ? ExprResult(literal_expr) : ExprResult(true);
Chris Lattnere168f762006-11-10 05:29:30 +0000331}
332
333Action::ExprResult Sema::ParseParenExpr(SourceLocation L, SourceLocation R,
334 ExprTy *Val) {
335 return Val;
336}
337
338
339// Unary Operators. 'Tok' is the token for the operator.
340Action::ExprResult Sema::ParseUnaryOp(SourceLocation OpLoc, tok::TokenKind Op,
341 ExprTy *Input) {
342 UnaryOperator::Opcode Opc;
343 switch (Op) {
344 default: assert(0 && "Unknown unary op!");
345 case tok::plusplus: Opc = UnaryOperator::PreInc; break;
346 case tok::minusminus: Opc = UnaryOperator::PreDec; break;
347 case tok::amp: Opc = UnaryOperator::AddrOf; break;
348 case tok::star: Opc = UnaryOperator::Deref; break;
349 case tok::plus: Opc = UnaryOperator::Plus; break;
350 case tok::minus: Opc = UnaryOperator::Minus; break;
351 case tok::tilde: Opc = UnaryOperator::Not; break;
352 case tok::exclaim: Opc = UnaryOperator::LNot; break;
353 case tok::kw_sizeof: Opc = UnaryOperator::SizeOf; break;
354 case tok::kw___alignof: Opc = UnaryOperator::AlignOf; break;
355 case tok::kw___real: Opc = UnaryOperator::Real; break;
356 case tok::kw___imag: Opc = UnaryOperator::Imag; break;
357 case tok::ampamp: Opc = UnaryOperator::AddrLabel; break;
358 case tok::kw___extension__:
359 return Input;
360 //Opc = UnaryOperator::Extension;
361 //break;
362 }
363
364 return new UnaryOperator((Expr*)Input, Opc);
365}
366
367Action::ExprResult Sema::
368ParseSizeOfAlignOfTypeExpr(SourceLocation OpLoc, bool isSizeof,
369 SourceLocation LParenLoc, TypeTy *Ty,
370 SourceLocation RParenLoc) {
Chris Lattner0d8b1a12006-11-20 04:34:45 +0000371 // If error parsing type, ignore.
372 if (Ty == 0) return true;
Chris Lattner6531c102007-01-23 22:29:49 +0000373
374 // Verify that this is a valid expression.
375 TypeRef ArgTy = TypeRef::getFromOpaquePtr(Ty);
376
377 if (isa<FunctionType>(ArgTy) && isSizeof) {
378 // alignof(function) is allowed.
379 Diag(OpLoc, diag::ext_sizeof_function_type);
Steve Naroffdf7855b2007-02-21 23:46:25 +0000380 return new IntegerLiteral(/*1*/);
Chris Lattner6531c102007-01-23 22:29:49 +0000381 } else if (ArgTy->isVoidType()) {
382 Diag(OpLoc, diag::ext_sizeof_void_type, isSizeof ? "sizeof" : "__alignof");
383 } else if (ArgTy->isIncompleteType()) {
384 std::string TypeName;
385 ArgTy->getAsString(TypeName);
386 Diag(OpLoc, isSizeof ? diag::err_sizeof_incomplete_type :
387 diag::err_alignof_incomplete_type, TypeName);
Steve Naroffdf7855b2007-02-21 23:46:25 +0000388 return new IntegerLiteral(/*0*/);
Chris Lattner6531c102007-01-23 22:29:49 +0000389 }
390
391 return new SizeOfAlignOfTypeExpr(isSizeof, ArgTy);
Chris Lattnere168f762006-11-10 05:29:30 +0000392}
393
394
395Action::ExprResult Sema::ParsePostfixUnaryOp(SourceLocation OpLoc,
396 tok::TokenKind Kind,
397 ExprTy *Input) {
398 UnaryOperator::Opcode Opc;
399 switch (Kind) {
400 default: assert(0 && "Unknown unary op!");
401 case tok::plusplus: Opc = UnaryOperator::PostInc; break;
402 case tok::minusminus: Opc = UnaryOperator::PostDec; break;
403 }
404
405 return new UnaryOperator((Expr*)Input, Opc);
406}
407
408Action::ExprResult Sema::
409ParseArraySubscriptExpr(ExprTy *Base, SourceLocation LLoc,
410 ExprTy *Idx, SourceLocation RLoc) {
411 return new ArraySubscriptExpr((Expr*)Base, (Expr*)Idx);
412}
413
414Action::ExprResult Sema::
415ParseMemberReferenceExpr(ExprTy *Base, SourceLocation OpLoc,
416 tok::TokenKind OpKind, SourceLocation MemberLoc,
417 IdentifierInfo &Member) {
418 Decl *MemberDecl = 0;
419 // TODO: Look up MemberDecl.
420 return new MemberExpr((Expr*)Base, OpKind == tok::arrow, MemberDecl);
421}
422
423/// ParseCallExpr - Handle a call to Fn with the specified array of arguments.
424/// This provides the location of the left/right parens and a list of comma
425/// locations.
426Action::ExprResult Sema::
427ParseCallExpr(ExprTy *Fn, SourceLocation LParenLoc,
428 ExprTy **Args, unsigned NumArgs,
429 SourceLocation *CommaLocs, SourceLocation RParenLoc) {
430 return new CallExpr((Expr*)Fn, (Expr**)Args, NumArgs);
431}
432
433Action::ExprResult Sema::
434ParseCastExpr(SourceLocation LParenLoc, TypeTy *Ty,
435 SourceLocation RParenLoc, ExprTy *Op) {
Chris Lattner0d8b1a12006-11-20 04:34:45 +0000436 // If error parsing type, ignore.
437 if (Ty == 0) return true;
438 return new CastExpr(TypeRef::getFromOpaquePtr(Ty), (Expr*)Op);
Chris Lattnere168f762006-11-10 05:29:30 +0000439}
440
441
442
443// Binary Operators. 'Tok' is the token for the operator.
444Action::ExprResult Sema::ParseBinOp(SourceLocation TokLoc, tok::TokenKind Kind,
445 ExprTy *LHS, ExprTy *RHS) {
446 BinaryOperator::Opcode Opc;
447 switch (Kind) {
448 default: assert(0 && "Unknown binop!");
449 case tok::star: Opc = BinaryOperator::Mul; break;
450 case tok::slash: Opc = BinaryOperator::Div; break;
451 case tok::percent: Opc = BinaryOperator::Rem; break;
452 case tok::plus: Opc = BinaryOperator::Add; break;
453 case tok::minus: Opc = BinaryOperator::Sub; break;
454 case tok::lessless: Opc = BinaryOperator::Shl; break;
455 case tok::greatergreater: Opc = BinaryOperator::Shr; break;
456 case tok::lessequal: Opc = BinaryOperator::LE; break;
457 case tok::less: Opc = BinaryOperator::LT; break;
458 case tok::greaterequal: Opc = BinaryOperator::GE; break;
459 case tok::greater: Opc = BinaryOperator::GT; break;
460 case tok::exclaimequal: Opc = BinaryOperator::NE; break;
461 case tok::equalequal: Opc = BinaryOperator::EQ; break;
462 case tok::amp: Opc = BinaryOperator::And; break;
463 case tok::caret: Opc = BinaryOperator::Xor; break;
464 case tok::pipe: Opc = BinaryOperator::Or; break;
465 case tok::ampamp: Opc = BinaryOperator::LAnd; break;
466 case tok::pipepipe: Opc = BinaryOperator::LOr; break;
467 case tok::equal: Opc = BinaryOperator::Assign; break;
468 case tok::starequal: Opc = BinaryOperator::MulAssign; break;
469 case tok::slashequal: Opc = BinaryOperator::DivAssign; break;
470 case tok::percentequal: Opc = BinaryOperator::RemAssign; break;
471 case tok::plusequal: Opc = BinaryOperator::AddAssign; break;
472 case tok::minusequal: Opc = BinaryOperator::SubAssign; break;
473 case tok::lesslessequal: Opc = BinaryOperator::ShlAssign; break;
474 case tok::greatergreaterequal: Opc = BinaryOperator::ShrAssign; break;
475 case tok::ampequal: Opc = BinaryOperator::AndAssign; break;
476 case tok::caretequal: Opc = BinaryOperator::XorAssign; break;
477 case tok::pipeequal: Opc = BinaryOperator::OrAssign; break;
478 case tok::comma: Opc = BinaryOperator::Comma; break;
479 }
480
481 return new BinaryOperator((Expr*)LHS, (Expr*)RHS, Opc);
482}
483
484/// ParseConditionalOp - Parse a ?: operation. Note that 'LHS' may be null
485/// in the case of a the GNU conditional expr extension.
486Action::ExprResult Sema::ParseConditionalOp(SourceLocation QuestionLoc,
487 SourceLocation ColonLoc,
488 ExprTy *Cond, ExprTy *LHS,
489 ExprTy *RHS) {
490 return new ConditionalOperator((Expr*)Cond, (Expr*)LHS, (Expr*)RHS);
491}
492