 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
73.6% |
338 / 459 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
97.4% |
447 / 459 |
| |
|
Line Coverage: |
85.5% |
519 / 607 |
| |
 |
|
 |
1 : //===--- ParseExprCXX.cpp - C++ 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 for C++.
11 : //
12 : //===----------------------------------------------------------------------===//
13 :
14 : #include "clang/Parse/ParseDiagnostic.h"
15 : #include "clang/Parse/Parser.h"
16 : #include "clang/Parse/DeclSpec.h"
17 : #include "clang/Parse/Template.h"
18 : #include "llvm/Support/ErrorHandling.h"
19 :
20 : using namespace clang;
21 :
22 : /// \brief Parse global scope or nested-name-specifier if present.
23 : ///
24 : /// Parses a C++ global scope specifier ('::') or nested-name-specifier (which
25 : /// may be preceded by '::'). Note that this routine will not parse ::new or
26 : /// ::delete; it will just leave them in the token stream.
27 : ///
28 : /// '::'[opt] nested-name-specifier
29 : /// '::'
30 : ///
31 : /// nested-name-specifier:
32 : /// type-name '::'
33 : /// namespace-name '::'
34 : /// nested-name-specifier identifier '::'
35 : /// nested-name-specifier 'template'[opt] simple-template-id '::'
36 : ///
37 : ///
38 : /// \param SS the scope specifier that will be set to the parsed
39 : /// nested-name-specifier (or empty)
40 : ///
41 : /// \param ObjectType if this nested-name-specifier is being parsed following
42 : /// the "." or "->" of a member access expression, this parameter provides the
43 : /// type of the object whose members are being accessed.
44 : ///
45 : /// \param EnteringContext whether we will be entering into the context of
46 : /// the nested-name-specifier after parsing it.
47 : ///
48 : /// \returns true if a scope specifier was parsed.
49 : bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
50 : Action::TypeTy *ObjectType,
51 71336: bool EnteringContext) {
52 : assert(getLang().CPlusPlus &&
71336: branch 1 taken
0: branch 2 not taken
53 71336: "Call sites of this function should be guarded by checking for C++");
54 :
1425: branch 1 taken
69911: branch 2 taken
55 71336: if (Tok.is(tok::annot_cxxscope)) {
56 1425: SS.setScopeRep(Tok.getAnnotationValue());
57 1425: SS.setRange(Tok.getAnnotationRange());
58 1425: ConsumeToken();
59 1425: return true;
60 : }
61 :
62 69911: bool HasScopeSpecifier = false;
63 :
89: branch 1 taken
69822: branch 2 taken
64 69911: if (Tok.is(tok::coloncolon)) {
65 : // ::new and ::delete aren't nested-name-specifiers.
66 89: tok::TokenKind NextKind = NextToken().getKind();
87: branch 0 taken
2: branch 1 taken
2: branch 2 taken
85: branch 3 taken
67 89: if (NextKind == tok::kw_new || NextKind == tok::kw_delete)
68 4: return false;
69 :
70 : // '::' - Global scope qualifier.
71 85: SourceLocation CCLoc = ConsumeToken();
72 85: SS.setBeginLoc(CCLoc);
73 85: SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope, CCLoc));
74 85: SS.setEndLoc(CCLoc);
75 85: HasScopeSpecifier = true;
76 : }
77 :
78 4953: while (true) {
2819: branch 0 taken
72041: branch 1 taken
79 74860: if (HasScopeSpecifier) {
80 : // C++ [basic.lookup.classref]p5:
81 : // If the qualified-id has the form
82 : //
83 : // ::class-name-or-namespace-name::...
84 : //
85 : // the class-name-or-namespace-name is looked up in global scope as a
86 : // class-name or namespace-name.
87 : //
88 : // To implement this, we clear out the object type as soon as we've
89 : // seen a leading '::' or part of a nested-name-specifier.
90 2819: ObjectType = 0;
91 :
4: branch 1 taken
2815: branch 2 taken
92 2819: if (Tok.is(tok::code_completion)) {
93 : // Code completion for a nested-name-specifier, where the code
94 : // code completion token follows the '::'.
95 4: Actions.CodeCompleteQualifiedId(CurScope, SS, EnteringContext);
96 4: ConsumeToken();
97 : }
98 : }
99 :
100 : // nested-name-specifier:
101 : // nested-name-specifier 'template'[opt] simple-template-id '::'
102 :
103 : // Parse the optional 'template' keyword, then make sure we have
104 : // 'identifier <' after it.
52: branch 1 taken
74808: branch 2 taken
105 74860: if (Tok.is(tok::kw_template)) {
106 : // If we don't have a scope specifier or an object type, this isn't a
107 : // nested-name-specifier, since they aren't allowed to start with
108 : // 'template'.
5: branch 0 taken
47: branch 1 taken
4: branch 2 taken
1: branch 3 taken
109 52: if (!HasScopeSpecifier && !ObjectType)
110 1: break;
111 :
112 51: TentativeParsingAction TPA(*this);
113 51: SourceLocation TemplateKWLoc = ConsumeToken();
114 :
115 51: UnqualifiedId TemplateName;
48: branch 1 taken
3: branch 2 taken
116 51: if (Tok.is(tok::identifier)) {
117 : // Consume the identifier.
118 48: TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
119 48: ConsumeToken();
2: branch 1 taken
1: branch 2 taken
120 3: } else if (Tok.is(tok::kw_operator)) {
0: branch 1 not taken
2: branch 2 taken
121 2: if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType,
122 : TemplateName)) {
123 0: TPA.Commit();
124 7: break;
125 : }
126 :
0: branch 1 not taken
2: branch 2 taken
0: branch 4 not taken
0: branch 5 not taken
0: branch 6 not taken
2: branch 7 taken
127 2: if (TemplateName.getKind() != UnqualifiedId::IK_OperatorFunctionId &&
128 : TemplateName.getKind() != UnqualifiedId::IK_LiteralOperatorId) {
129 : Diag(TemplateName.getSourceRange().getBegin(),
130 : diag::err_id_after_template_in_nested_name_spec)
131 0: << TemplateName.getSourceRange();
132 0: TPA.Commit();
133 : break;
134 : }
135 : } else {
136 1: TPA.Revert();
137 : break;
138 : }
139 :
140 : // If the next token is not '<', we have a qualified-id that refers
141 : // to a template name, such as T::template apply, but is not a
142 : // template-id.
2: branch 1 taken
48: branch 2 taken
143 50: if (Tok.isNot(tok::less)) {
144 2: TPA.Revert();
145 : break;
146 : }
147 :
148 : // Commit to parsing the template-id.
149 48: TPA.Commit();
150 : TemplateTy Template
151 : = Actions.ActOnDependentTemplateName(TemplateKWLoc, SS, TemplateName,
152 48: ObjectType, EnteringContext);
4: branch 1 taken
44: branch 2 taken
153 48: if (!Template)
154 : break;
0: branch 1 not taken
44: branch 2 taken
155 44: if (AnnotateTemplateIdToken(Template, TNK_Dependent_template_name,
156 : &SS, TemplateName, TemplateKWLoc, false))
157 : break;
158 :
7: branch 1 taken
44: branch 2 taken
7: branch 4 taken
44: branch 5 taken
159 95: continue;
160 : }
161 :
2735: branch 1 taken
72073: branch 2 taken
795: branch 5 taken
1940: branch 6 taken
795: branch 7 taken
74013: branch 8 taken
162 74808: if (Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)) {
163 : // We have
164 : //
165 : // simple-template-id '::'
166 : //
167 : // So we need to check whether the simple-template-id is of the
168 : // right kind (it should name a type or be dependent), and then
169 : // convert it into a type within the nested-name-specifier.
170 : TemplateIdAnnotation *TemplateId
171 795: = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
172 :
12: branch 0 taken
783: branch 1 taken
12: branch 2 taken
0: branch 3 not taken
173 795: if (TemplateId->Kind == TNK_Type_template ||
174 : TemplateId->Kind == TNK_Dependent_template_name) {
175 795: AnnotateTemplateIdTokenAsType(&SS);
176 :
177 : assert(Tok.is(tok::annot_typename) &&
795: branch 1 taken
0: branch 2 not taken
178 795: "AnnotateTemplateIdTokenAsType isn't working");
179 795: Token TypeToken = Tok;
180 795: ConsumeToken();
795: branch 1 taken
0: branch 2 not taken
181 795: assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
182 795: SourceLocation CCLoc = ConsumeToken();
183 :
670: branch 0 taken
125: branch 1 taken
184 795: if (!HasScopeSpecifier) {
185 670: SS.setBeginLoc(TypeToken.getLocation());
186 670: HasScopeSpecifier = true;
187 : }
188 :
795: branch 1 taken
0: branch 2 not taken
189 795: if (TypeToken.getAnnotationValue())
190 : SS.setScopeRep(
191 : Actions.ActOnCXXNestedNameSpecifier(CurScope, SS,
192 : TypeToken.getAnnotationValue(),
193 : TypeToken.getAnnotationRange(),
194 795: CCLoc));
195 : else
196 0: SS.setScopeRep(0);
197 795: SS.setEndLoc(CCLoc);
198 795: continue;
199 : }
200 :
201 0: assert(false && "FIXME: Only type template names supported here");
202 : }
203 :
204 :
205 : // The rest of the nested-name-specifier possibilities start with
206 : // tok::identifier.
5929: branch 1 taken
68084: branch 2 taken
207 74013: if (Tok.isNot(tok::identifier))
208 5929: break;
209 :
210 68084: IdentifierInfo &II = *Tok.getIdentifierInfo();
211 :
212 : // nested-name-specifier:
213 : // type-name '::'
214 : // namespace-name '::'
215 : // nested-name-specifier identifier '::'
216 68084: Token Next = NextToken();
217 :
218 : // If we get foo:bar, this is almost certainly a typo for foo::bar. Recover
219 : // and emit a fixit hint for it.
879: branch 1 taken
67205: branch 2 taken
8: branch 3 taken
871: branch 4 taken
4: branch 6 taken
4: branch 7 taken
4: branch 10 taken
0: branch 11 not taken
4: branch 12 taken
68080: branch 13 taken
220 68084: if (Next.is(tok::colon) && !ColonIsSacred &&
221 : Actions.IsInvalidUnlessNestedName(CurScope, SS, II, ObjectType,
222 : EnteringContext) &&
223 : // If the token after the colon isn't an identifier, it's still an
224 : // error, but they probably meant something else strange so don't
225 : // recover like this.
226 : PP.LookAhead(1).is(tok::identifier)) {
227 : Diag(Next, diag::err_unexected_colon_in_nested_name_spec)
228 4: << CodeModificationHint::CreateReplacement(Next.getLocation(), "::");
229 :
230 : // Recover as if the user wrote '::'.
231 4: Next.setKind(tok::coloncolon);
232 : }
233 :
1623: branch 1 taken
66461: branch 2 taken
234 68084: if (Next.is(tok::coloncolon)) {
235 : // We have an identifier followed by a '::'. Lookup this name
236 : // as the name in a nested-name-specifier.
237 1623: SourceLocation IdLoc = ConsumeToken();
238 : assert((Tok.is(tok::coloncolon) || Tok.is(tok::colon)) &&
4: branch 1 taken
1619: branch 2 taken
4: branch 4 taken
0: branch 5 not taken
239 1623: "NextToken() not working properly!");
240 1623: SourceLocation CCLoc = ConsumeToken();
241 :
1436: branch 0 taken
187: branch 1 taken
242 1623: if (!HasScopeSpecifier) {
243 1436: SS.setBeginLoc(IdLoc);
244 1436: HasScopeSpecifier = true;
245 : }
246 :
2: branch 1 taken
1621: branch 2 taken
247 1623: if (SS.isInvalid())
248 2: continue;
249 :
250 : SS.setScopeRep(
251 : Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, II,
252 1621: ObjectType, EnteringContext));
253 1621: SS.setEndLoc(CCLoc);
254 1621: continue;
255 : }
256 :
257 : // nested-name-specifier:
258 : // type-name '<'
2713: branch 1 taken
63748: branch 2 taken
259 66461: if (Next.is(tok::less)) {
260 2713: TemplateTy Template;
261 2713: UnqualifiedId TemplateName;
262 2713: TemplateName.setIdentifier(&II, Tok.getLocation());
2496: branch 0 taken
217: branch 1 taken
263 2713: if (TemplateNameKind TNK = Actions.isTemplateName(CurScope, SS,
264 : TemplateName,
265 : ObjectType,
266 : EnteringContext,
267 2713: Template)) {
268 : // We have found a template name, so annotate this this token
269 : // with a template-id annotation. We do not permit the
270 : // template-id to be translated into a type annotation,
271 : // because some clients (e.g., the parsing of class template
272 : // specializations) still want to see the original template-id
273 : // token.
274 2496: ConsumeToken();
5: branch 2 taken
2491: branch 3 taken
275 2496: if (AnnotateTemplateIdToken(Template, TNK, &SS, TemplateName,
276 : SourceLocation(), false))
277 5: break;
278 2491: continue;
217: branch 1 taken
5: branch 2 taken
2491: branch 3 taken
279 2713: }
280 : }
281 :
282 : // We don't have any tokens that form the beginning of a
283 : // nested-name-specifier, so we're done.
284 63965: break;
285 : }
286 :
287 69907: return HasScopeSpecifier;
288 : }
289 :
290 : /// ParseCXXIdExpression - Handle id-expression.
291 : ///
292 : /// id-expression:
293 : /// unqualified-id
294 : /// qualified-id
295 : ///
296 : /// qualified-id:
297 : /// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
298 : /// '::' identifier
299 : /// '::' operator-function-id
300 : /// '::' template-id
301 : ///
302 : /// NOTE: The standard specifies that, for qualified-id, the parser does not
303 : /// expect:
304 : ///
305 : /// '::' conversion-function-id
306 : /// '::' '~' class-name
307 : ///
308 : /// This may cause a slight inconsistency on diagnostics:
309 : ///
310 : /// class C {};
311 : /// namespace A {}
312 : /// void f() {
313 : /// :: A :: ~ C(); // Some Sema error about using destructor with a
314 : /// // namespace.
315 : /// :: ~ C(); // Some Parser error like 'unexpected ~'.
316 : /// }
317 : ///
318 : /// We simplify the parser a bit and make it work like:
319 : ///
320 : /// qualified-id:
321 : /// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
322 : /// '::' unqualified-id
323 : ///
324 : /// That way Sema can handle and report similar errors for namespaces and the
325 : /// global scope.
326 : ///
327 : /// The isAddressOfOperand parameter indicates that this id-expression is a
328 : /// direct operand of the address-of operator. This is, besides member contexts,
329 : /// the only place where a qualified-id naming a non-static class member may
330 : /// appear.
331 : ///
332 661: Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
333 : // qualified-id:
334 : // '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
335 : // '::' unqualified-id
336 : //
337 661: CXXScopeSpec SS;
338 661: ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
339 :
340 661: UnqualifiedId Name;
8: branch 1 taken
653: branch 2 taken
341 661: if (ParseUnqualifiedId(SS,
342 : /*EnteringContext=*/false,
343 : /*AllowDestructorName=*/false,
344 : /*AllowConstructorName=*/false,
345 : /*ObjectType=*/0,
346 : Name))
347 8: return ExprError();
348 :
349 : // This is only the direct operand of an & operator if it is not
350 : // followed by a postfix-expression suffix.
130: branch 0 taken
523: branch 1 taken
351 653: if (isAddressOfOperand) {
6: branch 1 taken
124: branch 2 taken
352 130: switch (Tok.getKind()) {
353 : case tok::l_square:
354 : case tok::l_paren:
355 : case tok::arrow:
356 : case tok::period:
357 : case tok::plusplus:
358 : case tok::minusminus:
359 6: isAddressOfOperand = false;
360 : break;
361 :
362 : default:
363 : break;
364 : }
365 : }
366 :
367 : return Actions.ActOnIdExpression(CurScope, SS, Name, Tok.is(tok::l_paren),
368 653: isAddressOfOperand);
369 :
370 : }
371 :
372 : /// ParseCXXCasts - This handles the various ways to cast expressions to another
373 : /// type.
374 : ///
375 : /// postfix-expression: [C++ 5.2p1]
376 : /// 'dynamic_cast' '<' type-name '>' '(' expression ')'
377 : /// 'static_cast' '<' type-name '>' '(' expression ')'
378 : /// 'reinterpret_cast' '<' type-name '>' '(' expression ')'
379 : /// 'const_cast' '<' type-name '>' '(' expression ')'
380 : ///
381 252: Parser::OwningExprResult Parser::ParseCXXCasts() {
382 252: tok::TokenKind Kind = Tok.getKind();
383 252: const char *CastName = 0; // For error messages
384 :
0: branch 0 not taken
21: branch 1 taken
41: branch 2 taken
68: branch 3 taken
122: branch 4 taken
385 252: switch (Kind) {
386 0: default: assert(0 && "Unknown C++ cast!"); abort();
387 21: case tok::kw_const_cast: CastName = "const_cast"; break;
388 41: case tok::kw_dynamic_cast: CastName = "dynamic_cast"; break;
389 68: case tok::kw_reinterpret_cast: CastName = "reinterpret_cast"; break;
390 122: case tok::kw_static_cast: CastName = "static_cast"; break;
391 : }
392 :
393 252: SourceLocation OpLoc = ConsumeToken();
394 252: SourceLocation LAngleBracketLoc = Tok.getLocation();
395 :
0: branch 1 not taken
252: branch 2 taken
396 252: if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName))
397 0: return ExprError();
398 :
399 252: TypeResult CastTy = ParseTypeName();
400 252: SourceLocation RAngleBracketLoc = Tok.getLocation();
401 :
0: branch 1 not taken
252: branch 2 taken
402 252: if (ExpectAndConsume(tok::greater, diag::err_expected_greater))
403 0: return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << "<");
404 :
405 252: SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
406 :
0: branch 1 not taken
252: branch 2 taken
407 252: if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, CastName))
408 0: return ExprError();
409 :
410 252: OwningExprResult Result = ParseExpression();
411 :
412 : // Match the ')'.
413 252: RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
414 :
251: branch 1 taken
1: branch 2 taken
251: branch 4 taken
0: branch 5 not taken
251: branch 6 taken
1: branch 7 taken
415 252: if (!Result.isInvalid() && !CastTy.isInvalid())
416 : Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
417 : LAngleBracketLoc, CastTy.get(),
418 : RAngleBracketLoc,
419 251: LParenLoc, move(Result), RParenLoc);
420 :
421 252: return move(Result);
422 : }
423 :
424 : /// ParseCXXTypeid - This handles the C++ typeid expression.
425 : ///
426 : /// postfix-expression: [C++ 5.2p1]
427 : /// 'typeid' '(' expression ')'
428 : /// 'typeid' '(' type-id ')'
429 : ///
430 83: Parser::OwningExprResult Parser::ParseCXXTypeid() {
83: branch 1 taken
0: branch 2 not taken
431 83: assert(Tok.is(tok::kw_typeid) && "Not 'typeid'!");
432 :
433 83: SourceLocation OpLoc = ConsumeToken();
434 83: SourceLocation LParenLoc = Tok.getLocation();
435 83: SourceLocation RParenLoc;
436 :
437 : // typeid expressions are always parenthesized.
1: branch 1 taken
82: branch 2 taken
438 83: if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
439 : "typeid"))
440 1: return ExprError();
441 :
442 82: OwningExprResult Result(Actions);
443 :
73: branch 1 taken
9: branch 2 taken
444 82: if (isTypeIdInParens()) {
445 73: TypeResult Ty = ParseTypeName();
446 :
447 : // Match the ')'.
448 73: MatchRHSPunctuation(tok::r_paren, LParenLoc);
449 :
0: branch 1 not taken
73: branch 2 taken
450 73: if (Ty.isInvalid())
451 0: return ExprError();
452 :
453 : Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true,
454 73: Ty.get(), RParenLoc);
455 : } else {
456 : // C++0x [expr.typeid]p3:
457 : // When typeid is applied to an expression other than an lvalue of a
458 : // polymorphic class type [...] The expression is an unevaluated
459 : // operand (Clause 5).
460 : //
461 : // Note that we can't tell whether the expression is an lvalue of a
462 : // polymorphic class type until after we've parsed the expression, so
463 : // we the expression is potentially potentially evaluated.
464 : EnterExpressionEvaluationContext Unevaluated(Actions,
465 9: Action::PotentiallyPotentiallyEvaluated);
466 9: Result = ParseExpression();
467 :
468 : // Match the ')'.
0: branch 1 not taken
9: branch 2 taken
469 9: if (Result.isInvalid())
470 0: SkipUntil(tok::r_paren);
471 : else {
472 9: MatchRHSPunctuation(tok::r_paren, LParenLoc);
473 :
474 : Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false,
475 9: Result.release(), RParenLoc);
476 9: }
477 : }
478 :
479 82: return move(Result);
480 : }
481 :
482 : /// ParseCXXBoolLiteral - This handles the C++ Boolean literals.
483 : ///
484 : /// boolean-literal: [C++ 2.13.5]
485 : /// 'true'
486 : /// 'false'
487 141: Parser::OwningExprResult Parser::ParseCXXBoolLiteral() {
488 141: tok::TokenKind Kind = Tok.getKind();
489 141: return Actions.ActOnCXXBoolLiteral(ConsumeToken(), Kind);
490 : }
491 :
492 : /// ParseThrowExpression - This handles the C++ throw expression.
493 : ///
494 : /// throw-expression: [C++ 15]
495 : /// 'throw' assignment-expression[opt]
496 40: Parser::OwningExprResult Parser::ParseThrowExpression() {
40: branch 1 taken
0: branch 2 not taken
497 40: assert(Tok.is(tok::kw_throw) && "Not throw!");
498 40: SourceLocation ThrowLoc = ConsumeToken(); // Eat the throw token.
499 :
500 : // If the current token isn't the start of an assignment-expression,
501 : // then the expression is not present. This handles things like:
502 : // "C ? throw : (void)42", which is crazy but legal.
10: branch 1 taken
30: branch 2 taken
503 40: switch (Tok.getKind()) { // FIXME: move this predicate somewhere common.
504 : case tok::semi:
505 : case tok::r_paren:
506 : case tok::r_square:
507 : case tok::r_brace:
508 : case tok::colon:
509 : case tok::comma:
510 10: return Actions.ActOnCXXThrow(ThrowLoc, ExprArg(Actions));
511 :
512 : default:
513 30: OwningExprResult Expr(ParseAssignmentExpression());
0: branch 1 not taken
30: branch 2 taken
514 30: if (Expr.isInvalid()) return move(Expr);
515 30: return Actions.ActOnCXXThrow(ThrowLoc, move(Expr));
516 : }
517 : }
518 :
519 : /// ParseCXXThis - This handles the C++ 'this' pointer.
520 : ///
521 : /// C++ 9.3.2: In the body of a non-static member function, the keyword this is
522 : /// a non-lvalue expression whose value is the address of the object for which
523 : /// the function is called.
524 80: Parser::OwningExprResult Parser::ParseCXXThis() {
80: branch 1 taken
0: branch 2 not taken
525 80: assert(Tok.is(tok::kw_this) && "Not 'this'!");
526 80: SourceLocation ThisLoc = ConsumeToken();
527 80: return Actions.ActOnCXXThis(ThisLoc);
528 : }
529 :
530 : /// ParseCXXTypeConstructExpression - Parse construction of a specified type.
531 : /// Can be interpreted either as function-style casting ("int(x)")
532 : /// or class type construction ("ClassType(x,y,z)")
533 : /// or creation of a value-initialized type ("int()").
534 : ///
535 : /// postfix-expression: [C++ 5.2p1]
536 : /// simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3]
537 : /// typename-specifier '(' expression-list[opt] ')' [TODO]
538 : ///
539 : Parser::OwningExprResult
540 515: Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
541 515: Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
542 515: TypeTy *TypeRep = Actions.ActOnTypeName(CurScope, DeclaratorInfo).get();
543 :
515: branch 1 taken
0: branch 2 not taken
544 515: assert(Tok.is(tok::l_paren) && "Expected '('!");
545 515: SourceLocation LParenLoc = ConsumeParen();
546 :
547 515: ExprVector Exprs(Actions);
548 515: CommaLocsTy CommaLocs;
549 :
189: branch 1 taken
326: branch 2 taken
550 515: if (Tok.isNot(tok::r_paren)) {
0: branch 1 not taken
189: branch 2 taken
551 189: if (ParseExpressionList(Exprs, CommaLocs)) {
552 0: SkipUntil(tok::r_paren);
553 0: return ExprError();
554 : }
555 : }
556 :
557 : // Match the ')'.
558 515: SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
559 :
560 : // TypeRep could be null, if it references an invalid typedef.
0: branch 0 not taken
515: branch 1 taken
561 515: if (!TypeRep)
562 0: return ExprError();
563 :
564 : assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&&
189: branch 1 taken
326: branch 2 taken
189: branch 5 taken
0: branch 6 not taken
565 515: "Unexpected number of commas!");
566 : return Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep,
567 : LParenLoc, move_arg(Exprs),
568 1030: CommaLocs.data(), RParenLoc);
569 : }
570 :
571 : /// ParseCXXCondition - if/switch/while condition expression.
572 : ///
573 : /// condition:
574 : /// expression
575 : /// type-specifier-seq declarator '=' assignment-expression
576 : /// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
577 : /// '=' assignment-expression
578 : ///
579 : /// \param ExprResult if the condition was parsed as an expression, the
580 : /// parsed expression.
581 : ///
582 : /// \param DeclResult if the condition was parsed as a declaration, the
583 : /// parsed declaration.
584 : ///
585 : /// \returns true if there was a parsing, false otherwise.
586 : bool Parser::ParseCXXCondition(OwningExprResult &ExprResult,
587 365: DeclPtrTy &DeclResult) {
0: branch 1 not taken
365: branch 2 taken
588 365: if (Tok.is(tok::code_completion)) {
589 0: Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Condition);
590 0: ConsumeToken();
591 : }
592 :
305: branch 1 taken
60: branch 2 taken
593 365: if (!isCXXConditionDeclaration()) {
594 305: ExprResult = ParseExpression(); // expression
595 305: DeclResult = DeclPtrTy();
596 305: return ExprResult.isInvalid();
597 : }
598 :
599 : // type-specifier-seq
600 60: DeclSpec DS;
601 60: ParseSpecifierQualifierList(DS);
602 :
603 : // declarator
604 60: Declarator DeclaratorInfo(DS, Declarator::ConditionContext);
605 60: ParseDeclarator(DeclaratorInfo);
606 :
607 : // simple-asm-expr[opt]
0: branch 1 not taken
60: branch 2 taken
608 60: if (Tok.is(tok::kw_asm)) {
609 0: SourceLocation Loc;
610 0: OwningExprResult AsmLabel(ParseSimpleAsm(&Loc));
0: branch 1 not taken
0: branch 2 not taken
611 0: if (AsmLabel.isInvalid()) {
612 0: SkipUntil(tok::semi);
613 0: return true;
614 : }
615 0: DeclaratorInfo.setAsmLabel(AsmLabel.release());
0: branch 2 not taken
0: branch 3 not taken
616 0: DeclaratorInfo.SetRangeEnd(Loc);
617 : }
618 :
619 : // If attributes are present, parse them.
0: branch 1 not taken
60: branch 2 taken
620 60: if (Tok.is(tok::kw___attribute)) {
621 0: SourceLocation Loc;
622 0: AttributeList *AttrList = ParseGNUAttributes(&Loc);
623 0: DeclaratorInfo.AddAttributes(AttrList, Loc);
624 : }
625 :
626 : // Type-check the declaration itself.
627 : Action::DeclResult Dcl = Actions.ActOnCXXConditionDeclaration(CurScope,
628 60: DeclaratorInfo);
629 60: DeclResult = Dcl.get();
630 60: ExprResult = ExprError();
631 :
632 : // '=' assignment-expression
59: branch 1 taken
1: branch 2 taken
633 60: if (Tok.is(tok::equal)) {
634 59: SourceLocation EqualLoc = ConsumeToken();
635 59: OwningExprResult AssignExpr(ParseAssignmentExpression());
59: branch 1 taken
0: branch 2 not taken
636 59: if (!AssignExpr.isInvalid())
637 59: Actions.AddInitializerToDecl(DeclResult, move(AssignExpr));
638 : } else {
639 : // FIXME: C++0x allows a braced-init-list
640 1: Diag(Tok, diag::err_expected_equal_after_declarator);
641 : }
642 :
643 60: return false;
644 : }
645 :
646 : /// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers.
647 : /// This should only be called when the current token is known to be part of
648 : /// simple-type-specifier.
649 : ///
650 : /// simple-type-specifier:
651 : /// '::'[opt] nested-name-specifier[opt] type-name
652 : /// '::'[opt] nested-name-specifier 'template' simple-template-id [TODO]
653 : /// char
654 : /// wchar_t
655 : /// bool
656 : /// short
657 : /// int
658 : /// long
659 : /// signed
660 : /// unsigned
661 : /// float
662 : /// double
663 : /// void
664 : /// [GNU] typeof-specifier
665 : /// [C++0x] auto [TODO]
666 : ///
667 : /// type-name:
668 : /// class-name
669 : /// enum-name
670 : /// typedef-name
671 : ///
672 517: void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
673 517: DS.SetRangeStart(Tok.getLocation());
674 : const char *PrevSpec;
675 : unsigned DiagID;
676 517: SourceLocation Loc = Tok.getLocation();
677 :
0: branch 1 not taken
0: branch 2 not taken
461: branch 3 taken
0: branch 4 not taken
2: branch 5 taken
0: branch 6 not taken
2: branch 7 taken
5: branch 8 taken
3: branch 9 taken
29: branch 10 taken
7: branch 11 taken
3: branch 12 taken
0: branch 13 not taken
0: branch 14 not taken
0: branch 15 not taken
1: branch 16 taken
4: branch 17 taken
678 517: switch (Tok.getKind()) {
679 : case tok::identifier: // foo::bar
680 : case tok::coloncolon: // ::foo::bar
681 0: assert(0 && "Annotation token should already be formed!");
682 : default:
683 0: assert(0 && "Not a simple-type-specifier token!");
684 : abort();
685 :
686 : // type-name
687 : case tok::annot_typename: {
688 : DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID,
689 461: Tok.getAnnotationValue());
690 461: break;
691 : }
692 :
693 : // builtin types
694 : case tok::kw_short:
695 0: DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, DiagID);
696 0: break;
697 : case tok::kw_long:
698 2: DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec, DiagID);
699 2: break;
700 : case tok::kw_signed:
701 0: DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec, DiagID);
702 0: break;
703 : case tok::kw_unsigned:
704 2: DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec, DiagID);
705 2: break;
706 : case tok::kw_void:
707 5: DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, DiagID);
708 5: break;
709 : case tok::kw_char:
710 3: DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, DiagID);
711 3: break;
712 : case tok::kw_int:
713 29: DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID);
714 29: break;
715 : case tok::kw_float:
716 7: DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID);
717 7: break;
718 : case tok::kw_double:
719 3: DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID);
720 3: break;
721 : case tok::kw_wchar_t:
722 0: DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID);
723 0: break;
724 : case tok::kw_char16_t:
725 0: DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, DiagID);
726 0: break;
727 : case tok::kw_char32_t:
728 0: DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec, DiagID);
729 0: break;
730 : case tok::kw_bool:
731 1: DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, DiagID);
732 1: break;
733 :
734 : // GNU typeof support.
735 : case tok::kw_typeof:
736 4: ParseTypeofSpecifier(DS);
737 4: DS.Finish(Diags, PP);
738 4: return;
739 : }
461: branch 1 taken
52: branch 2 taken
740 513: if (Tok.is(tok::annot_typename))
741 461: DS.SetRangeEnd(Tok.getAnnotationEndLoc());
742 : else
743 52: DS.SetRangeEnd(Tok.getLocation());
744 513: ConsumeToken();
745 513: DS.Finish(Diags, PP);
746 : }
747 :
748 : /// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++
749 : /// [dcl.name]), which is a non-empty sequence of type-specifiers,
750 : /// e.g., "const short int". Note that the DeclSpec is *not* finished
751 : /// by parsing the type-specifier-seq, because these sequences are
752 : /// typically followed by some form of declarator. Returns true and
753 : /// emits diagnostics if this is not a type-specifier-seq, false
754 : /// otherwise.
755 : ///
756 : /// type-specifier-seq: [C++ 8.1]
757 : /// type-specifier type-specifier-seq[opt]
758 : ///
759 417: bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
760 417: DS.SetRangeStart(Tok.getLocation());
761 417: const char *PrevSpec = 0;
762 : unsigned DiagID;
763 417: bool isInvalid = 0;
764 :
765 : // Parse one or more of the type specifiers.
8: branch 2 taken
409: branch 3 taken
766 417: if (!ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
767 : ParsedTemplateInfo(), /*SuppressDeclarations*/true)) {
768 8: Diag(Tok, diag::err_operator_missing_type_specifier);
769 8: return true;
770 : }
771 :
31: branch 2 taken
409: branch 3 taken
772 440: while (ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
773 : ParsedTemplateInfo(), /*SuppressDeclarations*/true))
774 : {}
775 :
776 409: return false;
777 : }
778 :
779 : /// \brief Finish parsing a C++ unqualified-id that is a template-id of
780 : /// some form.
781 : ///
782 : /// This routine is invoked when a '<' is encountered after an identifier or
783 : /// operator-function-id is parsed by \c ParseUnqualifiedId() to determine
784 : /// whether the unqualified-id is actually a template-id. This routine will
785 : /// then parse the template arguments and form the appropriate template-id to
786 : /// return to the caller.
787 : ///
788 : /// \param SS the nested-name-specifier that precedes this template-id, if
789 : /// we're actually parsing a qualified-id.
790 : ///
791 : /// \param Name for constructor and destructor names, this is the actual
792 : /// identifier that may be a template-name.
793 : ///
794 : /// \param NameLoc the location of the class-name in a constructor or
795 : /// destructor.
796 : ///
797 : /// \param EnteringContext whether we're entering the scope of the
798 : /// nested-name-specifier.
799 : ///
800 : /// \param ObjectType if this unqualified-id occurs within a member access
801 : /// expression, the type of the base object whose member is being accessed.
802 : ///
803 : /// \param Id as input, describes the template-name or operator-function-id
804 : /// that precedes the '<'. If template arguments were parsed successfully,
805 : /// will be updated with the template-id.
806 : ///
807 : /// \returns true if a parse error occurred, false otherwise.
808 : bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
809 : IdentifierInfo *Name,
810 : SourceLocation NameLoc,
811 : bool EnteringContext,
812 : TypeTy *ObjectType,
813 7: UnqualifiedId &Id) {
7: branch 1 taken
0: branch 2 not taken
814 7: assert(Tok.is(tok::less) && "Expected '<' to finish parsing a template-id");
815 :
816 7: TemplateTy Template;
817 7: TemplateNameKind TNK = TNK_Non_template;
6: branch 1 taken
0: branch 2 not taken
1: branch 3 taken
0: branch 4 not taken
818 7: switch (Id.getKind()) {
819 : case UnqualifiedId::IK_Identifier:
820 : case UnqualifiedId::IK_OperatorFunctionId:
821 : case UnqualifiedId::IK_LiteralOperatorId:
822 : TNK = Actions.isTemplateName(CurScope, SS, Id, ObjectType, EnteringContext,
823 6: Template);
824 6: break;
825 :
826 : case UnqualifiedId::IK_ConstructorName: {
827 0: UnqualifiedId TemplateName;
828 0: TemplateName.setIdentifier(Name, NameLoc);
829 : TNK = Actions.isTemplateName(CurScope, SS, TemplateName, ObjectType,
830 0: EnteringContext, Template);
831 0: break;
832 : }
833 :
834 : case UnqualifiedId::IK_DestructorName: {
835 1: UnqualifiedId TemplateName;
836 1: TemplateName.setIdentifier(Name, NameLoc);
1: branch 0 taken
0: branch 1 not taken
837 1: if (ObjectType) {
838 : Template = Actions.ActOnDependentTemplateName(SourceLocation(), SS,
839 : TemplateName, ObjectType,
840 1: EnteringContext);
841 1: TNK = TNK_Dependent_template_name;
0: branch 1 not taken
1: branch 2 taken
842 1: if (!Template.get())
843 0: return true;
844 : } else {
845 : TNK = Actions.isTemplateName(CurScope, SS, TemplateName, ObjectType,
846 0: EnteringContext, Template);
847 :
0: branch 0 not taken
0: branch 1 not taken
0: branch 2 not taken
0: branch 3 not taken
848 0: if (TNK == TNK_Non_template && Id.DestructorName == 0) {
849 : // The identifier following the destructor did not refer to a template
850 : // or to a type. Complain.
0: branch 0 not taken
0: branch 1 not taken
851 0: if (ObjectType)
852 : Diag(NameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
853 0: << Name;
854 : else
855 0: Diag(NameLoc, diag::err_destructor_class_name);
856 0: return true;
857 : }
858 : }
0: branch 1 not taken
1: branch 2 taken
859 2: break;
860 : }
861 :
862 : default:
863 0: return false;
864 : }
865 :
3: branch 0 taken
4: branch 1 taken
866 7: if (TNK == TNK_Non_template)
867 3: return false;
868 :
869 : // Parse the enclosed template argument list.
870 4: SourceLocation LAngleLoc, RAngleLoc;
871 4: TemplateArgList TemplateArgs;
0: branch 1 not taken
4: branch 2 taken
872 4: if (ParseTemplateIdAfterTemplateName(Template, Id.StartLocation,
873 : &SS, true, LAngleLoc,
874 : TemplateArgs,
875 : RAngleLoc))
876 0: return true;
877 :
4: branch 1 taken
0: branch 2 not taken
1: branch 4 taken
3: branch 5 taken
0: branch 7 not taken
1: branch 8 taken
3: branch 9 taken
1: branch 10 taken
878 4: if (Id.getKind() == UnqualifiedId::IK_Identifier ||
879 : Id.getKind() == UnqualifiedId::IK_OperatorFunctionId ||
880 : Id.getKind() == UnqualifiedId::IK_LiteralOperatorId) {
881 : // Form a parsed representation of the template-id to be stored in the
882 : // UnqualifiedId.
883 : TemplateIdAnnotation *TemplateId
884 3: = TemplateIdAnnotation::Allocate(TemplateArgs.size());
885 :
0: branch 1 not taken
3: branch 2 taken
886 3: if (Id.getKind() == UnqualifiedId::IK_Identifier) {
887 0: TemplateId->Name = Id.Identifier;
888 0: TemplateId->Operator = OO_None;
889 0: TemplateId->TemplateNameLoc = Id.StartLocation;
890 : } else {
891 3: TemplateId->Name = 0;
892 3: TemplateId->Operator = Id.OperatorFunctionId.Operator;
893 3: TemplateId->TemplateNameLoc = Id.StartLocation;
894 : }
895 :
896 3: TemplateId->Template = Template.getAs<void*>();
897 3: TemplateId->Kind = TNK;
898 3: TemplateId->LAngleLoc = LAngleLoc;
899 3: TemplateId->RAngleLoc = RAngleLoc;
900 3: ParsedTemplateArgument *Args = TemplateId->getTemplateArgs();
4: branch 1 taken
3: branch 2 taken
901 7: for (unsigned Arg = 0, ArgEnd = TemplateArgs.size();
902 : Arg != ArgEnd; ++Arg)
903 4: Args[Arg] = TemplateArgs[Arg];
904 :
905 3: Id.setTemplateId(TemplateId);
906 3: return false;
907 : }
908 :
909 : // Bundle the template arguments together.
910 : ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(),
911 1: TemplateArgs.size());
912 :
913 : // Constructor and destructor names.
914 : Action::TypeResult Type
915 : = Actions.ActOnTemplateIdType(Template, NameLoc,
916 : LAngleLoc, TemplateArgsPtr,
917 1: RAngleLoc);
0: branch 1 not taken
1: branch 2 taken
918 1: if (Type.isInvalid())
919 0: return true;
920 :
0: branch 1 not taken
1: branch 2 taken
921 1: if (Id.getKind() == UnqualifiedId::IK_ConstructorName)
922 0: Id.setConstructorName(Type.get(), NameLoc, RAngleLoc);
923 : else
924 1: Id.setDestructorName(Id.StartLocation, Type.get(), RAngleLoc);
925 :
926 1: return false;
927 : }
928 :
929 : /// \brief Parse an operator-function-id or conversion-function-id as part
930 : /// of a C++ unqualified-id.
931 : ///
932 : /// This routine is responsible only for parsing the operator-function-id or
933 : /// conversion-function-id; it does not handle template arguments in any way.
934 : ///
935 : /// \code
936 : /// operator-function-id: [C++ 13.5]
937 : /// 'operator' operator
938 : ///
939 : /// operator: one of
940 : /// new delete new[] delete[]
941 : /// + - * / % ^ & | ~
942 : /// ! = < > += -= *= /= %=
943 : /// ^= &= |= << >> >>= <<= == !=
944 : /// <= >= && || ++ -- , ->* ->
945 : /// () []
946 : ///
947 : /// conversion-function-id: [C++ 12.3.2]
948 : /// operator conversion-type-id
949 : ///
950 : /// conversion-type-id:
951 : /// type-specifier-seq conversion-declarator[opt]
952 : ///
953 : /// conversion-declarator:
954 : /// ptr-operator conversion-declarator[opt]
955 : /// \endcode
956 : ///
957 : /// \param The nested-name-specifier that preceded this unqualified-id. If
958 : /// non-empty, then we are parsing the unqualified-id of a qualified-id.
959 : ///
960 : /// \param EnteringContext whether we are entering the scope of the
961 : /// nested-name-specifier.
962 : ///
963 : /// \param ObjectType if this unqualified-id occurs within a member access
964 : /// expression, the type of the base object whose member is being accessed.
965 : ///
966 : /// \param Result on a successful parse, contains the parsed unqualified-id.
967 : ///
968 : /// \returns true if parsing fails, false otherwise.
969 : bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
970 : TypeTy *ObjectType,
971 608: UnqualifiedId &Result) {
608: branch 1 taken
0: branch 2 not taken
972 608: assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
973 :
974 : // Consume the 'operator' keyword.
975 608: SourceLocation KeywordLoc = ConsumeToken();
976 :
977 : // Determine what kind of operator name we have.
978 608: unsigned SymbolIdx = 0;
1824: branch 1 taken
608: branch 2 taken
979 2432: SourceLocation SymbolLocations[3];
980 608: OverloadedOperatorKind Op = OO_None;
59: branch 1 taken
52: branch 2 taken
11: branch 3 taken
8: branch 4 taken
2: branch 5 taken
1: branch 6 taken
0: branch 7 not taken
3: branch 8 taken
2: branch 9 taken
0: branch 10 not taken
3: branch 11 taken
38: branch 12 taken
0: branch 13 not taken
0: branch 14 not taken
8: branch 15 taken
0: branch 16 not taken
0: branch 17 not taken
0: branch 18 not taken
0: branch 19 not taken
0: branch 20 not taken
0: branch 21 not taken
0: branch 22 not taken
3: branch 23 taken
0: branch 24 not taken
0: branch 25 not taken
0: branch 26 not taken
27: branch 27 taken
7: branch 28 taken
0: branch 29 not taken
0: branch 30 not taken
0: branch 31 not taken
0: branch 32 not taken
12: branch 33 taken
5: branch 34 taken
1: branch 35 taken
1: branch 36 taken
14: branch 37 taken
28: branch 38 taken
14: branch 39 taken
1: branch 40 taken
308: branch 41 taken
981 608: switch (Tok.getKind()) {
982 : case tok::kw_new:
983 : case tok::kw_delete: {
984 59: bool isNew = Tok.getKind() == tok::kw_new;
985 : // Consume the 'new' or 'delete'.
986 59: SymbolLocations[SymbolIdx++] = ConsumeToken();
6: branch 1 taken
53: branch 2 taken
987 59: if (Tok.is(tok::l_square)) {
988 : // Consume the '['.
989 6: SourceLocation LBracketLoc = ConsumeBracket();
990 : // Consume the ']'.
991 : SourceLocation RBracketLoc = MatchRHSPunctuation(tok::r_square,
992 6: LBracketLoc);
0: branch 1 not taken
6: branch 2 taken
993 6: if (RBracketLoc.isInvalid())
994 0: return true;
995 :
996 6: SymbolLocations[SymbolIdx++] = LBracketLoc;
997 6: SymbolLocations[SymbolIdx++] = RBracketLoc;
4: branch 0 taken
2: branch 1 taken
998 6: Op = isNew? OO_Array_New : OO_Array_Delete;
999 : } else {
32: branch 0 taken
21: branch 1 taken
1000 53: Op = isNew? OO_New : OO_Delete;
1001 : }
1002 59: break;
1003 : }
1004 :
1005 : #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
1006 : case tok::Token: \
1007 : SymbolLocations[SymbolIdx++] = ConsumeToken(); \
1008 : Op = OO_##Name; \
1009 : break;
1010 : #define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
1011 : #include "clang/Basic/OperatorKinds.def"
1012 :
1013 : case tok::l_paren: {
1014 : // Consume the '('.
1015 28: SourceLocation LParenLoc = ConsumeParen();
1016 : // Consume the ')'.
1017 : SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren,
1018 28: LParenLoc);
0: branch 1 not taken
28: branch 2 taken
1019 28: if (RParenLoc.isInvalid())
1020 0: return true;
1021 :
1022 28: SymbolLocations[SymbolIdx++] = LParenLoc;
1023 28: SymbolLocations[SymbolIdx++] = RParenLoc;
1024 28: Op = OO_Call;
1025 28: break;
1026 : }
1027 :
1028 : case tok::l_square: {
1029 : // Consume the '['.
1030 14: SourceLocation LBracketLoc = ConsumeBracket();
1031 : // Consume the ']'.
1032 : SourceLocation RBracketLoc = MatchRHSPunctuation(tok::r_square,
1033 14: LBracketLoc);
0: branch 1 not taken
14: branch 2 taken
1034 14: if (RBracketLoc.isInvalid())
1035 0: return true;
1036 :
1037 14: SymbolLocations[SymbolIdx++] = LBracketLoc;
1038 14: SymbolLocations[SymbolIdx++] = RBracketLoc;
1039 14: Op = OO_Subscript;
1040 14: break;
1041 : }
1042 :
1043 : case tok::code_completion: {
1044 : // Code completion for the operator name.
1045 1: Actions.CodeCompleteOperatorName(CurScope);
1046 :
1047 : // Consume the operator token.
1048 1: ConsumeToken();
1049 :
1050 : // Don't try to parse any further.
1051 1: return true;
1052 : }
1053 :
1054 : default:
1055 : break;
1056 : }
1057 :
299: branch 0 taken
308: branch 1 taken
1058 607: if (Op != OO_None) {
1059 : // We have parsed an operator-function-id.
1060 299: Result.setOperatorFunctionId(KeywordLoc, Op, SymbolLocations);
1061 299: return false;
1062 : }
1063 :
1064 : // Parse a literal-operator-id.
1065 : //
1066 : // literal-operator-id: [C++0x 13.5.8]
1067 : // operator "" identifier
1068 :
113: branch 1 taken
195: branch 2 taken
22: branch 4 taken
91: branch 5 taken
22: branch 6 taken
286: branch 7 taken
1069 308: if (getLang().CPlusPlus0x && Tok.is(tok::string_literal)) {
1: branch 1 taken
21: branch 2 taken
1070 22: if (Tok.getLength() != 2)
1071 1: Diag(Tok.getLocation(), diag::err_operator_string_not_empty);
1072 22: ConsumeStringToken();
1073 :
1: branch 1 taken
21: branch 2 taken
1074 22: if (Tok.isNot(tok::identifier)) {
1075 1: Diag(Tok.getLocation(), diag::err_expected_ident);
1076 1: return true;
1077 : }
1078 :
1079 21: IdentifierInfo *II = Tok.getIdentifierInfo();
1080 21: Result.setLiteralOperatorId(II, KeywordLoc, ConsumeToken());
1081 21: return false;
1082 : }
1083 :
1084 : // Parse a conversion-function-id.
1085 : //
1086 : // conversion-function-id: [C++ 12.3.2]
1087 : // operator conversion-type-id
1088 : //
1089 : // conversion-type-id:
1090 : // type-specifier-seq conversion-declarator[opt]
1091 : //
1092 : // conversion-declarator:
1093 : // ptr-operator conversion-declarator[opt]
1094 :
1095 : // Parse the type-specifier-seq.
1096 286: DeclSpec DS;
6: branch 1 taken
280: branch 2 taken
1097 286: if (ParseCXXTypeSpecifierSeq(DS)) // FIXME: ObjectType?
1098 6: return true;
1099 :
1100 : // Parse the conversion-declarator, which is merely a sequence of
1101 : // ptr-operators.
1102 280: Declarator D(DS, Declarator::TypeNameContext);
1103 280: ParseDeclaratorInternal(D, /*DirectDeclParser=*/0);
1104 :
1105 : // Finish up the type.
1106 280: Action::TypeResult Ty = Actions.ActOnTypeName(CurScope, D);
0: branch 1 not taken
280: branch 2 taken
1107 280: if (Ty.isInvalid())
1108 0: return true;
1109 :
1110 : // Note that this is a conversion-function-id.
1111 : Result.setConversionFunctionId(KeywordLoc, Ty.get(),
1112 280: D.getSourceRange().getEnd());
1113 280: return false;
1114 : }
1115 :
1116 : /// \brief Parse a C++ unqualified-id (or a C identifier), which describes the
1117 : /// name of an entity.
1118 : ///
1119 : /// \code
1120 : /// unqualified-id: [C++ expr.prim.general]
1121 : /// identifier
1122 : /// operator-function-id
1123 : /// conversion-function-id
1124 : /// [C++0x] literal-operator-id [TODO]
1125 : /// ~ class-name
1126 : /// template-id
1127 : ///
1128 : /// \endcode
1129 : ///
1130 : /// \param The nested-name-specifier that preceded this unqualified-id. If
1131 : /// non-empty, then we are parsing the unqualified-id of a qualified-id.
1132 : ///
1133 : /// \param EnteringContext whether we are entering the scope of the
1134 : /// nested-name-specifier.
1135 : ///
1136 : /// \param AllowDestructorName whether we allow parsing of a destructor name.
1137 : ///
1138 : /// \param AllowConstructorName whether we allow parsing a constructor name.
1139 : ///
1140 : /// \param ObjectType if this unqualified-id occurs within a member access
1141 : /// expression, the type of the base object whose member is being accessed.
1142 : ///
1143 : /// \param Result on a successful parse, contains the parsed unqualified-id.
1144 : ///
1145 : /// \returns true if parsing fails, false otherwise.
1146 : bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
1147 : bool AllowDestructorName,
1148 : bool AllowConstructorName,
1149 : TypeTy *ObjectType,
1150 19930: UnqualifiedId &Result) {
1151 : // unqualified-id:
1152 : // identifier
1153 : // template-id (when it hasn't already been annotated)
18858: branch 1 taken
1072: branch 2 taken
1154 19930: if (Tok.is(tok::identifier)) {
1155 : // Consume the identifier.
1156 18858: IdentifierInfo *Id = Tok.getIdentifierInfo();
1157 18858: SourceLocation IdLoc = ConsumeToken();
1158 :
1310: branch 1 taken
17548: branch 2 taken
1159 18858: if (!getLang().CPlusPlus) {
1160 : // If we're not in C++, only identifiers matter. Record the
1161 : // identifier and return.
1162 1310: Result.setIdentifier(Id, IdLoc);
1163 1310: return false;
1164 : }
1165 :
774: branch 0 taken
16774: branch 1 taken
649: branch 3 taken
125: branch 4 taken
649: branch 5 taken
16899: branch 6 taken
1166 17548: if (AllowConstructorName &&
1167 : Actions.isCurrentClassName(*Id, CurScope, &SS)) {
1168 : // We have parsed a constructor name.
1169 : Result.setConstructorName(Actions.getTypeName(*Id, IdLoc, CurScope,
1170 : &SS, false),
1171 649: IdLoc, IdLoc);
1172 : } else {
1173 : // We have parsed an identifier.
1174 16899: Result.setIdentifier(Id, IdLoc);
1175 : }
1176 :
1177 : // If the next token is a '<', we may have a template.
3: branch 1 taken
17545: branch 2 taken
1178 17548: if (Tok.is(tok::less))
1179 : return ParseUnqualifiedIdTemplateId(SS, Id, IdLoc, EnteringContext,
1180 3: ObjectType, Result);
1181 :
1182 17545: return false;
1183 : }
1184 :
1185 : // unqualified-id:
1186 : // template-id (already parsed and annotated)
234: branch 1 taken
838: branch 2 taken
1187 1072: if (Tok.is(tok::annot_template_id)) {
1188 : TemplateIdAnnotation *TemplateId
1189 234: = static_cast<TemplateIdAnnotation*>(Tok.getAnnotationValue());
1190 :
1191 : // If the template-name names the current class, then this is a constructor
10: branch 0 taken
224: branch 1 taken
10: branch 2 taken
0: branch 3 not taken
7: branch 5 taken
3: branch 6 taken
7: branch 7 taken
227: branch 8 taken
1192 234: if (AllowConstructorName && TemplateId->Name &&
1193 : Actions.isCurrentClassName(*TemplateId->Name, CurScope, &SS)) {
2: branch 1 taken
5: branch 2 taken
1194 7: if (SS.isSet()) {
1195 : // C++ [class.qual]p2 specifies that a qualified template-name
1196 : // is taken as the constructor name where a constructor can be
1197 : // declared. Thus, the template arguments are extraneous, so
1198 : // complain about them and remove them entirely.
1199 : Diag(TemplateId->TemplateNameLoc,
1200 : diag::err_out_of_line_constructor_template_id)
1201 : << TemplateId->Name
1202 : << CodeModificationHint::CreateRemoval(
1203 2: SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc));
1204 : Result.setConstructorName(Actions.getTypeName(*TemplateId->Name,
1205 : TemplateId->TemplateNameLoc,
1206 : CurScope,
1207 : &SS, false),
1208 : TemplateId->TemplateNameLoc,
1209 2: TemplateId->RAngleLoc);
1210 2: TemplateId->Destroy();
1211 2: ConsumeToken();
1212 2: return false;
1213 : }
1214 :
1215 5: Result.setConstructorTemplateId(TemplateId);
1216 5: ConsumeToken();
1217 5: return false;
1218 : }
1219 :
1220 : // We have already parsed a template-id; consume the annotation token as
1221 : // our unqualified-id.
1222 227: Result.setTemplateId(TemplateId);
1223 227: ConsumeToken();
1224 227: return false;
1225 : }
1226 :
1227 : // unqualified-id:
1228 : // operator-function-id
1229 : // conversion-function-id
606: branch 1 taken
232: branch 2 taken
1230 838: if (Tok.is(tok::kw_operator)) {
8: branch 1 taken
598: branch 2 taken
1231 606: if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType, Result))
1232 8: return true;
1233 :
1234 : // If we have an operator-function-id or a literal-operator-id and the next
1235 : // token is a '<', we may have a
1236 : //
1237 : // template-id:
1238 : // operator-function-id < template-argument-list[opt] >
301: branch 1 taken
297: branch 2 taken
21: branch 4 taken
280: branch 5 taken
3: branch 7 taken
315: branch 8 taken
3: branch 9 taken
595: branch 10 taken
1239 598: if ((Result.getKind() == UnqualifiedId::IK_OperatorFunctionId ||
1240 : Result.getKind() == UnqualifiedId::IK_LiteralOperatorId) &&
1241 : Tok.is(tok::less))
1242 : return ParseUnqualifiedIdTemplateId(SS, 0, SourceLocation(),
1243 : EnteringContext, ObjectType,
1244 3: Result);
1245 :
1246 595: return false;
1247 : }
1248 :
226: branch 1 taken
6: branch 2 taken
7: branch 3 taken
219: branch 4 taken
7: branch 6 taken
0: branch 7 not taken
211: branch 9 taken
15: branch 10 taken
211: branch 11 taken
21: branch 12 taken
1249 232: if (getLang().CPlusPlus &&
1250 : (AllowDestructorName || SS.isSet()) && Tok.is(tok::tilde)) {
1251 : // C++ [expr.unary.op]p10:
1252 : // There is an ambiguity in the unary-expression ~X(), where X is a
1253 : // class-name. The ambiguity is resolved in favor of treating ~ as a
1254 : // unary complement rather than treating ~X as referring to a destructor.
1255 :
1256 : // Parse the '~'.
1257 211: SourceLocation TildeLoc = ConsumeToken();
1258 :
1259 : // Parse the class-name.
4: branch 1 taken
207: branch 2 taken
1260 211: if (Tok.isNot(tok::identifier)) {
1261 4: Diag(Tok, diag::err_destructor_class_name);
1262 4: return true;
1263 : }
1264 :
1265 : // Parse the class-name (or template-name in a simple-template-id).
1266 207: IdentifierInfo *ClassName = Tok.getIdentifierInfo();
1267 207: SourceLocation ClassNameLoc = ConsumeToken();
1268 :
1: branch 1 taken
206: branch 2 taken
1269 207: if (Tok.is(tok::less)) {
1270 1: Result.setDestructorName(TildeLoc, 0, ClassNameLoc);
1271 : return ParseUnqualifiedIdTemplateId(SS, ClassName, ClassNameLoc,
1272 1: EnteringContext, ObjectType, Result);
1273 : }
1274 :
1275 : // Note that this is a destructor name.
1276 : Action::TypeTy *Ty = Actions.getTypeName(*ClassName, ClassNameLoc,
1277 206: CurScope, &SS, false, ObjectType);
2: branch 0 taken
204: branch 1 taken
1278 206: if (!Ty) {
1: branch 0 taken
1: branch 1 taken
1279 2: if (ObjectType)
1280 : Diag(ClassNameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
1281 1: << ClassName;
1282 : else
1283 1: Diag(ClassNameLoc, diag::err_destructor_class_name);
1284 2: return true;
1285 : }
1286 :
1287 204: Result.setDestructorName(TildeLoc, Ty, ClassNameLoc);
1288 204: return false;
1289 : }
1290 :
1291 : Diag(Tok, diag::err_expected_unqualified_id)
1292 21: << getLang().CPlusPlus;
1293 21: return true;
1294 : }
1295 :
1296 : /// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate
1297 : /// memory in a typesafe manner and call constructors.
1298 : ///
1299 : /// This method is called to parse the new expression after the optional :: has
1300 : /// been already parsed. If the :: was present, "UseGlobal" is true and "Start"
1301 : /// is its location. Otherwise, "Start" is the location of the 'new' token.
1302 : ///
1303 : /// new-expression:
1304 : /// '::'[opt] 'new' new-placement[opt] new-type-id
1305 : /// new-initializer[opt]
1306 : /// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
1307 : /// new-initializer[opt]
1308 : ///
1309 : /// new-placement:
1310 : /// '(' expression-list ')'
1311 : ///
1312 : /// new-type-id:
1313 : /// type-specifier-seq new-declarator[opt]
1314 : ///
1315 : /// new-declarator:
1316 : /// ptr-operator new-declarator[opt]
1317 : /// direct-new-declarator
1318 : ///
1319 : /// new-initializer:
1320 : /// '(' expression-list[opt] ')'
1321 : /// [C++0x] braced-init-list [TODO]
1322 : ///
1323 : Parser::OwningExprResult
1324 115: Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
115: branch 1 taken
0: branch 2 not taken
1325 115: assert(Tok.is(tok::kw_new) && "expected 'new' token");
1326 115: ConsumeToken(); // Consume 'new'
1327 :
1328 : // A '(' now can be a new-placement or the '(' wrapping the type-id in the
1329 : // second form of new-expression. It can't be a new-type-id.
1330 :
1331 115: ExprVector PlacementArgs(Actions);
1332 115: SourceLocation PlacementLParen, PlacementRParen;
1333 :
1334 : bool ParenTypeId;
1335 115: DeclSpec DS;
1336 115: Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
32: branch 1 taken
83: branch 2 taken
1337 115: if (Tok.is(tok::l_paren)) {
1338 : // If it turns out to be a placement, we change the type location.
1339 32: PlacementLParen = ConsumeParen();
1: branch 1 taken
31: branch 2 taken
1340 32: if (ParseExpressionListOrTypeId(PlacementArgs, DeclaratorInfo)) {
1341 1: SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
1342 1: return ExprError();
1343 : }
1344 :
1345 31: PlacementRParen = MatchRHSPunctuation(tok::r_paren, PlacementLParen);
0: branch 1 not taken
31: branch 2 taken
1346 31: if (PlacementRParen.isInvalid()) {
1347 0: SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
1348 0: return ExprError();
1349 : }
1350 :
6: branch 1 taken
25: branch 2 taken
1351 31: if (PlacementArgs.empty()) {
1352 : // Reset the placement locations. There was no placement.
1353 6: PlacementLParen = PlacementRParen = SourceLocation();
1354 6: ParenTypeId = true;
1355 : } else {
1356 : // We still need the type.
1: branch 1 taken
24: branch 2 taken
1357 25: if (Tok.is(tok::l_paren)) {
1358 1: SourceLocation LParen = ConsumeParen();
1359 1: ParseSpecifierQualifierList(DS);
1360 1: DeclaratorInfo.SetSourceRange(DS.getSourceRange());
1361 1: ParseDeclarator(DeclaratorInfo);
1362 1: MatchRHSPunctuation(tok::r_paren, LParen);
1363 1: ParenTypeId = true;
1364 : } else {
0: branch 1 not taken
24: branch 2 taken
1365 24: if (ParseCXXTypeSpecifierSeq(DS))
1366 0: DeclaratorInfo.setInvalidType(true);
1367 : else {
1368 24: DeclaratorInfo.SetSourceRange(DS.getSourceRange());
1369 : ParseDeclaratorInternal(DeclaratorInfo,
1370 24: &Parser::ParseDirectNewDeclarator);
1371 : }
1372 24: ParenTypeId = false;
1373 : }
1374 : }
1375 : } else {
1376 : // A new-type-id is a simplified type-id, where essentially the
1377 : // direct-declarator is replaced by a direct-new-declarator.
2: branch 1 taken
81: branch 2 taken
1378 83: if (ParseCXXTypeSpecifierSeq(DS))
1379 2: DeclaratorInfo.setInvalidType(true);
1380 : else {
1381 81: DeclaratorInfo.SetSourceRange(DS.getSourceRange());
1382 : ParseDeclaratorInternal(DeclaratorInfo,
1383 81: &Parser::ParseDirectNewDeclarator);
1384 : }
1385 83: ParenTypeId = false;
1386 : }
2: branch 1 taken
112: branch 2 taken
1387 114: if (DeclaratorInfo.isInvalidType()) {
1388 2: SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
1389 2: return ExprError();
1390 : }
1391 :
1392 112: ExprVector ConstructorArgs(Actions);
1393 112: SourceLocation ConstructorLParen, ConstructorRParen;
1394 :
45: branch 1 taken
67: branch 2 taken
1395 112: if (Tok.is(tok::l_paren)) {
1396 45: ConstructorLParen = ConsumeParen();
35: branch 1 taken
10: branch 2 taken
1397 45: if (Tok.isNot(tok::r_paren)) {
1398 35: CommaLocsTy CommaLocs;
0: branch 1 not taken
35: branch 2 taken
1399 35: if (ParseExpressionList(ConstructorArgs, CommaLocs)) {
1400 0: SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
1401 0: return ExprError();
35: branch 1 taken
0: branch 2 not taken
1402 35: }
1403 : }
1404 45: ConstructorRParen = MatchRHSPunctuation(tok::r_paren, ConstructorLParen);
0: branch 1 not taken
45: branch 2 taken
1405 45: if (ConstructorRParen.isInvalid()) {
1406 0: SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
1407 0: return ExprError();
1408 : }
1409 : }
1410 :
1411 : return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen,
1412 : move_arg(PlacementArgs), PlacementRParen,
1413 : ParenTypeId, DeclaratorInfo, ConstructorLParen,
1414 112: move_arg(ConstructorArgs), ConstructorRParen);
1415 : }
1416 :
1417 : /// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be
1418 : /// passed to ParseDeclaratorInternal.
1419 : ///
1420 : /// direct-new-declarator:
1421 : /// '[' expression ']'
1422 : /// direct-new-declarator '[' constant-expression ']'
1423 : ///
1424 105: void Parser::ParseDirectNewDeclarator(Declarator &D) {
1425 : // Parse the array dimensions.
1426 105: bool first = true;
23: branch 1 taken
0: branch 2 not taken
23: branch 4 taken
105: branch 5 taken
1427 256: while (Tok.is(tok::l_square)) {
1428 23: SourceLocation LLoc = ConsumeBracket();
1429 : OwningExprResult Size(first ? ParseExpression()
21: branch 0 taken
2: branch 1 taken
1430 23: : ParseConstantExpression());
0: branch 1 not taken
23: branch 2 taken
1431 23: if (Size.isInvalid()) {
1432 : // Recover
1433 0: SkipUntil(tok::r_square);
1434 0: return;
1435 : }
1436 23: first = false;
1437 :
1438 23: SourceLocation RLoc = MatchRHSPunctuation(tok::r_square, LLoc);
1439 : D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false,
1440 : Size.release(), LLoc, RLoc),
1441 23: RLoc);
1442 :
0: branch 1 not taken
23: branch 2 taken
1443 23: if (RLoc.isInvalid())
1444 : return;
1445 : }
1446 : }
1447 :
1448 : /// ParseExpressionListOrTypeId - Parse either an expression-list or a type-id.
1449 : /// This ambiguity appears in the syntax of the C++ new operator.
1450 : ///
1451 : /// new-expression:
1452 : /// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
1453 : /// new-initializer[opt]
1454 : ///
1455 : /// new-placement:
1456 : /// '(' expression-list ')'
1457 : ///
1458 : bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs,
1459 32: Declarator &D) {
1460 : // The '(' was already consumed.
6: branch 1 taken
26: branch 2 taken
1461 32: if (isTypeIdInParens()) {
1462 6: ParseSpecifierQualifierList(D.getMutableDeclSpec());
1463 6: D.SetSourceRange(D.getDeclSpec().getSourceRange());
1464 6: ParseDeclarator(D);
1465 6: return D.isInvalidType();
1466 : }
1467 :
1468 : // It's not a type, it has to be an expression list.
1469 : // Discard the comma locations - ActOnCXXNew has enough parameters.
1470 26: CommaLocsTy CommaLocs;
1471 26: return ParseExpressionList(PlacementArgs, CommaLocs);
1472 : }
1473 :
1474 : /// ParseCXXDeleteExpression - Parse a C++ delete-expression. Delete is used
1475 : /// to free memory allocated by new.
1476 : ///
1477 : /// This method is called to parse the 'delete' expression after the optional
1478 : /// '::' has been already parsed. If the '::' was present, "UseGlobal" is true
1479 : /// and "Start" is its location. Otherwise, "Start" is the location of the
1480 : /// 'delete' token.
1481 : ///
1482 : /// delete-expression:
1483 : /// '::'[opt] 'delete' cast-expression
1484 : /// '::'[opt] 'delete' '[' ']' cast-expression
1485 : Parser::OwningExprResult
1486 50: Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) {
50: branch 1 taken
0: branch 2 not taken
1487 50: assert(Tok.is(tok::kw_delete) && "Expected 'delete' keyword");
1488 50: ConsumeToken(); // Consume 'delete'
1489 :
1490 : // Array delete?
1491 50: bool ArrayDelete = false;
11: branch 1 taken
39: branch 2 taken
1492 50: if (Tok.is(tok::l_square)) {
1493 11: ArrayDelete = true;
1494 11: SourceLocation LHS = ConsumeBracket();
1495 11: SourceLocation RHS = MatchRHSPunctuation(tok::r_square, LHS);
0: branch 1 not taken
11: branch 2 taken
1496 11: if (RHS.isInvalid())
1497 0: return ExprError();
1498 : }
1499 :
1500 50: OwningExprResult Operand(ParseCastExpression(false));
0: branch 1 not taken
50: branch 2 taken
1501 50: if (Operand.isInvalid())
1502 0: return move(Operand);
1503 :
1504 50: return Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete, move(Operand));
1505 : }
1506 :
1507 180: static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) {
0: branch 0 not taken
0: branch 1 not taken
0: branch 2 not taken
0: branch 3 not taken
18: branch 4 taken
18: branch 5 taken
26: branch 6 taken
28: branch 7 taken
0: branch 8 not taken
4: branch 9 taken
9: branch 10 taken
18: branch 11 taken
9: branch 12 taken
27: branch 13 taken
11: branch 14 taken
7: branch 15 taken
5: branch 16 taken
1508 180: switch(kind) {
1509 0: default: assert(false && "Not a known unary type trait.");
1510 0: case tok::kw___has_nothrow_assign: return UTT_HasNothrowAssign;
1511 0: case tok::kw___has_nothrow_copy: return UTT_HasNothrowCopy;
1512 0: case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor;
1513 18: case tok::kw___has_trivial_assign: return UTT_HasTrivialAssign;
1514 18: case tok::kw___has_trivial_copy: return UTT_HasTrivialCopy;
1515 26: case tok::kw___has_trivial_constructor: return UTT_HasTrivialConstructor;
1516 28: case tok::kw___has_trivial_destructor: return UTT_HasTrivialDestructor;
1517 0: case tok::kw___has_virtual_destructor: return UTT_HasVirtualDestructor;
1518 4: case tok::kw___is_abstract: return UTT_IsAbstract;
1519 9: case tok::kw___is_class: return UTT_IsClass;
1520 18: case tok::kw___is_empty: return UTT_IsEmpty;
1521 9: case tok::kw___is_enum: return UTT_IsEnum;
1522 27: case tok::kw___is_pod: return UTT_IsPOD;
1523 11: case tok::kw___is_polymorphic: return UTT_IsPolymorphic;
1524 7: case tok::kw___is_union: return UTT_IsUnion;
1525 5: case tok::kw___is_literal: return UTT_IsLiteral;
1526 : }
1527 : }
1528 :
1529 : /// ParseUnaryTypeTrait - Parse the built-in unary type-trait
1530 : /// pseudo-functions that allow implementation of the TR1/C++0x type traits
1531 : /// templates.
1532 : ///
1533 : /// primary-expression:
1534 : /// [GNU] unary-type-trait '(' type-id ')'
1535 : ///
1536 180: Parser::OwningExprResult Parser::ParseUnaryTypeTrait() {
1537 180: UnaryTypeTrait UTT = UnaryTypeTraitFromTokKind(Tok.getKind());
1538 180: SourceLocation Loc = ConsumeToken();
1539 :
1540 180: SourceLocation LParen = Tok.getLocation();
0: branch 1 not taken
180: branch 2 taken
1541 180: if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen))
1542 0: return ExprError();
1543 :
1544 : // FIXME: Error reporting absolutely sucks! If the this fails to parse a type
1545 : // there will be cryptic errors about mismatched parentheses and missing
1546 : // specifiers.
1547 180: TypeResult Ty = ParseTypeName();
1548 :
1549 180: SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen);
1550 :
0: branch 1 not taken
180: branch 2 taken
1551 180: if (Ty.isInvalid())
1552 0: return ExprError();
1553 :
1554 180: return Actions.ActOnUnaryTypeTrait(UTT, Loc, LParen, Ty.get(), RParen);
1555 : }
1556 :
1557 : /// ParseCXXAmbiguousParenExpression - We have parsed the left paren of a
1558 : /// parenthesized ambiguous type-id. This uses tentative parsing to disambiguate
1559 : /// based on the context past the parens.
1560 : Parser::OwningExprResult
1561 : Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
1562 : TypeTy *&CastTy,
1563 : SourceLocation LParenLoc,
1564 35: SourceLocation &RParenLoc) {
35: branch 1 taken
0: branch 2 not taken
1565 35: assert(getLang().CPlusPlus && "Should only be called for C++!");
0: branch 0 not taken
35: branch 1 taken
1566 35: assert(ExprType == CastExpr && "Compound literals are not ambiguous!");
35: branch 1 taken
0: branch 2 not taken
1567 35: assert(isTypeIdInParens() && "Not a type-id!");
1568 :
1569 35: OwningExprResult Result(Actions, true);
1570 35: CastTy = 0;
1571 :
1572 : // We need to disambiguate a very ugly part of the C++ syntax:
1573 : //
1574 : // (T())x; - type-id
1575 : // (T())*x; - type-id
1576 : // (T())/x; - expression
1577 : // (T()); - expression
1578 : //
1579 : // The bad news is that we cannot use the specialized tentative parser, since
1580 : // it can only verify that the thing inside the parens can be parsed as
1581 : // type-id, it is not useful for determining the context past the parens.
1582 : //
1583 : // The good news is that the parser can disambiguate this part without
1584 : // making any unnecessary Action calls.
1585 : //
1586 : // It uses a scheme similar to parsing inline methods. The parenthesized
1587 : // tokens are cached, the context that follows is determined (possibly by
1588 : // parsing a cast-expression), and then we re-introduce the cached tokens
1589 : // into the token stream and parse them appropriately.
1590 :
1591 : ParenParseOption ParseAs;
1592 35: CachedTokens Toks;
1593 :
1594 : // Store the tokens of the parentheses. We will parse them after we determine
1595 : // the context that follows them.
0: branch 1 not taken
35: branch 2 taken
1596 35: if (!ConsumeAndStoreUntil(tok::r_paren, tok::unknown, Toks, tok::semi)) {
1597 : // We didn't find the ')' we expected.
1598 0: MatchRHSPunctuation(tok::r_paren, LParenLoc);
1599 0: return ExprError();
1600 : }
1601 :
0: branch 1 not taken
35: branch 2 taken
1602 35: if (Tok.is(tok::l_brace)) {
1603 0: ParseAs = CompoundLiteral;
1604 : } else {
1605 : bool NotCastExpr;
1606 : // FIXME: Special-case ++ and --: "(S())++;" is not a cast-expression
7: branch 1 taken
28: branch 2 taken
1: branch 5 taken
6: branch 6 taken
1: branch 7 taken
34: branch 8 taken
1607 35: if (Tok.is(tok::l_paren) && NextToken().is(tok::r_paren)) {
1608 1: NotCastExpr = true;
1609 : } else {
1610 : // Try parsing the cast-expression that may follow.
1611 : // If it is not a cast-expression, NotCastExpr will be true and no token
1612 : // will be consumed.
1613 : Result = ParseCastExpression(false/*isUnaryExpression*/,
1614 : false/*isAddressofOperand*/,
1615 34: NotCastExpr, false);
1616 : }
1617 :
1618 : // If we parsed a cast-expression, it's really a type-id, otherwise it's
1619 : // an expression.
10: branch 0 taken
25: branch 1 taken
1620 35: ParseAs = NotCastExpr ? SimpleExpr : CastExpr;
1621 : }
1622 :
1623 : // The current token should go after the cached tokens.
1624 35: Toks.push_back(Tok);
1625 : // Re-enter the stored parenthesized tokens into the token stream, so we may
1626 : // parse them now.
1627 : PP.EnterTokenStream(Toks.data(), Toks.size(),
1628 35: true/*DisableMacroExpansion*/, false/*OwnsTokens*/);
1629 : // Drop the current token and bring the first cached one. It's the same token
1630 : // as when we entered this function.
1631 35: ConsumeAnyToken();
1632 :
25: branch 0 taken
10: branch 1 taken
1633 35: if (ParseAs >= CompoundLiteral) {
1634 25: TypeResult Ty = ParseTypeName();
1635 :
1636 : // Match the ')'.
25: branch 1 taken
0: branch 2 not taken
1637 25: if (Tok.is(tok::r_paren))
1638 25: RParenLoc = ConsumeParen();
1639 : else
1640 0: MatchRHSPunctuation(tok::r_paren, LParenLoc);
1641 :
0: branch 0 not taken
25: branch 1 taken
1642 25: if (ParseAs == CompoundLiteral) {
1643 0: ExprType = CompoundLiteral;
1644 0: return ParseCompoundLiteralExpression(Ty.get(), LParenLoc, RParenLoc);
1645 : }
1646 :
1647 : // We parsed '(' type-id ')' and the thing after it wasn't a '{'.
0: branch 0 not taken
25: branch 1 taken
1648 25: assert(ParseAs == CastExpr);
1649 :
0: branch 1 not taken
25: branch 2 taken
1650 25: if (Ty.isInvalid())
1651 0: return ExprError();
1652 :
1653 25: CastTy = Ty.get();
1654 :
1655 : // Result is what ParseCastExpression returned earlier.
25: branch 1 taken
0: branch 2 not taken
1656 25: if (!Result.isInvalid())
1657 : Result = Actions.ActOnCastExpr(CurScope, LParenLoc, CastTy, RParenLoc,
1658 25: move(Result));
1659 25: return move(Result);
1660 : }
1661 :
1662 : // Not a compound literal, and not followed by a cast-expression.
0: branch 0 not taken
10: branch 1 taken
1663 10: assert(ParseAs == SimpleExpr);
1664 :
1665 10: ExprType = SimpleExpr;
1666 10: Result = ParseExpression();
10: branch 1 taken
0: branch 2 not taken
10: branch 4 taken
0: branch 5 not taken
10: branch 6 taken
0: branch 7 not taken
1667 10: if (!Result.isInvalid() && Tok.is(tok::r_paren))
1668 10: Result = Actions.ActOnParenExpr(LParenLoc, Tok.getLocation(), move(Result));
1669 :
1670 : // Match the ')'.
0: branch 1 not taken
10: branch 2 taken
1671 10: if (Result.isInvalid()) {
1672 0: SkipUntil(tok::r_paren);
1673 0: return ExprError();
1674 : }
1675 :
10: branch 1 taken
0: branch 2 not taken
1676 10: if (Tok.is(tok::r_paren))
1677 10: RParenLoc = ConsumeParen();
1678 : else
1679 0: MatchRHSPunctuation(tok::r_paren, LParenLoc);
1680 :
1681 10: return move(Result);
1682 : }
Generated: 2010-02-10 01:31 by zcov