 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
85.1% |
370 / 435 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
100.0% |
435 / 435 |
| |
|
Line Coverage: |
90.2% |
505 / 560 |
| |
 |
|
 |
1 : //===--- ParseExpr.cpp - Expression Parsing -------------------------------===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 : //
10 : // This file implements the Expression parsing implementation. Expressions in
11 : // C99 basically consist of a bunch of binary operators with unary operators and
12 : // other random stuff at the leaves.
13 : //
14 : // In the C99 grammar, these unary operators bind tightest and are represented
15 : // as the 'cast-expression' production. Everything else is either a binary
16 : // operator (e.g. '/') or a ternary operator ("?:"). The unary leaves are
17 : // handled by ParseCastExpression, the higher level pieces are handled by
18 : // ParseBinaryExpression.
19 : //
20 : //===----------------------------------------------------------------------===//
21 :
22 : #include "clang/Parse/Parser.h"
23 : #include "clang/Parse/DeclSpec.h"
24 : #include "clang/Parse/Scope.h"
25 : #include "clang/Parse/Template.h"
26 : #include "clang/Basic/PrettyStackTrace.h"
27 : #include "RAIIObjectsForParser.h"
28 : #include "llvm/ADT/SmallVector.h"
29 : #include "llvm/ADT/SmallString.h"
30 : using namespace clang;
31 :
32 : /// PrecedenceLevels - These are precedences for the binary/ternary operators in
33 : /// the C99 grammar. These have been named to relate with the C99 grammar
34 : /// productions. Low precedences numbers bind more weakly than high numbers.
35 : namespace prec {
36 : enum Level {
37 : Unknown = 0, // Not binary operator.
38 : Comma = 1, // ,
39 : Assignment = 2, // =, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=, |=
40 : Conditional = 3, // ?
41 : LogicalOr = 4, // ||
42 : LogicalAnd = 5, // &&
43 : InclusiveOr = 6, // |
44 : ExclusiveOr = 7, // ^
45 : And = 8, // &
46 : Equality = 9, // ==, !=
47 : Relational = 10, // >=, <=, >, <
48 : Shift = 11, // <<, >>
49 : Additive = 12, // -, +
50 : Multiplicative = 13, // *, /, %
51 : PointerToMember = 14 // .*, ->*
52 : };
53 : }
54 :
55 :
56 : /// getBinOpPrecedence - Return the precedence of the specified binary operator
57 : /// token. This returns:
58 : ///
59 : static prec::Level getBinOpPrecedence(tok::TokenKind Kind,
60 : bool GreaterThanIsOperator,
61 78675: bool CPlusPlus0x) {
610: branch 0 taken
23: branch 1 taken
60213: branch 2 taken
7778: branch 3 taken
3852: branch 4 taken
1054: branch 5 taken
47: branch 6 taken
70: branch 7 taken
200: branch 8 taken
37: branch 9 taken
247: branch 10 taken
1498: branch 11 taken
439: branch 12 taken
320: branch 13 taken
1642: branch 14 taken
565: branch 15 taken
80: branch 16 taken
62 78675: switch (Kind) {
63 : case tok::greater:
64 : // C++ [temp.names]p3:
65 : // [...] When parsing a template-argument-list, the first
66 : // non-nested > is taken as the ending delimiter rather than a
67 : // greater-than operator. [...]
159: branch 0 taken
451: branch 1 taken
68 610: if (GreaterThanIsOperator)
69 159: return prec::Relational;
70 451: return prec::Unknown;
71 :
72 : case tok::greatergreater:
73 : // C++0x [temp.names]p3:
74 : //
75 : // [...] Similarly, the first non-nested >> is treated as two
76 : // consecutive but distinct > tokens, the first of which is
77 : // taken as the end of the template-argument-list and completes
78 : // the template-id. [...]
4: branch 0 taken
19: branch 1 taken
3: branch 2 taken
1: branch 3 taken
79 23: if (GreaterThanIsOperator || !CPlusPlus0x)
80 22: return prec::Shift;
81 1: return prec::Unknown;
82 :
83 60213: default: return prec::Unknown;
84 7778: case tok::comma: return prec::Comma;
85 : case tok::equal:
86 : case tok::starequal:
87 : case tok::slashequal:
88 : case tok::percentequal:
89 : case tok::plusequal:
90 : case tok::minusequal:
91 : case tok::lesslessequal:
92 : case tok::greatergreaterequal:
93 : case tok::ampequal:
94 : case tok::caretequal:
95 3852: case tok::pipeequal: return prec::Assignment;
96 1054: case tok::question: return prec::Conditional;
97 47: case tok::pipepipe: return prec::LogicalOr;
98 70: case tok::ampamp: return prec::LogicalAnd;
99 200: case tok::pipe: return prec::InclusiveOr;
100 37: case tok::caret: return prec::ExclusiveOr;
101 247: case tok::amp: return prec::And;
102 : case tok::exclaimequal:
103 1498: case tok::equalequal: return prec::Equality;
104 : case tok::lessequal:
105 : case tok::less:
106 439: case tok::greaterequal: return prec::Relational;
107 320: case tok::lessless: return prec::Shift;
108 : case tok::plus:
109 1642: case tok::minus: return prec::Additive;
110 : case tok::percent:
111 : case tok::slash:
112 565: case tok::star: return prec::Multiplicative;
113 : case tok::periodstar:
114 80: case tok::arrowstar: return prec::PointerToMember;
115 : }
116 : }
117 :
118 :
119 : /// ParseExpression - Simple precedence-based parser for binary/ternary
120 : /// operators.
121 : ///
122 : /// Note: we diverge from the C99 grammar when parsing the assignment-expression
123 : /// production. C99 specifies that the LHS of an assignment operator should be
124 : /// parsed as a unary-expression, but consistency dictates that it be a
125 : /// conditional-expession. In practice, the important thing here is that the
126 : /// LHS of an assignment has to be an l-value, which productions between
127 : /// unary-expression and conditional-expression don't produce. Because we want
128 : /// consistency, we parse the LHS as a conditional-expression, then check for
129 : /// l-value-ness in semantic analysis stages.
130 : ///
131 : /// pm-expression: [C++ 5.5]
132 : /// cast-expression
133 : /// pm-expression '.*' cast-expression
134 : /// pm-expression '->*' cast-expression
135 : ///
136 : /// multiplicative-expression: [C99 6.5.5]
137 : /// Note: in C++, apply pm-expression instead of cast-expression
138 : /// cast-expression
139 : /// multiplicative-expression '*' cast-expression
140 : /// multiplicative-expression '/' cast-expression
141 : /// multiplicative-expression '%' cast-expression
142 : ///
143 : /// additive-expression: [C99 6.5.6]
144 : /// multiplicative-expression
145 : /// additive-expression '+' multiplicative-expression
146 : /// additive-expression '-' multiplicative-expression
147 : ///
148 : /// shift-expression: [C99 6.5.7]
149 : /// additive-expression
150 : /// shift-expression '<<' additive-expression
151 : /// shift-expression '>>' additive-expression
152 : ///
153 : /// relational-expression: [C99 6.5.8]
154 : /// shift-expression
155 : /// relational-expression '<' shift-expression
156 : /// relational-expression '>' shift-expression
157 : /// relational-expression '<=' shift-expression
158 : /// relational-expression '>=' shift-expression
159 : ///
160 : /// equality-expression: [C99 6.5.9]
161 : /// relational-expression
162 : /// equality-expression '==' relational-expression
163 : /// equality-expression '!=' relational-expression
164 : ///
165 : /// AND-expression: [C99 6.5.10]
166 : /// equality-expression
167 : /// AND-expression '&' equality-expression
168 : ///
169 : /// exclusive-OR-expression: [C99 6.5.11]
170 : /// AND-expression
171 : /// exclusive-OR-expression '^' AND-expression
172 : ///
173 : /// inclusive-OR-expression: [C99 6.5.12]
174 : /// exclusive-OR-expression
175 : /// inclusive-OR-expression '|' exclusive-OR-expression
176 : ///
177 : /// logical-AND-expression: [C99 6.5.13]
178 : /// inclusive-OR-expression
179 : /// logical-AND-expression '&&' inclusive-OR-expression
180 : ///
181 : /// logical-OR-expression: [C99 6.5.14]
182 : /// logical-AND-expression
183 : /// logical-OR-expression '||' logical-AND-expression
184 : ///
185 : /// conditional-expression: [C99 6.5.15]
186 : /// logical-OR-expression
187 : /// logical-OR-expression '?' expression ':' conditional-expression
188 : /// [GNU] logical-OR-expression '?' ':' conditional-expression
189 : /// [C++] the third operand is an assignment-expression
190 : ///
191 : /// assignment-expression: [C99 6.5.16]
192 : /// conditional-expression
193 : /// unary-expression assignment-operator assignment-expression
194 : /// [C++] throw-expression [C++ 15]
195 : ///
196 : /// assignment-operator: one of
197 : /// = *= /= %= += -= <<= >>= &= ^= |=
198 : ///
199 : /// expression: [C99 6.5.17]
200 : /// assignment-expression
201 : /// expression ',' assignment-expression
202 : ///
203 22537: Parser::OwningExprResult Parser::ParseExpression() {
204 22537: OwningExprResult LHS(ParseAssignmentExpression());
750: branch 1 taken
21787: branch 2 taken
205 22537: if (LHS.isInvalid()) return move(LHS);
206 :
207 21787: return ParseRHSOfBinaryExpression(move(LHS), prec::Comma);
208 : }
209 :
210 : /// This routine is called when the '@' is seen and consumed.
211 : /// Current token is an Identifier and is not a 'try'. This
212 : /// routine is necessary to disambiguate @try-statement from,
213 : /// for example, @encode-expression.
214 : ///
215 : Parser::OwningExprResult
216 4: Parser::ParseExpressionWithLeadingAt(SourceLocation AtLoc) {
217 4: OwningExprResult LHS(ParseObjCAtExpression(AtLoc));
0: branch 1 not taken
4: branch 2 taken
218 4: if (LHS.isInvalid()) return move(LHS);
219 :
220 4: return ParseRHSOfBinaryExpression(move(LHS), prec::Comma);
221 : }
222 :
223 : /// This routine is called when a leading '__extension__' is seen and
224 : /// consumed. This is necessary because the token gets consumed in the
225 : /// process of disambiguating between an expression and a declaration.
226 : Parser::OwningExprResult
227 6: Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) {
228 6: OwningExprResult LHS(Actions, true);
229 : {
230 : // Silence extension warnings in the sub-expression
231 6: ExtensionRAIIObject O(Diags);
232 :
233 6: LHS = ParseCastExpression(false);
2: branch 1 taken
4: branch 2 taken
4: branch 8 taken
2: branch 9 taken
234 6: if (LHS.isInvalid()) return move(LHS);
235 : }
236 :
237 : LHS = Actions.ActOnUnaryOp(CurScope, ExtLoc, tok::kw___extension__,
238 4: move(LHS));
0: branch 1 not taken
4: branch 2 taken
239 4: if (LHS.isInvalid()) return move(LHS);
240 :
241 4: return ParseRHSOfBinaryExpression(move(LHS), prec::Comma);
242 : }
243 :
244 : /// ParseAssignmentExpression - Parse an expr that doesn't include commas.
245 : ///
246 44284: Parser::OwningExprResult Parser::ParseAssignmentExpression() {
2: branch 1 taken
44282: branch 2 taken
247 44284: if (Tok.is(tok::code_completion)) {
248 2: Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Expression);
249 2: ConsumeToken();
250 : }
251 :
40: branch 1 taken
44244: branch 2 taken
252 44284: if (Tok.is(tok::kw_throw))
253 40: return ParseThrowExpression();
254 :
255 44244: OwningExprResult LHS(ParseCastExpression(false));
720: branch 1 taken
43524: branch 2 taken
256 44244: if (LHS.isInvalid()) return move(LHS);
257 :
258 43524: return ParseRHSOfBinaryExpression(move(LHS), prec::Assignment);
259 : }
260 :
261 : /// ParseAssignmentExprWithObjCMessageExprStart - Parse an assignment expression
262 : /// where part of an objc message send has already been parsed. In this case
263 : /// LBracLoc indicates the location of the '[' of the message send, and either
264 : /// ReceiverName or ReceiverExpr is non-null indicating the receiver of the
265 : /// message.
266 : ///
267 : /// Since this handles full assignment-expression's, it handles postfix
268 : /// expressions and other binary operators for these expressions as well.
269 : Parser::OwningExprResult
270 : Parser::ParseAssignmentExprWithObjCMessageExprStart(SourceLocation LBracLoc,
271 : SourceLocation NameLoc,
272 : IdentifierInfo *ReceiverName,
273 26: ExprArg ReceiverExpr) {
274 : OwningExprResult R(ParseObjCMessageExpressionBody(LBracLoc, NameLoc,
275 : ReceiverName,
276 26: move(ReceiverExpr)));
0: branch 1 not taken
26: branch 2 taken
277 26: if (R.isInvalid()) return move(R);
278 26: R = ParsePostfixExpressionSuffix(move(R));
0: branch 1 not taken
26: branch 2 taken
279 26: if (R.isInvalid()) return move(R);
280 26: return ParseRHSOfBinaryExpression(move(R), prec::Assignment);
281 : }
282 :
283 :
284 2620: Parser::OwningExprResult Parser::ParseConstantExpression() {
285 : // C++ [basic.def.odr]p2:
286 : // An expression is potentially evaluated unless it appears where an
287 : // integral constant expression is required (see 5.19) [...].
288 : EnterExpressionEvaluationContext Unevaluated(Actions,
289 2620: Action::Unevaluated);
290 :
291 2620: OwningExprResult LHS(ParseCastExpression(false));
12: branch 1 taken
2608: branch 2 taken
292 2620: if (LHS.isInvalid()) return move(LHS);
293 :
294 2608: return ParseRHSOfBinaryExpression(move(LHS), prec::Conditional);
295 : }
296 :
297 : /// ParseRHSOfBinaryExpression - Parse a binary expression that starts with
298 : /// LHS and has a precedence of at least MinPrec.
299 : Parser::OwningExprResult
300 68338: Parser::ParseRHSOfBinaryExpression(OwningExprResult LHS, unsigned MinPrec) {
301 : unsigned NextTokPrec = getBinOpPrecedence(Tok.getKind(),
302 : GreaterThanIsOperator,
303 68338: getLang().CPlusPlus0x);
304 68338: SourceLocation ColonLoc;
305 :
9952: branch 1 taken
37: branch 2 taken
9952: branch 4 taken
37: branch 5 taken
306 9989: while (1) {
307 : // If this token has a lower precedence than we are allowed to parse (e.g.
308 : // because we are called recursively, or because the token is not a binop),
309 : // then we are done!
68301: branch 0 taken
9989: branch 1 taken
310 78290: if (NextTokPrec < MinPrec)
311 68301: return move(LHS);
312 :
313 : // Consume the operator, saving the operator token for error reporting.
314 9989: Token OpToken = Tok;
315 9989: ConsumeToken();
316 :
317 : // Special case handling for the ternary operator.
318 9989: OwningExprResult TernaryMiddle(Actions, true);
1011: branch 0 taken
8978: branch 1 taken
319 9989: if (NextTokPrec == prec::Conditional) {
985: branch 1 taken
26: branch 2 taken
320 1011: if (Tok.isNot(tok::colon)) {
321 : // Don't parse FOO:BAR as if it were a typo for FOO::BAR.
322 985: ColonProtectionRAIIObject X(*this);
323 :
324 : // Handle this production specially:
325 : // logical-OR-expression '?' expression ':' conditional-expression
326 : // In particular, the RHS of the '?' is 'expression', not
327 : // 'logical-OR-expression' as we might expect.
328 985: TernaryMiddle = ParseExpression();
0: branch 1 not taken
985: branch 2 taken
329 985: if (TernaryMiddle.isInvalid())
985: branch 5 taken
0: branch 6 not taken
330 0: return move(TernaryMiddle);
331 : } else {
332 : // Special case handling of "X ? Y : Z" where Y is empty:
333 : // logical-OR-expression '?' ':' conditional-expression [GNU]
334 26: TernaryMiddle = 0;
335 26: Diag(Tok, diag::ext_gnu_conditional_expr);
336 : }
337 :
0: branch 1 not taken
1011: branch 2 taken
338 1011: if (Tok.isNot(tok::colon)) {
339 0: Diag(Tok, diag::err_expected_colon);
340 0: Diag(OpToken, diag::note_matching) << "?";
341 0: return ExprError();
342 : }
343 :
344 : // Eat the colon.
345 1011: ColonLoc = ConsumeToken();
346 : }
347 :
348 : // Parse another leaf here for the RHS of the operator.
349 : // ParseCastExpression works here because all RHS expressions in C have it
350 : // as a prefix, at least. However, in C++, an assignment-expression could
351 : // be a throw-expression, which is not a valid cast-expression.
352 : // Therefore we need some special-casing here.
353 : // Also note that the third operand of the conditional operator is
354 : // an assignment-expression in C++.
355 9989: OwningExprResult RHS(Actions);
2347: branch 1 taken
7642: branch 2 taken
1091: branch 3 taken
1256: branch 4 taken
1091: branch 5 taken
8898: branch 6 taken
356 9989: if (getLang().CPlusPlus && NextTokPrec <= prec::Conditional)
357 1091: RHS = ParseAssignmentExpression();
358 : else
359 8898: RHS = ParseCastExpression(false);
30: branch 1 taken
9959: branch 2 taken
360 9989: if (RHS.isInvalid())
361 30: return move(RHS);
362 :
363 : // Remember the precedence of this operator and get the precedence of the
364 : // operator immediately to the right of the RHS.
365 9959: unsigned ThisPrec = NextTokPrec;
366 : NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator,
367 9959: getLang().CPlusPlus0x);
368 :
369 : // Assignment and conditional expressions are right-associative.
370 : bool isRightAssoc = ThisPrec == prec::Conditional ||
8948: branch 0 taken
1011: branch 1 taken
3808: branch 2 taken
5140: branch 3 taken
371 9959: ThisPrec == prec::Assignment;
372 :
373 : // Get the precedence of the operator to the right of the RHS. If it binds
374 : // more tightly with RHS than we do, evaluate it completely first.
9591: branch 0 taken
368: branch 1 taken
529: branch 2 taken
9062: branch 3 taken
17: branch 4 taken
512: branch 5 taken
375 9959: if (ThisPrec < NextTokPrec ||
376 : (ThisPrec == NextTokPrec && isRightAssoc)) {
377 : // If this is left-associative, only parse things on the RHS that bind
378 : // more tightly than the current operator. If it is left-associative, it
379 : // is okay, to bind exactly as tightly. For example, compile A=B=C=D as
380 : // A=(B=(C=D)), where each paren is a level of recursion here.
381 : // The function takes ownership of the RHS.
382 385: RHS = ParseRHSOfBinaryExpression(move(RHS), ThisPrec + !isRightAssoc);
7: branch 1 taken
378: branch 2 taken
383 385: if (RHS.isInvalid())
384 7: return move(RHS);
385 :
386 : NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator,
387 378: getLang().CPlusPlus0x);
388 : }
0: branch 0 not taken
9952: branch 1 taken
389 9952: assert(NextTokPrec <= ThisPrec && "Recursion didn't work!");
390 :
9949: branch 1 taken
3: branch 2 taken
391 9952: if (!LHS.isInvalid()) {
392 : // Combine the LHS and RHS into the LHS (e.g. build AST).
8939: branch 1 taken
1010: branch 2 taken
393 9949: if (TernaryMiddle.isInvalid()) {
394 : // If we're using '>>' as an operator within a template
395 : // argument list (in C++98), suggest the addition of
396 : // parentheses so that the code remains well-formed in C++0x.
24: branch 0 taken
8915: branch 1 taken
3: branch 3 taken
21: branch 4 taken
3: branch 5 taken
8936: branch 6 taken
397 8939: if (!GreaterThanIsOperator && OpToken.is(tok::greatergreater))
398 : SuggestParentheses(OpToken.getLocation(),
399 : diag::warn_cxx0x_right_shift_in_template_arg,
400 : SourceRange(Actions.getExprRange(LHS.get()).getBegin(),
401 3: Actions.getExprRange(RHS.get()).getEnd()));
402 :
403 : LHS = Actions.ActOnBinOp(CurScope, OpToken.getLocation(),
404 8939: OpToken.getKind(), move(LHS), move(RHS));
405 : } else
406 : LHS = Actions.ActOnConditionalOp(OpToken.getLocation(), ColonLoc,
407 : move(LHS), move(TernaryMiddle),
408 1010: move(RHS));
409 : }
410 : }
411 : }
412 :
413 : /// ParseCastExpression - Parse a cast-expression, or, if isUnaryExpression is
414 : /// true, parse a unary-expression. isAddressOfOperand exists because an
415 : /// id-expression that is the operand of address-of gets special treatment
416 : /// due to member pointers.
417 : ///
418 : Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
419 : bool isAddressOfOperand,
420 65481: TypeTy *TypeOfCast) {
421 : bool NotCastExpr;
422 : OwningExprResult Res = ParseCastExpression(isUnaryExpression,
423 : isAddressOfOperand,
424 : NotCastExpr,
425 65481: TypeOfCast);
26: branch 0 taken
65455: branch 1 taken
426 65481: if (NotCastExpr)
427 26: Diag(Tok, diag::err_expected_expression);
428 65481: return move(Res);
429 : }
430 :
431 : /// ParseCastExpression - Parse a cast-expression, or, if isUnaryExpression is
432 : /// true, parse a unary-expression. isAddressOfOperand exists because an
433 : /// id-expression that is the operand of address-of gets special treatment
434 : /// due to member pointers. NotCastExpr is set to true if the token is not the
435 : /// start of a cast-expression, and no diagnostic is emitted in this case.
436 : ///
437 : /// cast-expression: [C99 6.5.4]
438 : /// unary-expression
439 : /// '(' type-name ')' cast-expression
440 : ///
441 : /// unary-expression: [C99 6.5.3]
442 : /// postfix-expression
443 : /// '++' unary-expression
444 : /// '--' unary-expression
445 : /// unary-operator cast-expression
446 : /// 'sizeof' unary-expression
447 : /// 'sizeof' '(' type-name ')'
448 : /// [GNU] '__alignof' unary-expression
449 : /// [GNU] '__alignof' '(' type-name ')'
450 : /// [C++0x] 'alignof' '(' type-id ')'
451 : /// [GNU] '&&' identifier
452 : /// [C++] new-expression
453 : /// [C++] delete-expression
454 : ///
455 : /// unary-operator: one of
456 : /// '&' '*' '+' '-' '~' '!'
457 : /// [GNU] '__extension__' '__real' '__imag'
458 : ///
459 : /// primary-expression: [C99 6.5.1]
460 : /// [C99] identifier
461 : /// [C++] id-expression
462 : /// constant
463 : /// string-literal
464 : /// [C++] boolean-literal [C++ 2.13.5]
465 : /// [C++0x] 'nullptr' [C++0x 2.14.7]
466 : /// '(' expression ')'
467 : /// '__func__' [C99 6.4.2.2]
468 : /// [GNU] '__FUNCTION__'
469 : /// [GNU] '__PRETTY_FUNCTION__'
470 : /// [GNU] '(' compound-statement ')'
471 : /// [GNU] '__builtin_va_arg' '(' assignment-expression ',' type-name ')'
472 : /// [GNU] '__builtin_offsetof' '(' type-name ',' offsetof-member-designator')'
473 : /// [GNU] '__builtin_choose_expr' '(' assign-expr ',' assign-expr ','
474 : /// assign-expr ')'
475 : /// [GNU] '__builtin_types_compatible_p' '(' type-name ',' type-name ')'
476 : /// [GNU] '__null'
477 : /// [OBJC] '[' objc-message-expr ']'
478 : /// [OBJC] '@selector' '(' objc-selector-arg ')'
479 : /// [OBJC] '@protocol' '(' identifier ')'
480 : /// [OBJC] '@encode' '(' type-name ')'
481 : /// [OBJC] objc-string-literal
482 : /// [C++] simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3]
483 : /// [C++] typename-specifier '(' expression-list[opt] ')' [TODO]
484 : /// [C++] 'const_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]
485 : /// [C++] 'dynamic_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]
486 : /// [C++] 'reinterpret_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]
487 : /// [C++] 'static_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]
488 : /// [C++] 'typeid' '(' expression ')' [C++ 5.2p1]
489 : /// [C++] 'typeid' '(' type-id ')' [C++ 5.2p1]
490 : /// [C++] 'this' [C++ 9.3.2]
491 : /// [G++] unary-type-trait '(' type-id ')'
492 : /// [G++] binary-type-trait '(' type-id ',' type-id ')' [TODO]
493 : /// [clang] '^' block-literal
494 : ///
495 : /// constant: [C99 6.4.4]
496 : /// integer-constant
497 : /// floating-constant
498 : /// enumeration-constant -> identifier
499 : /// character-constant
500 : ///
501 : /// id-expression: [C++ 5.1]
502 : /// unqualified-id
503 : /// qualified-id [TODO]
504 : ///
505 : /// unqualified-id: [C++ 5.1]
506 : /// identifier
507 : /// operator-function-id
508 : /// conversion-function-id [TODO]
509 : /// '~' class-name [TODO]
510 : /// template-id [TODO]
511 : ///
512 : /// new-expression: [C++ 5.3.4]
513 : /// '::'[opt] 'new' new-placement[opt] new-type-id
514 : /// new-initializer[opt]
515 : /// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
516 : /// new-initializer[opt]
517 : ///
518 : /// delete-expression: [C++ 5.3.5]
519 : /// '::'[opt] 'delete' cast-expression
520 : /// '::'[opt] 'delete' '[' ']' cast-expression
521 : ///
522 : /// [GNU] unary-type-trait:
523 : /// '__has_nothrow_assign' [TODO]
524 : /// '__has_nothrow_copy' [TODO]
525 : /// '__has_nothrow_constructor' [TODO]
526 : /// '__has_trivial_assign' [TODO]
527 : /// '__has_trivial_copy' [TODO]
528 : /// '__has_trivial_constructor'
529 : /// '__has_trivial_destructor'
530 : /// '__has_virtual_destructor' [TODO]
531 : /// '__is_abstract' [TODO]
532 : /// '__is_class'
533 : /// '__is_empty' [TODO]
534 : /// '__is_enum'
535 : /// '__is_pod'
536 : /// '__is_polymorphic'
537 : /// '__is_union'
538 : ///
539 : /// [GNU] binary-type-trait:
540 : /// '__is_base_of' [TODO]
541 : ///
542 : Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
543 : bool isAddressOfOperand,
544 : bool &NotCastExpr,
545 65517: TypeTy *TypeOfCast) {
546 65517: OwningExprResult Res(Actions);
547 65517: tok::TokenKind SavedKind = Tok.getKind();
548 65517: NotCastExpr = false;
549 :
550 : // This handles all of cast-expression, unary-expression, postfix-expression,
551 : // and primary-expression. We handle them together like this for efficiency
552 : // and to simplify handling of an expression starting with a '(' token: which
553 : // may be one of a parenthesized expression, cast-expression, compound literal
554 : // expression, or statement expression.
555 : //
556 : // If the parsed tokens consist of a primary-expression, the cases below
557 : // call ParsePostfixExpressionSuffix to handle the postfix expression
558 : // suffixes. Cases that cannot be followed by postfix exprs should
559 : // return without invoking ParsePostfixExpressionSuffix.
8637: branch 0 taken
16337: branch 1 taken
141: branch 2 taken
36: branch 3 taken
29546: branch 4 taken
192: branch 5 taken
242: branch 6 taken
1211: branch 7 taken
234: branch 8 taken
18: branch 9 taken
487: branch 10 taken
1223: branch 11 taken
2275: branch 12 taken
37: branch 13 taken
623: branch 14 taken
39: branch 15 taken
252: branch 16 taken
83: branch 17 taken
80: branch 18 taken
518: branch 19 taken
532: branch 20 taken
120: branch 21 taken
11: branch 22 taken
10: branch 23 taken
113: branch 24 taken
48: branch 25 taken
180: branch 26 taken
318: branch 27 taken
264: branch 28 taken
1677: branch 29 taken
33: branch 30 taken
560 65517: switch (SavedKind) {
561 : case tok::l_paren: {
562 : // If this expression is limited to being a unary-expression, the parent can
563 : // not start a cast expression.
564 : ParenParseOption ParenExprType =
3: branch 0 taken
8634: branch 1 taken
565 8637: isUnaryExpression ? CompoundLiteral : CastExpr;
566 : TypeTy *CastTy;
567 8637: SourceLocation LParenLoc = Tok.getLocation();
568 8637: SourceLocation RParenLoc;
569 :
570 : {
571 : // The inside of the parens don't need to be a colon protected scope.
572 8637: ColonProtectionRAIIObject X(*this, false);
573 :
574 : Res = ParseParenExpression(ParenExprType, false/*stopIfCastExr*/,
575 8637: TypeOfCast, CastTy, RParenLoc);
240: branch 1 taken
8397: branch 2 taken
8397: branch 8 taken
240: branch 9 taken
576 8637: if (Res.isInvalid()) return move(Res);
577 : }
578 :
3394: branch 0 taken
64: branch 1 taken
285: branch 2 taken
4654: branch 3 taken
0: branch 4 not taken
579 8397: switch (ParenExprType) {
580 3394: case SimpleExpr: break; // Nothing else to do.
581 64: case CompoundStmt: break; // Nothing else to do.
582 : case CompoundLiteral:
583 : // We parsed '(' type-name ')' '{' ... '}'. If any suffixes of
584 : // postfix-expression exist, parse them now.
585 285: break;
586 : case CastExpr:
587 : // We have parsed the cast-expression and no postfix-expr pieces are
588 : // following.
589 4654: return move(Res);
590 : }
591 :
592 : // These can be followed by postfix-expr pieces.
593 3743: return ParsePostfixExpressionSuffix(move(Res));
594 : }
595 :
596 : // primary-expression
597 : case tok::numeric_constant:
598 : // constant: integer-constant
599 : // constant: floating-constant
600 :
601 16337: Res = Actions.ActOnNumericConstant(Tok);
602 16337: ConsumeToken();
603 :
604 : // These can be followed by postfix-expr pieces.
605 16337: return ParsePostfixExpressionSuffix(move(Res));
606 :
607 : case tok::kw_true:
608 : case tok::kw_false:
609 141: return ParseCXXBoolLiteral();
610 :
611 : case tok::kw_nullptr:
612 36: return Actions.ActOnCXXNullPtrLiteral(ConsumeToken());
613 :
614 : case tok::identifier: { // primary-expression: identifier
615 : // unqualified-id: identifier
616 : // constant: enumeration-constant
617 : // Turn a potentially qualified name into a annot_typename or
618 : // annot_cxxscope if it would be valid. This handles things like x::y, etc.
8510: branch 1 taken
21036: branch 2 taken
619 29546: if (getLang().CPlusPlus) {
620 : // Avoid the unnecessary parse-time lookup in the common case
621 : // where the syntax forbids a type.
622 8510: const Token &Next = NextToken();
8307: branch 1 taken
203: branch 2 taken
8077: branch 3 taken
230: branch 4 taken
8073: branch 6 taken
4: branch 7 taken
7930: branch 9 taken
373: branch 10 taken
1864: branch 12 taken
6066: branch 13 taken
2444: branch 14 taken
6066: branch 15 taken
623 8510: if (Next.is(tok::coloncolon) ||
624 : (!ColonIsSacred && Next.is(tok::colon)) ||
625 : Next.is(tok::less) ||
626 : Next.is(tok::l_paren)) {
627 : // If TryAnnotateTypeOrScopeToken annotates the token, tail recurse.
803: branch 1 taken
1641: branch 2 taken
628 2444: if (TryAnnotateTypeOrScopeToken())
629 803: return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
630 : }
631 : }
632 :
633 : // Consume the identifier so that we can see if it is followed by a '(' or
634 : // '.'.
635 28743: IdentifierInfo &II = *Tok.getIdentifierInfo();
636 28743: SourceLocation ILoc = ConsumeToken();
637 :
638 : // Support 'Class.property' notation. We don't use
639 : // isTokObjCMessageIdentifierReceiver(), since it allows 'super' (which is
640 : // inappropriate here).
8314: branch 1 taken
20429: branch 2 taken
399: branch 4 taken
7915: branch 5 taken
17: branch 7 taken
382: branch 8 taken
17: branch 9 taken
28726: branch 10 taken
641 28743: if (getLang().ObjC1 && Tok.is(tok::period) &&
642 : Actions.getTypeName(II, ILoc, CurScope)) {
643 17: SourceLocation DotLoc = ConsumeToken();
644 :
0: branch 1 not taken
17: branch 2 taken
645 17: if (Tok.isNot(tok::identifier)) {
646 0: Diag(Tok, diag::err_expected_property_name);
647 0: return ExprError();
648 : }
649 17: IdentifierInfo &PropertyName = *Tok.getIdentifierInfo();
650 17: SourceLocation PropertyLoc = ConsumeToken();
651 :
652 : Res = Actions.ActOnClassPropertyRefExpr(II, PropertyName,
653 17: ILoc, PropertyLoc);
654 : // These can be followed by postfix-expr pieces.
655 17: return ParsePostfixExpressionSuffix(move(Res));
656 : }
657 :
658 : // Function designators are allowed to be undeclared (C99 6.5.1p2), so we
659 : // need to know whether or not this identifier is a function designator or
660 : // not.
661 28726: UnqualifiedId Name;
662 28726: CXXScopeSpec ScopeSpec;
663 28726: Name.setIdentifier(&II, ILoc);
664 : Res = Actions.ActOnIdExpression(CurScope, ScopeSpec, Name,
665 28726: Tok.is(tok::l_paren), false);
666 : // These can be followed by postfix-expr pieces.
667 28726: return ParsePostfixExpressionSuffix(move(Res));
668 : }
669 : case tok::char_constant: // constant: character-constant
670 192: Res = Actions.ActOnCharacterConstant(Tok);
671 192: ConsumeToken();
672 : // These can be followed by postfix-expr pieces.
673 192: return ParsePostfixExpressionSuffix(move(Res));
674 : case tok::kw___func__: // primary-expression: __func__ [C99 6.4.2.2]
675 : case tok::kw___FUNCTION__: // primary-expression: __FUNCTION__ [GNU]
676 : case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU]
677 242: Res = Actions.ActOnPredefinedExpr(Tok.getLocation(), SavedKind);
678 242: ConsumeToken();
679 : // These can be followed by postfix-expr pieces.
680 242: return ParsePostfixExpressionSuffix(move(Res));
681 : case tok::string_literal: // primary-expression: string-literal
682 : case tok::wide_string_literal:
683 1211: Res = ParseStringLiteralExpression();
4: branch 1 taken
1207: branch 2 taken
684 1211: if (Res.isInvalid()) return move(Res);
685 : // This can be followed by postfix-expr pieces (e.g. "foo"[1]).
686 1207: return ParsePostfixExpressionSuffix(move(Res));
687 : case tok::kw___builtin_va_arg:
688 : case tok::kw___builtin_offsetof:
689 : case tok::kw___builtin_choose_expr:
690 : case tok::kw___builtin_types_compatible_p:
691 234: return ParseBuiltinPrimaryExpression();
692 : case tok::kw___null:
693 18: return Actions.ActOnGNUNullExpr(ConsumeToken());
694 : break;
695 : case tok::plusplus: // unary-expression: '++' unary-expression
696 : case tok::minusminus: { // unary-expression: '--' unary-expression
697 487: SourceLocation SavedLoc = ConsumeToken();
698 487: Res = ParseCastExpression(true);
486: branch 1 taken
1: branch 2 taken
699 487: if (!Res.isInvalid())
700 486: Res = Actions.ActOnUnaryOp(CurScope, SavedLoc, SavedKind, move(Res));
701 487: return move(Res);
702 : }
703 : case tok::amp: { // unary-expression: '&' cast-expression
704 : // Special treatment because of member pointers
705 1223: SourceLocation SavedLoc = ConsumeToken();
706 1223: Res = ParseCastExpression(false, true);
1217: branch 1 taken
6: branch 2 taken
707 1223: if (!Res.isInvalid())
708 1217: Res = Actions.ActOnUnaryOp(CurScope, SavedLoc, SavedKind, move(Res));
709 1223: return move(Res);
710 : }
711 :
712 : case tok::star: // unary-expression: '*' cast-expression
713 : case tok::plus: // unary-expression: '+' cast-expression
714 : case tok::minus: // unary-expression: '-' cast-expression
715 : case tok::tilde: // unary-expression: '~' cast-expression
716 : case tok::exclaim: // unary-expression: '!' cast-expression
717 : case tok::kw___real: // unary-expression: '__real' cast-expression [GNU]
718 : case tok::kw___imag: { // unary-expression: '__imag' cast-expression [GNU]
719 2275: SourceLocation SavedLoc = ConsumeToken();
720 2275: Res = ParseCastExpression(false);
2272: branch 1 taken
3: branch 2 taken
721 2275: if (!Res.isInvalid())
722 2272: Res = Actions.ActOnUnaryOp(CurScope, SavedLoc, SavedKind, move(Res));
723 2275: return move(Res);
724 : }
725 :
726 : case tok::kw___extension__:{//unary-expression:'__extension__' cast-expr [GNU]
727 : // __extension__ silences extension warnings in the subexpression.
728 37: ExtensionRAIIObject O(Diags); // Use RAII to do this.
729 37: SourceLocation SavedLoc = ConsumeToken();
730 37: Res = ParseCastExpression(false);
37: branch 1 taken
0: branch 2 not taken
731 37: if (!Res.isInvalid())
732 37: Res = Actions.ActOnUnaryOp(CurScope, SavedLoc, SavedKind, move(Res));
733 37: return move(Res);
734 : }
735 : case tok::kw_sizeof: // unary-expression: 'sizeof' unary-expression
736 : // unary-expression: 'sizeof' '(' type-name ')'
737 : case tok::kw_alignof:
738 : case tok::kw___alignof: // unary-expression: '__alignof' unary-expression
739 : // unary-expression: '__alignof' '(' type-name ')'
740 : // unary-expression: 'alignof' '(' type-id ')'
741 623: return ParseSizeofAlignofExpression();
742 : case tok::ampamp: { // unary-expression: '&&' identifier
743 39: SourceLocation AmpAmpLoc = ConsumeToken();
0: branch 1 not taken
39: branch 2 taken
744 39: if (Tok.isNot(tok::identifier))
745 0: return ExprError(Diag(Tok, diag::err_expected_ident));
746 :
747 39: Diag(AmpAmpLoc, diag::ext_gnu_address_of_label);
748 : Res = Actions.ActOnAddrLabel(AmpAmpLoc, Tok.getLocation(),
749 39: Tok.getIdentifierInfo());
750 39: ConsumeToken();
751 39: return move(Res);
752 : }
753 : case tok::kw_const_cast:
754 : case tok::kw_dynamic_cast:
755 : case tok::kw_reinterpret_cast:
756 : case tok::kw_static_cast:
757 252: Res = ParseCXXCasts();
758 : // These can be followed by postfix-expr pieces.
759 252: return ParsePostfixExpressionSuffix(move(Res));
760 : case tok::kw_typeid:
761 83: Res = ParseCXXTypeid();
762 : // This can be followed by postfix-expr pieces.
763 83: return ParsePostfixExpressionSuffix(move(Res));
764 : case tok::kw_this:
765 80: Res = ParseCXXThis();
766 : // This can be followed by postfix-expr pieces.
767 80: return ParsePostfixExpressionSuffix(move(Res));
768 :
769 : case tok::kw_char:
770 : case tok::kw_wchar_t:
771 : case tok::kw_char16_t:
772 : case tok::kw_char32_t:
773 : case tok::kw_bool:
774 : case tok::kw_short:
775 : case tok::kw_int:
776 : case tok::kw_long:
777 : case tok::kw_signed:
778 : case tok::kw_unsigned:
779 : case tok::kw_float:
780 : case tok::kw_double:
781 : case tok::kw_void:
782 : case tok::kw_typename:
783 : case tok::kw_typeof:
784 : case tok::kw___vector:
785 : case tok::annot_typename: {
0: branch 1 not taken
518: branch 2 taken
786 518: if (!getLang().CPlusPlus) {
787 0: Diag(Tok, diag::err_expected_expression);
788 0: return ExprError();
789 : }
790 :
3: branch 0 taken
515: branch 1 taken
791 518: if (SavedKind == tok::kw_typename) {
792 : // postfix-expression: typename-specifier '(' expression-list[opt] ')'
1: branch 1 taken
2: branch 2 taken
793 3: if (!TryAnnotateTypeOrScopeToken())
794 1: return ExprError();
795 : }
796 :
797 : // postfix-expression: simple-type-specifier '(' expression-list[opt] ')'
798 : //
799 517: DeclSpec DS;
800 517: ParseCXXSimpleTypeSpecifier(DS);
2: branch 1 taken
515: branch 2 taken
801 517: if (Tok.isNot(tok::l_paren))
802 : return ExprError(Diag(Tok, diag::err_expected_lparen_after_type)
803 2: << DS.getSourceRange());
804 :
805 515: Res = ParseCXXTypeConstructExpression(DS);
806 : // This can be followed by postfix-expr pieces.
807 515: return ParsePostfixExpressionSuffix(move(Res));
808 : }
809 :
810 : case tok::annot_cxxscope: { // [C++] id-expression: qualified-id
811 532: Token Next = NextToken();
11: branch 1 taken
521: branch 2 taken
812 532: if (Next.is(tok::annot_template_id)) {
813 : TemplateIdAnnotation *TemplateId
814 11: = static_cast<TemplateIdAnnotation *>(Next.getAnnotationValue());
1: branch 0 taken
10: branch 1 taken
815 11: if (TemplateId->Kind == TNK_Type_template) {
816 : // We have a qualified template-id that we know refers to a
817 : // type, translate it into a type and continue parsing as a
818 : // cast expression.
819 1: CXXScopeSpec SS;
820 1: ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
821 1: AnnotateTemplateIdTokenAsType(&SS);
822 : return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
823 1: NotCastExpr, TypeOfCast);
824 : }
825 : }
826 :
827 : // Parse as an id-expression.
828 531: Res = ParseCXXIdExpression(isAddressOfOperand);
829 531: return ParsePostfixExpressionSuffix(move(Res));
830 : }
831 :
832 : case tok::annot_template_id: { // [C++] template-id
833 : TemplateIdAnnotation *TemplateId
834 120: = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
1: branch 0 taken
119: branch 1 taken
835 120: if (TemplateId->Kind == TNK_Type_template) {
836 : // We have a template-id that we know refers to a type,
837 : // translate it into a type and continue parsing as a cast
838 : // expression.
839 1: AnnotateTemplateIdTokenAsType();
840 : return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
841 1: NotCastExpr, TypeOfCast);
842 : }
843 :
844 : // Fall through to treat the template-id as an id-expression.
845 : }
846 :
847 : case tok::kw_operator: // [C++] id-expression: operator/conversion-function-id
848 130: Res = ParseCXXIdExpression(isAddressOfOperand);
849 130: return ParsePostfixExpressionSuffix(move(Res));
850 :
851 : case tok::coloncolon: {
852 : // ::foo::bar -> global qualified name etc. If TryAnnotateTypeOrScopeToken
853 : // annotates the token, tail recurse.
6: branch 1 taken
4: branch 2 taken
854 10: if (TryAnnotateTypeOrScopeToken())
855 6: return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
856 :
857 : // ::new -> [C++] new-expression
858 : // ::delete -> [C++] delete-expression
859 4: SourceLocation CCLoc = ConsumeToken();
2: branch 1 taken
2: branch 2 taken
860 4: if (Tok.is(tok::kw_new))
861 2: return ParseCXXNewExpression(true, CCLoc);
2: branch 1 taken
0: branch 2 not taken
862 2: if (Tok.is(tok::kw_delete))
863 2: return ParseCXXDeleteExpression(true, CCLoc);
864 :
865 : // This is not a type name or scope specifier, it is an invalid expression.
866 0: Diag(CCLoc, diag::err_expected_expression);
867 0: return ExprError();
868 : }
869 :
870 : case tok::kw_new: // [C++] new-expression
871 113: return ParseCXXNewExpression(false, Tok.getLocation());
872 :
873 : case tok::kw_delete: // [C++] delete-expression
874 48: return ParseCXXDeleteExpression(false, Tok.getLocation());
875 :
876 : case tok::kw___is_pod: // [GNU] unary-type-trait
877 : case tok::kw___is_class:
878 : case tok::kw___is_enum:
879 : case tok::kw___is_union:
880 : case tok::kw___is_empty:
881 : case tok::kw___is_polymorphic:
882 : case tok::kw___is_abstract:
883 : case tok::kw___is_literal:
884 : case tok::kw___has_trivial_constructor:
885 : case tok::kw___has_trivial_copy:
886 : case tok::kw___has_trivial_assign:
887 : case tok::kw___has_trivial_destructor:
888 180: return ParseUnaryTypeTrait();
889 :
890 : case tok::at: {
891 318: SourceLocation AtLoc = ConsumeToken();
892 318: return ParseObjCAtExpression(AtLoc);
893 : }
894 : case tok::caret:
895 264: return ParsePostfixExpressionSuffix(ParseBlockLiteralExpression());
896 : case tok::l_square:
897 : // These can be followed by postfix-expr pieces.
1675: branch 1 taken
2: branch 2 taken
898 1677: if (getLang().ObjC1)
899 1675: return ParsePostfixExpressionSuffix(ParseObjCMessageExpression());
900 : // FALL THROUGH.
901 : default:
902 35: NotCastExpr = true;
903 35: return ExprError();
904 : }
905 :
906 : // unreachable.
907 65517: abort();
908 : }
909 :
910 : /// ParsePostfixExpressionSuffix - Once the leading part of a postfix-expression
911 : /// is parsed, this method parses any suffixes that apply.
912 : ///
913 : /// postfix-expression: [C99 6.5.2]
914 : /// primary-expression
915 : /// postfix-expression '[' expression ']'
916 : /// postfix-expression '(' argument-expression-list[opt] ')'
917 : /// postfix-expression '.' identifier
918 : /// postfix-expression '->' identifier
919 : /// postfix-expression '++'
920 : /// postfix-expression '--'
921 : /// '(' type-name ')' '{' initializer-list '}'
922 : /// '(' type-name ')' '{' initializer-list ',' '}'
923 : ///
924 : /// argument-expression-list: [C99 6.5.2]
925 : /// argument-expression
926 : /// argument-expression-list ',' assignment-expression
927 : ///
928 : Parser::OwningExprResult
929 55001: Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
930 : // Now that the primary-expression piece of the postfix-expression has been
931 : // parsed, see if there are any postfix-expression pieces here.
932 55001: SourceLocation Loc;
933 9917: while (1) {
54954: branch 1 taken
852: branch 2 taken
6549: branch 3 taken
2208: branch 4 taken
355: branch 5 taken
934 64918: switch (Tok.getKind()) {
935 : default: // Not a postfix-expression suffix.
936 54954: return move(LHS);
937 : case tok::l_square: { // postfix-expression: p-e '[' expression ']'
938 852: Loc = ConsumeBracket();
939 852: OwningExprResult Idx(ParseExpression());
940 :
941 852: SourceLocation RLoc = Tok.getLocation();
942 :
843: branch 1 taken
9: branch 2 taken
843: branch 4 taken
0: branch 5 not taken
843: branch 7 taken
0: branch 8 not taken
843: branch 9 taken
9: branch 10 taken
943 852: if (!LHS.isInvalid() && !Idx.isInvalid() && Tok.is(tok::r_square)) {
944 : LHS = Actions.ActOnArraySubscriptExpr(CurScope, move(LHS), Loc,
945 843: move(Idx), RLoc);
946 : } else
947 9: LHS = ExprError();
948 :
949 : // Match the ']'.
950 852: MatchRHSPunctuation(tok::r_square, Loc);
951 852: break;
952 : }
953 :
954 : case tok::l_paren: { // p-e: p-e '(' argument-expression-list[opt] ')'
955 6549: ExprVector ArgExprs(Actions);
956 6549: CommaLocsTy CommaLocs;
957 :
958 6549: Loc = ConsumeParen();
959 :
2: branch 1 taken
6547: branch 2 taken
960 6549: if (Tok.is(tok::code_completion)) {
961 2: Actions.CodeCompleteCall(CurScope, LHS.get(), 0, 0);
962 2: ConsumeToken();
963 : }
964 :
4936: branch 1 taken
1613: branch 2 taken
965 6549: if (Tok.isNot(tok::r_paren)) {
24: branch 2 taken
4912: branch 3 taken
966 4936: if (ParseExpressionList(ArgExprs, CommaLocs, &Action::CodeCompleteCall,
967 : LHS.get())) {
968 24: SkipUntil(tok::r_paren);
969 24: return ExprError();
970 : }
971 : }
972 :
973 : // Match the ')'.
1: branch 1 taken
6524: branch 2 taken
974 6525: if (Tok.isNot(tok::r_paren)) {
975 1: MatchRHSPunctuation(tok::r_paren, Loc);
976 1: return ExprError();
977 : }
978 :
6507: branch 1 taken
17: branch 2 taken
979 6524: if (!LHS.isInvalid()) {
980 : assert((ArgExprs.size() == 0 || ArgExprs.size()-1 == CommaLocs.size())&&
4908: branch 1 taken
1599: branch 2 taken
4908: branch 5 taken
0: branch 6 not taken
981 6507: "Unexpected number of commas!");
982 : LHS = Actions.ActOnCallExpr(CurScope, move(LHS), Loc,
983 : move_arg(ArgExprs), CommaLocs.data(),
984 6507: Tok.getLocation());
985 : }
986 :
987 6524: ConsumeParen();
25: branch 1 taken
6524: branch 2 taken
25: branch 4 taken
6524: branch 5 taken
988 6549: break;
989 : }
990 : case tok::arrow:
991 : case tok::period: {
992 : // postfix-expression: p-e '->' template[opt] id-expression
993 : // postfix-expression: p-e '.' template[opt] id-expression
994 2208: tok::TokenKind OpKind = Tok.getKind();
995 2208: SourceLocation OpLoc = ConsumeToken(); // Eat the "." or "->" token.
996 :
997 2208: CXXScopeSpec SS;
998 2208: Action::TypeTy *ObjectType = 0;
892: branch 1 taken
1316: branch 2 taken
890: branch 4 taken
2: branch 5 taken
890: branch 6 taken
1318: branch 7 taken
999 2208: if (getLang().CPlusPlus && !LHS.isInvalid()) {
1000 : LHS = Actions.ActOnStartCXXMemberReference(CurScope, move(LHS),
1001 890: OpLoc, OpKind, ObjectType);
12: branch 1 taken
878: branch 2 taken
1002 890: if (LHS.isInvalid())
1003 12: break;
1004 878: ParseOptionalCXXScopeSpecifier(SS, ObjectType, false);
1005 : }
1006 :
10: branch 1 taken
2186: branch 2 taken
1007 2196: if (Tok.is(tok::code_completion)) {
1008 : // Code completion for a member access expression.
1009 : Actions.CodeCompleteMemberReferenceExpr(CurScope, LHS.get(),
1010 10: OpLoc, OpKind == tok::arrow);
1011 :
1012 10: ConsumeToken();
1013 : }
1014 :
1015 2196: UnqualifiedId Name;
22: branch 1 taken
2174: branch 2 taken
1016 2196: if (ParseUnqualifiedId(SS,
1017 : /*EnteringContext=*/false,
1018 : /*AllowDestructorName=*/true,
1019 : /*AllowConstructorName=*/false,
1020 : ObjectType,
1021 : Name))
1022 22: return ExprError();
1023 :
2168: branch 1 taken
6: branch 2 taken
1024 2174: if (!LHS.isInvalid())
1025 : LHS = Actions.ActOnMemberAccessExpr(CurScope, move(LHS), OpLoc, OpKind,
1026 : SS, Name, ObjCImpDecl,
1027 2168: Tok.is(tok::l_paren));
1028 :
22: branch 1 taken
2174: branch 2 taken
1029 2196: break;
1030 : }
1031 : case tok::plusplus: // postfix-expression: postfix-expression '++'
1032 : case tok::minusminus: // postfix-expression: postfix-expression '--'
348: branch 1 taken
7: branch 2 taken
1033 355: if (!LHS.isInvalid()) {
1034 : LHS = Actions.ActOnPostfixUnaryOp(CurScope, Tok.getLocation(),
1035 348: Tok.getKind(), move(LHS));
1036 : }
1037 355: ConsumeToken();
1038 : break;
1039 : }
1040 : }
1041 : }
1042 :
1043 : /// ParseExprAfterTypeofSizeofAlignof - We parsed a typeof/sizeof/alignof and
1044 : /// we are at the start of an expression or a parenthesized type-id.
1045 : /// OpTok is the operand token (typeof/sizeof/alignof). Returns the expression
1046 : /// (isCastExpr == false) or the type (isCastExpr == true).
1047 : ///
1048 : /// unary-expression: [C99 6.5.3]
1049 : /// 'sizeof' unary-expression
1050 : /// 'sizeof' '(' type-name ')'
1051 : /// [GNU] '__alignof' unary-expression
1052 : /// [GNU] '__alignof' '(' type-name ')'
1053 : /// [C++0x] 'alignof' '(' type-id ')'
1054 : ///
1055 : /// [GNU] typeof-specifier:
1056 : /// typeof ( expressions )
1057 : /// typeof ( type-name )
1058 : /// [GNU/C++] typeof unary-expression
1059 : ///
1060 : Parser::OwningExprResult
1061 : Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
1062 : bool &isCastExpr,
1063 : TypeTy *&CastTy,
1064 887: SourceRange &CastRange) {
1065 :
1066 : assert((OpTok.is(tok::kw_typeof) || OpTok.is(tok::kw_sizeof) ||
1067 : OpTok.is(tok::kw___alignof) || OpTok.is(tok::kw_alignof)) &&
623: branch 1 taken
264: branch 2 taken
54: branch 4 taken
569: branch 5 taken
7: branch 7 taken
47: branch 8 taken
7: branch 10 taken
0: branch 11 not taken
1068 887: "Not a typeof/sizeof/alignof expression!");
1069 :
1070 887: OwningExprResult Operand(Actions);
1071 :
1072 : // If the operand doesn't start with an '(', it must be an expression.
15: branch 1 taken
872: branch 2 taken
1073 887: if (Tok.isNot(tok::l_paren)) {
1074 15: isCastExpr = false;
1: branch 1 taken
14: branch 2 taken
0: branch 4 not taken
1: branch 5 taken
0: branch 6 not taken
15: branch 7 taken
1075 15: if (OpTok.is(tok::kw_typeof) && !getLang().CPlusPlus) {
1076 0: Diag(Tok,diag::err_expected_lparen_after_id) << OpTok.getIdentifierInfo();
1077 0: return ExprError();
1078 : }
1079 :
1080 : // C++0x [expr.sizeof]p1:
1081 : // [...] The operand is either an expression, which is an unevaluated
1082 : // operand (Clause 5) [...]
1083 : //
1084 : // The GNU typeof and alignof extensions also behave as unevaluated
1085 : // operands.
1086 : EnterExpressionEvaluationContext Unevaluated(Actions,
1087 15: Action::Unevaluated);
1088 15: Operand = ParseCastExpression(true/*isUnaryExpression*/);
1089 : } else {
1090 : // If it starts with a '(', we know that it is either a parenthesized
1091 : // type-name, or it is a unary-expression that starts with a compound
1092 : // literal, or starts with a primary-expression that is a parenthesized
1093 : // expression.
1094 872: ParenParseOption ExprType = CastExpr;
1095 872: SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
1096 :
1097 : // C++0x [expr.sizeof]p1:
1098 : // [...] The operand is either an expression, which is an unevaluated
1099 : // operand (Clause 5) [...]
1100 : //
1101 : // The GNU typeof and alignof extensions also behave as unevaluated
1102 : // operands.
1103 : EnterExpressionEvaluationContext Unevaluated(Actions,
1104 872: Action::Unevaluated);
1105 : Operand = ParseParenExpression(ExprType, true/*stopIfCastExpr*/,
1106 : 0/*TypeOfCast*/,
1107 872: CastTy, RParenLoc);
1108 872: CastRange = SourceRange(LParenLoc, RParenLoc);
1109 :
1110 : // If ParseParenExpression parsed a '(typename)' sequence only, then this is
1111 : // a type.
443: branch 0 taken
429: branch 1 taken
1112 872: if (ExprType == CastExpr) {
1113 443: isCastExpr = true;
1114 443: return ExprEmpty();
1115 : }
1116 :
1117 : // If this is a parenthesized expression, it is the start of a
1118 : // unary-expression, but doesn't include any postfix pieces. Parse these
1119 : // now if present.
429: branch 10 taken
443: branch 11 taken
1120 429: Operand = ParsePostfixExpressionSuffix(move(Operand));
1121 : }
1122 :
1123 : // If we get here, the operand to the typeof/sizeof/alignof was an expresion.
1124 444: isCastExpr = false;
1125 444: return move(Operand);
1126 : }
1127 :
1128 :
1129 : /// ParseSizeofAlignofExpression - Parse a sizeof or alignof expression.
1130 : /// unary-expression: [C99 6.5.3]
1131 : /// 'sizeof' unary-expression
1132 : /// 'sizeof' '(' type-name ')'
1133 : /// [GNU] '__alignof' unary-expression
1134 : /// [GNU] '__alignof' '(' type-name ')'
1135 : /// [C++0x] 'alignof' '(' type-id ')'
1136 623: Parser::OwningExprResult Parser::ParseSizeofAlignofExpression() {
1137 : assert((Tok.is(tok::kw_sizeof) || Tok.is(tok::kw___alignof)
1138 : || Tok.is(tok::kw_alignof)) &&
54: branch 1 taken
569: branch 2 taken
7: branch 4 taken
47: branch 5 taken
7: branch 7 taken
0: branch 8 not taken
1139 623: "Not a sizeof/alignof expression!");
1140 623: Token OpTok = Tok;
1141 623: ConsumeToken();
1142 :
1143 : bool isCastExpr;
1144 : TypeTy *CastTy;
1145 623: SourceRange CastRange;
1146 : OwningExprResult Operand = ParseExprAfterTypeofSizeofAlignof(OpTok,
1147 : isCastExpr,
1148 : CastTy,
1149 623: CastRange);
1150 :
424: branch 0 taken
199: branch 1 taken
1151 623: if (isCastExpr)
1152 : return Actions.ActOnSizeOfAlignOfExpr(OpTok.getLocation(),
1153 : OpTok.is(tok::kw_sizeof),
1154 : /*isType=*/true, CastTy,
1155 424: CastRange);
1156 :
1157 : // If we get here, the operand to the sizeof/alignof was an expresion.
198: branch 1 taken
1: branch 2 taken
1158 199: if (!Operand.isInvalid())
1159 : Operand = Actions.ActOnSizeOfAlignOfExpr(OpTok.getLocation(),
1160 : OpTok.is(tok::kw_sizeof),
1161 : /*isType=*/false,
1162 198: Operand.release(), CastRange);
1163 199: return move(Operand);
1164 : }
1165 :
1166 : /// ParseBuiltinPrimaryExpression
1167 : ///
1168 : /// primary-expression: [C99 6.5.1]
1169 : /// [GNU] '__builtin_va_arg' '(' assignment-expression ',' type-name ')'
1170 : /// [GNU] '__builtin_offsetof' '(' type-name ',' offsetof-member-designator')'
1171 : /// [GNU] '__builtin_choose_expr' '(' assign-expr ',' assign-expr ','
1172 : /// assign-expr ')'
1173 : /// [GNU] '__builtin_types_compatible_p' '(' type-name ',' type-name ')'
1174 : ///
1175 : /// [GNU] offsetof-member-designator:
1176 : /// [GNU] identifier
1177 : /// [GNU] offsetof-member-designator '.' identifier
1178 : /// [GNU] offsetof-member-designator '[' expression ']'
1179 : ///
1180 234: Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() {
1181 234: OwningExprResult Res(Actions);
1182 234: const IdentifierInfo *BuiltinII = Tok.getIdentifierInfo();
1183 :
1184 234: tok::TokenKind T = Tok.getKind();
1185 234: SourceLocation StartLoc = ConsumeToken(); // Eat the builtin identifier.
1186 :
1187 : // All of these start with an open paren.
0: branch 1 not taken
234: branch 2 taken
1188 234: if (Tok.isNot(tok::l_paren))
1189 : return ExprError(Diag(Tok, diag::err_expected_lparen_after_id)
1190 0: << BuiltinII);
1191 :
1192 234: SourceLocation LParenLoc = ConsumeParen();
1193 : // TODO: Build AST.
1194 :
0: branch 0 not taken
35: branch 1 taken
128: branch 2 taken
33: branch 3 taken
38: branch 4 taken
1195 234: switch (T) {
1196 0: default: assert(0 && "Not a builtin primary expression!");
1197 : case tok::kw___builtin_va_arg: {
1198 35: OwningExprResult Expr(ParseAssignmentExpression());
1: branch 1 taken
34: branch 2 taken
1199 35: if (Expr.isInvalid()) {
1200 1: SkipUntil(tok::r_paren);
1201 1: return ExprError();
1202 : }
1203 :
0: branch 1 not taken
34: branch 2 taken
1204 34: if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
1205 0: return ExprError();
1206 :
1207 34: TypeResult Ty = ParseTypeName();
1208 :
0: branch 1 not taken
34: branch 2 taken
1209 34: if (Tok.isNot(tok::r_paren)) {
1210 0: Diag(Tok, diag::err_expected_rparen);
1211 0: return ExprError();
1212 : }
0: branch 1 not taken
34: branch 2 taken
1213 34: if (Ty.isInvalid())
1214 0: Res = ExprError();
1215 : else
1216 34: Res = Actions.ActOnVAArg(StartLoc, move(Expr), Ty.get(), ConsumeParen());
1: branch 1 taken
34: branch 2 taken
1217 35: break;
1218 : }
1219 : case tok::kw___builtin_offsetof: {
1220 128: SourceLocation TypeLoc = Tok.getLocation();
1221 128: TypeResult Ty = ParseTypeName();
1: branch 1 taken
127: branch 2 taken
1222 128: if (Ty.isInvalid()) {
1223 1: SkipUntil(tok::r_paren);
1224 1: return ExprError();
1225 : }
1226 :
0: branch 1 not taken
127: branch 2 taken
1227 127: if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
1228 0: return ExprError();
1229 :
1230 : // We must have at least one identifier here.
0: branch 1 not taken
127: branch 2 taken
1231 127: if (Tok.isNot(tok::identifier)) {
1232 0: Diag(Tok, diag::err_expected_ident);
1233 0: SkipUntil(tok::r_paren);
1234 0: return ExprError();
1235 : }
1236 :
1237 : // Keep track of the various subcomponents we see.
1238 127: llvm::SmallVector<Action::OffsetOfComponent, 4> Comps;
1239 :
1240 127: Comps.push_back(Action::OffsetOfComponent());
1241 127: Comps.back().isBrackets = false;
1242 127: Comps.back().U.IdentInfo = Tok.getIdentifierInfo();
1243 127: Comps.back().LocStart = Comps.back().LocEnd = ConsumeToken();
1244 :
1245 : // FIXME: This loop leaks the index expressions on error.
1246 16: while (1) {
7: branch 1 taken
136: branch 2 taken
1247 143: if (Tok.is(tok::period)) {
1248 : // offsetof-member-designator: offsetof-member-designator '.' identifier
1249 7: Comps.push_back(Action::OffsetOfComponent());
1250 7: Comps.back().isBrackets = false;
1251 7: Comps.back().LocStart = ConsumeToken();
1252 :
0: branch 1 not taken
7: branch 2 taken
1253 7: if (Tok.isNot(tok::identifier)) {
1254 0: Diag(Tok, diag::err_expected_ident);
1255 0: SkipUntil(tok::r_paren);
1256 0: return ExprError();
1257 : }
1258 7: Comps.back().U.IdentInfo = Tok.getIdentifierInfo();
1259 7: Comps.back().LocEnd = ConsumeToken();
1260 :
9: branch 1 taken
127: branch 2 taken
1261 136: } else if (Tok.is(tok::l_square)) {
1262 : // offsetof-member-designator: offsetof-member-design '[' expression ']'
1263 9: Comps.push_back(Action::OffsetOfComponent());
1264 9: Comps.back().isBrackets = true;
1265 9: Comps.back().LocStart = ConsumeBracket();
1266 9: Res = ParseExpression();
0: branch 1 not taken
9: branch 2 taken
1267 9: if (Res.isInvalid()) {
1268 0: SkipUntil(tok::r_paren);
1269 0: return move(Res);
1270 : }
1271 9: Comps.back().U.E = Res.release();
1272 :
1273 : Comps.back().LocEnd =
1274 9: MatchRHSPunctuation(tok::r_square, Comps.back().LocStart);
1275 : } else {
2: branch 1 taken
125: branch 2 taken
1276 127: if (Tok.isNot(tok::r_paren)) {
1277 2: MatchRHSPunctuation(tok::r_paren, LParenLoc);
1278 2: Res = ExprError();
0: branch 1 not taken
125: branch 2 taken
1279 125: } else if (Ty.isInvalid()) {
1280 0: Res = ExprError();
1281 : } else {
1282 : Res = Actions.ActOnBuiltinOffsetOf(CurScope, StartLoc, TypeLoc,
1283 : Ty.get(), &Comps[0],
1284 125: Comps.size(), ConsumeParen());
1285 : }
1286 : break;
1287 : }
1288 : }
0: branch 1 not taken
127: branch 2 taken
1289 127: break;
1290 : }
1291 : case tok::kw___builtin_choose_expr: {
1292 33: OwningExprResult Cond(ParseAssignmentExpression());
0: branch 1 not taken
33: branch 2 taken
1293 33: if (Cond.isInvalid()) {
1294 0: SkipUntil(tok::r_paren);
1295 0: return move(Cond);
1296 : }
0: branch 1 not taken
33: branch 2 taken
1297 33: if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
1298 0: return ExprError();
1299 :
1300 33: OwningExprResult Expr1(ParseAssignmentExpression());
0: branch 1 not taken
33: branch 2 taken
1301 33: if (Expr1.isInvalid()) {
1302 0: SkipUntil(tok::r_paren);
1303 0: return move(Expr1);
1304 : }
0: branch 1 not taken
33: branch 2 taken
1305 33: if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
1306 0: return ExprError();
1307 :
1308 33: OwningExprResult Expr2(ParseAssignmentExpression());
0: branch 1 not taken
33: branch 2 taken
1309 33: if (Expr2.isInvalid()) {
1310 0: SkipUntil(tok::r_paren);
1311 0: return move(Expr2);
1312 : }
0: branch 1 not taken
33: branch 2 taken
1313 33: if (Tok.isNot(tok::r_paren)) {
1314 0: Diag(Tok, diag::err_expected_rparen);
1315 0: return ExprError();
1316 : }
1317 : Res = Actions.ActOnChooseExpr(StartLoc, move(Cond), move(Expr1),
1318 33: move(Expr2), ConsumeParen());
0: branch 1 not taken
33: branch 2 taken
0: branch 4 not taken
33: branch 5 taken
0: branch 7 not taken
33: branch 8 taken
1319 33: break;
1320 : }
1321 : case tok::kw___builtin_types_compatible_p:
1322 38: TypeResult Ty1 = ParseTypeName();
1323 :
0: branch 1 not taken
38: branch 2 taken
1324 38: if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
1325 0: return ExprError();
1326 :
1327 38: TypeResult Ty2 = ParseTypeName();
1328 :
0: branch 1 not taken
38: branch 2 taken
1329 38: if (Tok.isNot(tok::r_paren)) {
1330 0: Diag(Tok, diag::err_expected_rparen);
1331 0: return ExprError();
1332 : }
1333 :
38: branch 1 taken
0: branch 2 not taken
0: branch 4 not taken
38: branch 5 taken
0: branch 6 not taken
38: branch 7 taken
1334 38: if (Ty1.isInvalid() || Ty2.isInvalid())
1335 0: Res = ExprError();
1336 : else
1337 : Res = Actions.ActOnTypesCompatibleExpr(StartLoc, Ty1.get(), Ty2.get(),
1338 38: ConsumeParen());
1339 : break;
1340 : }
1341 :
1342 : // These can be followed by postfix-expr pieces because they are
1343 : // primary-expressions.
1344 232: return ParsePostfixExpressionSuffix(move(Res));
1345 : }
1346 :
1347 : /// ParseParenExpression - This parses the unit that starts with a '(' token,
1348 : /// based on what is allowed by ExprType. The actual thing parsed is returned
1349 : /// in ExprType. If stopIfCastExpr is true, it will only return the parsed type,
1350 : /// not the parsed cast-expression.
1351 : ///
1352 : /// primary-expression: [C99 6.5.1]
1353 : /// '(' expression ')'
1354 : /// [GNU] '(' compound-statement ')' (if !ParenExprOnly)
1355 : /// postfix-expression: [C99 6.5.2]
1356 : /// '(' type-name ')' '{' initializer-list '}'
1357 : /// '(' type-name ')' '{' initializer-list ',' '}'
1358 : /// cast-expression: [C99 6.5.4]
1359 : /// '(' type-name ')' cast-expression
1360 : ///
1361 : Parser::OwningExprResult
1362 : Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
1363 : TypeTy *TypeOfCast, TypeTy *&CastTy,
1364 9509: SourceLocation &RParenLoc) {
9509: branch 1 taken
0: branch 2 not taken
1365 9509: assert(Tok.is(tok::l_paren) && "Not a paren expr!");
1366 9509: GreaterThanIsOperatorScope G(GreaterThanIsOperator, true);
1367 9509: SourceLocation OpenLoc = ConsumeParen();
1368 9509: OwningExprResult Result(Actions, true);
1369 : bool isAmbiguousTypeId;
1370 9509: CastTy = 0;
1371 :
9509: branch 0 taken
0: branch 1 not taken
65: branch 3 taken
9444: branch 4 taken
65: branch 5 taken
9444: branch 6 taken
1372 19018: if (ExprType >= CompoundStmt && Tok.is(tok::l_brace)) {
1373 65: Diag(Tok, diag::ext_gnu_statement_expr);
1374 65: OwningStmtResult Stmt(ParseCompoundStatement(0, true));
1375 65: ExprType = CompoundStmt;
1376 :
1377 : // If the substmt parsed correctly, build the AST node.
65: branch 1 taken
0: branch 2 not taken
65: branch 4 taken
0: branch 5 not taken
65: branch 6 taken
0: branch 7 not taken
1378 65: if (!Stmt.isInvalid() && Tok.is(tok::r_paren))
1379 65: Result = Actions.ActOnStmtExpr(OpenLoc, move(Stmt), Tok.getLocation());
1380 :
9444: branch 0 taken
0: branch 1 not taken
5586: branch 3 taken
3858: branch 4 taken
5586: branch 5 taken
3858: branch 6 taken
1381 9444: } else if (ExprType >= CompoundLiteral &&
1382 : isTypeIdInParens(isAmbiguousTypeId)) {
1383 :
1384 : // Otherwise, this is a compound literal expression or cast expression.
1385 :
1386 : // In C++, if the type-id is ambiguous we disambiguate based on context.
1387 : // If stopIfCastExpr is true the context is a typeof/sizeof/alignof
1388 : // in which case we should treat it as type-id.
1389 : // if stopIfCastExpr is false, we need to determine the context past the
1390 : // parens, so we defer to ParseCXXAmbiguousParenExpression for that.
36: branch 0 taken
5550: branch 1 taken
35: branch 2 taken
1: branch 3 taken
1391 5586: if (isAmbiguousTypeId && !stopIfCastExpr)
1392 : return ParseCXXAmbiguousParenExpression(ExprType, CastTy,
1393 35: OpenLoc, RParenLoc);
1394 :
1395 5551: TypeResult Ty = ParseTypeName();
1396 :
1397 : // Match the ')'.
5549: branch 1 taken
2: branch 2 taken
1398 5551: if (Tok.is(tok::r_paren))
1399 5549: RParenLoc = ConsumeParen();
1400 : else
1401 2: MatchRHSPunctuation(tok::r_paren, OpenLoc);
1402 :
291: branch 1 taken
5260: branch 2 taken
1403 5551: if (Tok.is(tok::l_brace)) {
1404 291: ExprType = CompoundLiteral;
1405 291: return ParseCompoundLiteralExpression(Ty.get(), OpenLoc, RParenLoc);
1406 : }
1407 :
5260: branch 0 taken
0: branch 1 not taken
1408 5260: if (ExprType == CastExpr) {
1409 : // We parsed '(' type-name ')' and the thing after it wasn't a '{'.
1410 :
4: branch 1 taken
5256: branch 2 taken
1411 5260: if (Ty.isInvalid())
1412 4: return ExprError();
1413 :
1414 5256: CastTy = Ty.get();
1415 :
439: branch 0 taken
4817: branch 1 taken
1416 5256: if (stopIfCastExpr) {
1417 : // Note that this doesn't parse the subsequent cast-expression, it just
1418 : // returns the parsed type to the callee.
1419 439: return OwningExprResult(Actions);
1420 : }
1421 :
1422 : // Parse the cast-expression that follows it next.
1423 : // TODO: For cast expression with CastTy.
1424 4817: Result = ParseCastExpression(false, false, CastTy);
4681: branch 1 taken
136: branch 2 taken
1425 4817: if (!Result.isInvalid())
1426 : Result = Actions.ActOnCastExpr(CurScope, OpenLoc, CastTy, RParenLoc,
1427 4681: move(Result));
1428 4817: return move(Result);
1429 : }
1430 :
1431 0: Diag(Tok, diag::err_expected_lbrace_in_compound_literal);
1432 0: return ExprError();
461: branch 0 taken
3397: branch 1 taken
1433 3858: } else if (TypeOfCast) {
1434 : // Parse the expression-list.
1435 461: ExprVector ArgExprs(Actions);
1436 461: CommaLocsTy CommaLocs;
1437 :
419: branch 1 taken
42: branch 2 taken
1438 461: if (!ParseExpressionList(ArgExprs, CommaLocs)) {
1439 419: ExprType = SimpleExpr;
1440 : Result = Actions.ActOnParenOrParenListExpr(OpenLoc, Tok.getLocation(),
1441 419: move_arg(ArgExprs), TypeOfCast);
1442 461: }
1443 : } else {
1444 3397: Result = ParseExpression();
1445 3397: ExprType = SimpleExpr;
3392: branch 1 taken
5: branch 2 taken
3392: branch 4 taken
0: branch 5 not taken
3392: branch 6 taken
5: branch 7 taken
1446 3397: if (!Result.isInvalid() && Tok.is(tok::r_paren))
1447 3392: Result = Actions.ActOnParenExpr(OpenLoc, Tok.getLocation(), move(Result));
1448 : }
1449 :
1450 : // Match the ')'.
48: branch 1 taken
3875: branch 2 taken
1451 3923: if (Result.isInvalid()) {
1452 48: SkipUntil(tok::r_paren);
1453 48: return ExprError();
1454 : }
1455 :
3875: branch 1 taken
0: branch 2 not taken
1456 3875: if (Tok.is(tok::r_paren))
1457 3875: RParenLoc = ConsumeParen();
1458 : else
1459 0: MatchRHSPunctuation(tok::r_paren, OpenLoc);
1460 :
1461 3875: return move(Result);
1462 : }
1463 :
1464 : /// ParseCompoundLiteralExpression - We have parsed the parenthesized type-name
1465 : /// and we are at the left brace.
1466 : ///
1467 : /// postfix-expression: [C99 6.5.2]
1468 : /// '(' type-name ')' '{' initializer-list '}'
1469 : /// '(' type-name ')' '{' initializer-list ',' '}'
1470 : ///
1471 : Parser::OwningExprResult
1472 : Parser::ParseCompoundLiteralExpression(TypeTy *Ty,
1473 : SourceLocation LParenLoc,
1474 291: SourceLocation RParenLoc) {
291: branch 1 taken
0: branch 2 not taken
1475 291: assert(Tok.is(tok::l_brace) && "Not a compound literal!");
50: branch 1 taken
241: branch 2 taken
1476 291: if (!getLang().C99) // Compound literals don't exist in C90.
1477 50: Diag(LParenLoc, diag::ext_c99_compound_literal);
1478 291: OwningExprResult Result = ParseInitializer();
291: branch 1 taken
0: branch 2 not taken
282: branch 3 taken
9: branch 4 taken
282: branch 5 taken
9: branch 6 taken
1479 291: if (!Result.isInvalid() && Ty)
1480 282: return Actions.ActOnCompoundLiteral(LParenLoc, Ty, RParenLoc, move(Result));
1481 9: return move(Result);
1482 : }
1483 :
1484 : /// ParseStringLiteralExpression - This handles the various token types that
1485 : /// form string literals, and also handles string concatenation [C99 5.1.1.2,
1486 : /// translation phase #6].
1487 : ///
1488 : /// primary-expression: [C99 6.5.1]
1489 : /// string-literal
1490 1790: Parser::OwningExprResult Parser::ParseStringLiteralExpression() {
1790: branch 1 taken
0: branch 2 not taken
1491 1790: assert(isTokenStringLiteral() && "Not a string literal!");
1492 :
1493 : // String concat. Note that keywords like __func__ and __FUNCTION__ are not
1494 : // considered to be strings for concatenation purposes.
1495 1790: llvm::SmallVector<Token, 4> StringToks;
1496 :
175: branch 1 taken
1790: branch 2 taken
1497 1965: do {
1498 1965: StringToks.push_back(Tok);
1499 1965: ConsumeStringToken();
1500 : } while (isTokenStringLiteral());
1501 :
1502 : // Pass the set of string tokens, ready for concatenation, to the actions.
1503 1790: return Actions.ActOnStringLiteral(&StringToks[0], StringToks.size());
1504 : }
1505 :
1506 : /// ParseExpressionList - Used for C/C++ (argument-)expression-list.
1507 : ///
1508 : /// argument-expression-list:
1509 : /// assignment-expression
1510 : /// argument-expression-list , assignment-expression
1511 : ///
1512 : /// [C++] expression-list:
1513 : /// [C++] assignment-expression
1514 : /// [C++] expression-list , assignment-expression
1515 : ///
1516 : bool Parser::ParseExpressionList(ExprListTy &Exprs, CommaLocsTy &CommaLocs,
1517 : void (Action::*Completer)(Scope *S,
1518 : void *Data,
1519 : ExprTy **Args,
1520 : unsigned NumArgs),
1521 10348: void *Data) {
4346: branch 1 taken
6002: branch 2 taken
1522 10348: while (1) {
4: branch 1 taken
10344: branch 2 taken
1523 10348: if (Tok.is(tok::code_completion)) {
4: branch 0 taken
0: branch 1 not taken
1524 4: if (Completer)
4: branch 0 taken
0: branch 1 not taken
1525 4: (Actions.*Completer)(CurScope, Data, Exprs.data(), Exprs.size());
1526 4: ConsumeToken();
1527 : }
1528 :
1529 10348: OwningExprResult Expr(ParseAssignmentExpression());
69: branch 1 taken
10279: branch 2 taken
1530 10348: if (Expr.isInvalid())
1531 69: return true;
1532 :
1533 10279: Exprs.push_back(Expr.release());
1534 :
5933: branch 1 taken
4346: branch 2 taken
1535 10279: if (Tok.isNot(tok::comma))
1536 5933: return false;
1537 : // Move to the next argument, remember where the comma was.
1538 4346: CommaLocs.push_back(ConsumeToken());
1539 : }
1540 : }
1541 :
1542 : /// ParseBlockId - Parse a block-id, which roughly looks like int (int x).
1543 : ///
1544 : /// [clang] block-id:
1545 : /// [clang] specifier-qualifier-list block-declarator
1546 : ///
1547 25: void Parser::ParseBlockId() {
1548 : // Parse the specifier-qualifier-list piece.
1549 25: DeclSpec DS;
1550 25: ParseSpecifierQualifierList(DS);
1551 :
1552 : // Parse the block-declarator.
1553 25: Declarator DeclaratorInfo(DS, Declarator::BlockLiteralContext);
1554 25: ParseDeclarator(DeclaratorInfo);
1555 :
1556 : // We do this for: ^ __attribute__((noreturn)) {, as DS has the attributes.
1557 : DeclaratorInfo.AddAttributes(DS.TakeAttributes(),
1558 25: SourceLocation());
1559 :
0: branch 1 not taken
25: branch 2 taken
1560 25: if (Tok.is(tok::kw___attribute)) {
1561 0: SourceLocation Loc;
1562 0: AttributeList *AttrList = ParseGNUAttributes(&Loc);
1563 0: DeclaratorInfo.AddAttributes(AttrList, Loc);
1564 : }
1565 :
1566 : // Inform sema that we are starting a block.
1567 25: Actions.ActOnBlockArguments(DeclaratorInfo, CurScope);
1568 25: }
1569 :
1570 : /// ParseBlockLiteralExpression - Parse a block literal, which roughly looks
1571 : /// like ^(int x){ return x+1; }
1572 : ///
1573 : /// block-literal:
1574 : /// [clang] '^' block-args[opt] compound-statement
1575 : /// [clang] '^' block-id compound-statement
1576 : /// [clang] block-args:
1577 : /// [clang] '(' parameter-list ')'
1578 : ///
1579 264: Parser::OwningExprResult Parser::ParseBlockLiteralExpression() {
264: branch 1 taken
0: branch 2 not taken
1580 264: assert(Tok.is(tok::caret) && "block literal starts with ^");
1581 264: SourceLocation CaretLoc = ConsumeToken();
1582 :
1583 : PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), CaretLoc,
1584 264: "block literal parsing");
1585 :
1586 : // Enter a scope to hold everything within the block. This includes the
1587 : // argument decls, decls within the compound expression, etc. This also
1588 : // allows determining whether a variable reference inside the block is
1589 : // within or outside of the block.
1590 : ParseScope BlockScope(this, Scope::BlockScope | Scope::FnScope |
1591 : Scope::BreakScope | Scope::ContinueScope |
1592 264: Scope::DeclScope);
1593 :
1594 : // Inform sema that we are starting a block.
1595 264: Actions.ActOnBlockStart(CaretLoc, CurScope);
1596 :
1597 : // Parse the return type if present.
1598 264: DeclSpec DS;
1599 264: Declarator ParamInfo(DS, Declarator::BlockLiteralContext);
1600 : // FIXME: Since the return type isn't actually parsed, it can't be used to
1601 : // fill ParamInfo with an initial valid range, so do it manually.
1602 264: ParamInfo.SetSourceRange(SourceRange(Tok.getLocation(), Tok.getLocation()));
1603 :
1604 : // If this block has arguments, parse them. There is no ambiguity here with
1605 : // the expression case, because the expression case requires a parameter list.
59: branch 1 taken
205: branch 2 taken
1606 264: if (Tok.is(tok::l_paren)) {
1607 59: ParseParenDeclarator(ParamInfo);
1608 : // Parse the pieces after the identifier as if we had "int(...)".
1609 : // SetIdentifier sets the source range end, but in this case we're past
1610 : // that location.
1611 59: SourceLocation Tmp = ParamInfo.getSourceRange().getEnd();
1612 59: ParamInfo.SetIdentifier(0, CaretLoc);
1613 59: ParamInfo.SetRangeEnd(Tmp);
0: branch 1 not taken
59: branch 2 taken
1614 59: if (ParamInfo.isInvalidType()) {
1615 : // If there was an error parsing the arguments, they may have
1616 : // tried to use ^(x+y) which requires an argument list. Just
1617 : // skip the whole block literal.
1618 0: Actions.ActOnBlockError(CaretLoc, CurScope);
1619 0: return ExprError();
1620 : }
1621 :
2: branch 1 taken
57: branch 2 taken
1622 59: if (Tok.is(tok::kw___attribute)) {
1623 2: SourceLocation Loc;
1624 2: AttributeList *AttrList = ParseGNUAttributes(&Loc);
1625 2: ParamInfo.AddAttributes(AttrList, Loc);
1626 : }
1627 :
1628 : // Inform sema that we are starting a block.
1629 59: Actions.ActOnBlockArguments(ParamInfo, CurScope);
25: branch 1 taken
180: branch 2 taken
1630 205: } else if (!Tok.is(tok::l_brace)) {
1631 25: ParseBlockId();
1632 : } else {
1633 : // Otherwise, pretend we saw (void).
1634 : ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(true, false,
1635 : SourceLocation(),
1636 : 0, 0, 0,
1637 : false, SourceLocation(),
1638 : false, 0, 0, 0,
1639 : CaretLoc, CaretLoc,
1640 : ParamInfo),
1641 180: CaretLoc);
1642 :
0: branch 1 not taken
180: branch 2 taken
1643 180: if (Tok.is(tok::kw___attribute)) {
1644 0: SourceLocation Loc;
1645 0: AttributeList *AttrList = ParseGNUAttributes(&Loc);
1646 0: ParamInfo.AddAttributes(AttrList, Loc);
1647 : }
1648 :
1649 : // Inform sema that we are starting a block.
1650 180: Actions.ActOnBlockArguments(ParamInfo, CurScope);
1651 : }
1652 :
1653 :
1654 264: OwningExprResult Result(Actions, true);
1: branch 1 taken
263: branch 2 taken
1655 264: if (!Tok.is(tok::l_brace)) {
1656 : // Saw something like: ^expr
1657 1: Diag(Tok, diag::err_expected_expression);
1658 1: Actions.ActOnBlockError(CaretLoc, CurScope);
1659 1: return ExprError();
1660 : }
1661 :
1662 263: OwningStmtResult Stmt(ParseCompoundStatementBody());
263: branch 1 taken
0: branch 2 not taken
1663 263: if (!Stmt.isInvalid())
1664 263: Result = Actions.ActOnBlockStmtExpr(CaretLoc, move(Stmt), CurScope);
1665 : else
1666 0: Actions.ActOnBlockError(CaretLoc, CurScope);
1667 263: return move(Result);
1668 : }
Generated: 2010-02-10 01:31 by zcov