 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
82.5% |
498 / 604 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
99.7% |
602 / 604 |
| |
|
Line Coverage: |
91.1% |
674 / 740 |
| |
 |
|
 |
1 : //===--- ParseDeclCXX.cpp - C++ Declaration 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 C++ Declaration portions of the Parser interfaces.
11 : //
12 : //===----------------------------------------------------------------------===//
13 :
14 : #include "clang/Basic/OperatorKinds.h"
15 : #include "clang/Parse/Parser.h"
16 : #include "clang/Parse/ParseDiagnostic.h"
17 : #include "clang/Parse/DeclSpec.h"
18 : #include "clang/Parse/Scope.h"
19 : #include "clang/Parse/Template.h"
20 : #include "RAIIObjectsForParser.h"
21 : using namespace clang;
22 :
23 : /// ParseNamespace - We know that the current token is a namespace keyword. This
24 : /// may either be a top level namespace or a block-level namespace alias.
25 : ///
26 : /// namespace-definition: [C++ 7.3: basic.namespace]
27 : /// named-namespace-definition
28 : /// unnamed-namespace-definition
29 : ///
30 : /// unnamed-namespace-definition:
31 : /// 'namespace' attributes[opt] '{' namespace-body '}'
32 : ///
33 : /// named-namespace-definition:
34 : /// original-namespace-definition
35 : /// extension-namespace-definition
36 : ///
37 : /// original-namespace-definition:
38 : /// 'namespace' identifier attributes[opt] '{' namespace-body '}'
39 : ///
40 : /// extension-namespace-definition:
41 : /// 'namespace' original-namespace-name '{' namespace-body '}'
42 : ///
43 : /// namespace-alias-definition: [C++ 7.3.2: namespace.alias]
44 : /// 'namespace' identifier '=' qualified-namespace-specifier ';'
45 : ///
46 : Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context,
47 694: SourceLocation &DeclEnd) {
694: branch 1 taken
0: branch 2 not taken
48 694: assert(Tok.is(tok::kw_namespace) && "Not a namespace!");
49 694: SourceLocation NamespaceLoc = ConsumeToken(); // eat the 'namespace'.
50 :
1: branch 1 taken
693: branch 2 taken
51 694: if (Tok.is(tok::code_completion)) {
52 1: Actions.CodeCompleteNamespaceDecl(CurScope);
53 1: ConsumeToken();
54 : }
55 :
56 694: SourceLocation IdentLoc;
57 694: IdentifierInfo *Ident = 0;
58 :
59 694: Token attrTok;
60 :
675: branch 1 taken
19: branch 2 taken
61 694: if (Tok.is(tok::identifier)) {
62 675: Ident = Tok.getIdentifierInfo();
63 675: IdentLoc = ConsumeToken(); // eat the identifier.
64 : }
65 :
66 : // Read label attributes, if present.
67 694: AttributeList *AttrList = 0;
3: branch 1 taken
691: branch 2 taken
68 694: if (Tok.is(tok::kw___attribute)) {
69 3: attrTok = Tok;
70 :
71 : // FIXME: save these somewhere.
72 3: AttrList = ParseGNUAttributes();
73 : }
74 :
34: branch 1 taken
660: branch 2 taken
75 694: if (Tok.is(tok::equal)) {
1: branch 0 taken
33: branch 1 taken
76 34: if (AttrList)
77 1: Diag(attrTok, diag::err_unexpected_namespace_attributes_alias);
78 :
79 34: return ParseNamespaceAlias(NamespaceLoc, IdentLoc, Ident, DeclEnd);
80 : }
81 :
1: branch 1 taken
659: branch 2 taken
82 660: if (Tok.isNot(tok::l_brace)) {
83 : Diag(Tok, Ident ? diag::err_expected_lbrace :
0: branch 0 not taken
1: branch 1 taken
84 1: diag::err_expected_ident_lbrace);
85 1: return DeclPtrTy();
86 : }
87 :
88 659: SourceLocation LBrace = ConsumeBrace();
89 :
90 : // Enter a scope for the namespace.
91 659: ParseScope NamespaceScope(this, Scope::DeclScope);
92 :
93 : DeclPtrTy NamespcDecl =
94 659: Actions.ActOnStartNamespaceDef(CurScope, IdentLoc, Ident, LBrace, AttrList);
95 :
96 : PrettyStackTraceActionsDecl CrashInfo(NamespcDecl, NamespaceLoc, Actions,
97 : PP.getSourceManager(),
98 659: "parsing namespace");
99 :
1646: branch 1 taken
653: branch 2 taken
1640: branch 4 taken
6: branch 5 taken
1640: branch 6 taken
659: branch 7 taken
100 2958: while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
101 1640: CXX0XAttributeList Attr;
103: branch 1 taken
1537: branch 2 taken
0: branch 4 not taken
103: branch 5 taken
0: branch 6 not taken
1640: branch 7 taken
102 1640: if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
103 0: Attr = ParseCXX0XAttributes();
104 1640: ParseExternalDeclaration(Attr);
105 : }
106 :
107 : // Leave the namespace scope.
108 659: NamespaceScope.Exit();
109 :
110 659: SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBrace);
111 659: Actions.ActOnFinishNamespaceDef(NamespcDecl, RBraceLoc);
112 :
113 659: DeclEnd = RBraceLoc;
114 659: return NamespcDecl;
115 : }
116 :
117 : /// ParseNamespaceAlias - Parse the part after the '=' in a namespace
118 : /// alias definition.
119 : ///
120 : Parser::DeclPtrTy Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
121 : SourceLocation AliasLoc,
122 : IdentifierInfo *Alias,
123 34: SourceLocation &DeclEnd) {
34: branch 1 taken
0: branch 2 not taken
124 34: assert(Tok.is(tok::equal) && "Not equal token");
125 :
126 34: ConsumeToken(); // eat the '='.
127 :
1: branch 1 taken
33: branch 2 taken
128 34: if (Tok.is(tok::code_completion)) {
129 1: Actions.CodeCompleteNamespaceAliasDecl(CurScope);
130 1: ConsumeToken();
131 : }
132 :
133 34: CXXScopeSpec SS;
134 : // Parse (optional) nested-name-specifier.
135 34: ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
136 :
33: branch 1 taken
1: branch 2 taken
2: branch 4 taken
31: branch 5 taken
3: branch 6 taken
31: branch 7 taken
137 34: if (SS.isInvalid() || Tok.isNot(tok::identifier)) {
138 3: Diag(Tok, diag::err_expected_namespace_name);
139 : // Skip to end of the definition and eat the ';'.
140 3: SkipUntil(tok::semi);
141 3: return DeclPtrTy();
142 : }
143 :
144 : // Parse identifier.
145 31: IdentifierInfo *Ident = Tok.getIdentifierInfo();
146 31: SourceLocation IdentLoc = ConsumeToken();
147 :
148 : // Eat the ';'.
149 31: DeclEnd = Tok.getLocation();
150 : ExpectAndConsume(tok::semi, diag::err_expected_semi_after_namespace_name,
151 31: "", tok::semi);
152 :
153 : return Actions.ActOnNamespaceAliasDef(CurScope, NamespaceLoc, AliasLoc, Alias,
154 31: SS, IdentLoc, Ident);
155 : }
156 :
157 : /// ParseLinkage - We know that the current token is a string_literal
158 : /// and just before that, that extern was seen.
159 : ///
160 : /// linkage-specification: [C++ 7.5p2: dcl.link]
161 : /// 'extern' string-literal '{' declaration-seq[opt] '}'
162 : /// 'extern' string-literal declaration
163 : ///
164 : Parser::DeclPtrTy Parser::ParseLinkage(ParsingDeclSpec &DS,
165 111: unsigned Context) {
111: branch 1 taken
0: branch 2 not taken
166 111: assert(Tok.is(tok::string_literal) && "Not a string literal!");
167 111: llvm::SmallVector<char, 8> LangBuffer;
168 : // LangBuffer is guaranteed to be big enough.
169 111: LangBuffer.resize(Tok.getLength());
170 111: const char *LangBufPtr = &LangBuffer[0];
171 111: unsigned StrSize = PP.getSpelling(Tok, LangBufPtr);
172 :
173 111: SourceLocation Loc = ConsumeStringToken();
174 :
175 111: ParseScope LinkageScope(this, Scope::DeclScope);
176 : DeclPtrTy LinkageSpec
177 : = Actions.ActOnStartLinkageSpecification(CurScope,
178 : /*FIXME: */SourceLocation(),
179 : Loc, LangBufPtr, StrSize,
180 : Tok.is(tok::l_brace)? Tok.getLocation()
40: branch 1 taken
71: branch 2 taken
181 151: : SourceLocation());
182 :
183 111: CXX0XAttributeList Attr;
28: branch 1 taken
83: branch 2 taken
2: branch 4 taken
26: branch 5 taken
2: branch 6 taken
109: branch 7 taken
184 111: if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
185 2: Attr = ParseCXX0XAttributes();
186 : }
187 :
70: branch 1 taken
41: branch 2 taken
188 111: if (Tok.isNot(tok::l_brace)) {
189 70: ParseDeclarationOrFunctionDefinition(DS, Attr.AttrList);
190 : return Actions.ActOnFinishLinkageSpecification(CurScope, LinkageSpec,
191 70: SourceLocation());
192 : }
193 :
194 41: DS.abort();
195 :
1: branch 0 taken
40: branch 1 taken
196 41: if (Attr.HasAttr)
197 : Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
198 1: << Attr.Range;
199 :
200 41: SourceLocation LBrace = ConsumeBrace();
550: branch 1 taken
41: branch 2 taken
550: branch 4 taken
0: branch 5 not taken
550: branch 6 taken
41: branch 7 taken
201 632: while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
202 550: CXX0XAttributeList Attr;
1: branch 1 taken
549: branch 2 taken
0: branch 4 not taken
1: branch 5 taken
0: branch 6 not taken
550: branch 7 taken
203 550: if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
204 0: Attr = ParseCXX0XAttributes();
205 550: ParseExternalDeclaration(Attr);
206 : }
207 :
208 41: SourceLocation RBrace = MatchRHSPunctuation(tok::r_brace, LBrace);
209 41: return Actions.ActOnFinishLinkageSpecification(CurScope, LinkageSpec, RBrace);
210 : }
211 :
212 : /// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or
213 : /// using-directive. Assumes that current token is 'using'.
214 : Parser::DeclPtrTy Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
215 : SourceLocation &DeclEnd,
216 150: CXX0XAttributeList Attr) {
150: branch 1 taken
0: branch 2 not taken
217 150: assert(Tok.is(tok::kw_using) && "Not using token");
218 :
219 : // Eat 'using'.
220 150: SourceLocation UsingLoc = ConsumeToken();
221 :
1: branch 1 taken
149: branch 2 taken
222 150: if (Tok.is(tok::code_completion)) {
223 1: Actions.CodeCompleteUsing(CurScope);
224 1: ConsumeToken();
225 : }
226 :
92: branch 1 taken
58: branch 2 taken
227 150: if (Tok.is(tok::kw_namespace))
228 : // Next token after 'using' is 'namespace' so it must be using-directive
229 92: return ParseUsingDirective(Context, UsingLoc, DeclEnd, Attr.AttrList);
230 :
1: branch 0 taken
57: branch 1 taken
231 58: if (Attr.HasAttr)
232 : Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
233 1: << Attr.Range;
234 :
235 : // Otherwise, it must be using-declaration.
236 : // Ignore illegal attributes (the caller should already have issued an error.
237 58: return ParseUsingDeclaration(Context, UsingLoc, DeclEnd);
238 : }
239 :
240 : /// ParseUsingDirective - Parse C++ using-directive, assumes
241 : /// that current token is 'namespace' and 'using' was already parsed.
242 : ///
243 : /// using-directive: [C++ 7.3.p4: namespace.udir]
244 : /// 'using' 'namespace' ::[opt] nested-name-specifier[opt]
245 : /// namespace-name ;
246 : /// [GNU] using-directive:
247 : /// 'using' 'namespace' ::[opt] nested-name-specifier[opt]
248 : /// namespace-name attributes[opt] ;
249 : ///
250 : Parser::DeclPtrTy Parser::ParseUsingDirective(unsigned Context,
251 : SourceLocation UsingLoc,
252 : SourceLocation &DeclEnd,
253 92: AttributeList *Attr) {
92: branch 1 taken
0: branch 2 not taken
254 92: assert(Tok.is(tok::kw_namespace) && "Not 'namespace' token");
255 :
256 : // Eat 'namespace'.
257 92: SourceLocation NamespcLoc = ConsumeToken();
258 :
1: branch 1 taken
91: branch 2 taken
259 92: if (Tok.is(tok::code_completion)) {
260 1: Actions.CodeCompleteUsingDirective(CurScope);
261 1: ConsumeToken();
262 : }
263 :
264 92: CXXScopeSpec SS;
265 : // Parse (optional) nested-name-specifier.
266 92: ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
267 :
268 92: IdentifierInfo *NamespcName = 0;
269 92: SourceLocation IdentLoc = SourceLocation();
270 :
271 : // Parse namespace-name.
92: branch 1 taken
0: branch 2 not taken
2: branch 4 taken
90: branch 5 taken
2: branch 6 taken
90: branch 7 taken
272 92: if (SS.isInvalid() || Tok.isNot(tok::identifier)) {
273 2: Diag(Tok, diag::err_expected_namespace_name);
274 : // If there was invalid namespace name, skip to end of decl, and eat ';'.
275 2: SkipUntil(tok::semi);
276 : // FIXME: Are there cases, when we would like to call ActOnUsingDirective?
277 2: return DeclPtrTy();
278 : }
279 :
280 : // Parse identifier.
281 90: NamespcName = Tok.getIdentifierInfo();
282 90: IdentLoc = ConsumeToken();
283 :
284 : // Parse (optional) attributes (most likely GNU strong-using extension).
285 90: bool GNUAttr = false;
0: branch 1 not taken
90: branch 2 taken
286 90: if (Tok.is(tok::kw___attribute)) {
287 0: GNUAttr = true;
288 0: Attr = addAttributeLists(Attr, ParseGNUAttributes());
289 : }
290 :
291 : // Eat ';'.
292 90: DeclEnd = Tok.getLocation();
293 : ExpectAndConsume(tok::semi,
294 : GNUAttr ? diag::err_expected_semi_after_attribute_list :
0: branch 0 not taken
90: branch 1 taken
295 90: diag::err_expected_semi_after_namespace_name, "", tok::semi);
296 :
297 : return Actions.ActOnUsingDirective(CurScope, UsingLoc, NamespcLoc, SS,
298 90: IdentLoc, NamespcName, Attr);
299 : }
300 :
301 : /// ParseUsingDeclaration - Parse C++ using-declaration. Assumes that
302 : /// 'using' was already seen.
303 : ///
304 : /// using-declaration: [C++ 7.3.p3: namespace.udecl]
305 : /// 'using' 'typename'[opt] ::[opt] nested-name-specifier
306 : /// unqualified-id
307 : /// 'using' :: unqualified-id
308 : ///
309 : Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
310 : SourceLocation UsingLoc,
311 : SourceLocation &DeclEnd,
312 130: AccessSpecifier AS) {
313 130: CXXScopeSpec SS;
314 130: SourceLocation TypenameLoc;
315 : bool IsTypeName;
316 :
317 : // Ignore optional 'typename'.
318 : // FIXME: This is wrong; we should parse this as a typename-specifier.
8: branch 1 taken
122: branch 2 taken
319 130: if (Tok.is(tok::kw_typename)) {
320 8: TypenameLoc = Tok.getLocation();
321 8: ConsumeToken();
322 8: IsTypeName = true;
323 : }
324 : else
325 122: IsTypeName = false;
326 :
327 : // Parse nested-name-specifier.
328 130: ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
329 :
330 130: AttributeList *AttrList = 0;
331 :
332 : // Check nested-name specifier.
0: branch 1 not taken
130: branch 2 taken
333 130: if (SS.isInvalid()) {
334 0: SkipUntil(tok::semi);
335 0: return DeclPtrTy();
336 : }
337 :
338 : // Parse the unqualified-id. We allow parsing of both constructor and
339 : // destructor names and allow the action module to diagnose any semantic
340 : // errors.
341 130: UnqualifiedId Name;
1: branch 1 taken
129: branch 2 taken
342 130: if (ParseUnqualifiedId(SS,
343 : /*EnteringContext=*/false,
344 : /*AllowDestructorName=*/true,
345 : /*AllowConstructorName=*/true,
346 : /*ObjectType=*/0,
347 : Name)) {
348 1: SkipUntil(tok::semi);
349 1: return DeclPtrTy();
350 : }
351 :
352 : // Parse (optional) attributes (most likely GNU strong-using extension).
0: branch 1 not taken
129: branch 2 taken
353 129: if (Tok.is(tok::kw___attribute))
354 0: AttrList = ParseGNUAttributes();
355 :
356 : // Eat ';'.
357 129: DeclEnd = Tok.getLocation();
358 : ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
359 : AttrList ? "attributes list" : "using declaration",
0: branch 0 not taken
129: branch 1 taken
360 129: tok::semi);
361 :
362 : return Actions.ActOnUsingDeclaration(CurScope, AS, true, UsingLoc, SS, Name,
363 129: AttrList, IsTypeName, TypenameLoc);
364 : }
365 :
366 : /// ParseStaticAssertDeclaration - Parse C++0x static_assert-declaratoion.
367 : ///
368 : /// static_assert-declaration:
369 : /// static_assert ( constant-expression , string-literal ) ;
370 : ///
371 61: Parser::DeclPtrTy Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
61: branch 1 taken
0: branch 2 not taken
372 61: assert(Tok.is(tok::kw_static_assert) && "Not a static_assert declaration");
373 61: SourceLocation StaticAssertLoc = ConsumeToken();
374 :
0: branch 1 not taken
61: branch 2 taken
375 61: if (Tok.isNot(tok::l_paren)) {
376 0: Diag(Tok, diag::err_expected_lparen);
377 0: return DeclPtrTy();
378 : }
379 :
380 61: SourceLocation LParenLoc = ConsumeParen();
381 :
382 61: OwningExprResult AssertExpr(ParseConstantExpression());
0: branch 1 not taken
61: branch 2 taken
383 61: if (AssertExpr.isInvalid()) {
384 0: SkipUntil(tok::semi);
385 0: return DeclPtrTy();
386 : }
387 :
0: branch 1 not taken
61: branch 2 taken
388 61: if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "", tok::semi))
389 0: return DeclPtrTy();
390 :
0: branch 1 not taken
61: branch 2 taken
391 61: if (Tok.isNot(tok::string_literal)) {
392 0: Diag(Tok, diag::err_expected_string_literal);
393 0: SkipUntil(tok::semi);
394 0: return DeclPtrTy();
395 : }
396 :
397 61: OwningExprResult AssertMessage(ParseStringLiteralExpression());
0: branch 1 not taken
61: branch 2 taken
398 61: if (AssertMessage.isInvalid())
399 0: return DeclPtrTy();
400 :
401 61: MatchRHSPunctuation(tok::r_paren, LParenLoc);
402 :
403 61: DeclEnd = Tok.getLocation();
404 61: ExpectAndConsume(tok::semi, diag::err_expected_semi_after_static_assert);
405 :
406 : return Actions.ActOnStaticAssertDeclaration(StaticAssertLoc, move(AssertExpr),
407 61: move(AssertMessage));
408 : }
409 :
410 : /// ParseDecltypeSpecifier - Parse a C++0x decltype specifier.
411 : ///
412 : /// 'decltype' ( expression )
413 : ///
414 16: void Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
16: branch 1 taken
0: branch 2 not taken
415 16: assert(Tok.is(tok::kw_decltype) && "Not a decltype specifier");
416 :
417 16: SourceLocation StartLoc = ConsumeToken();
418 16: SourceLocation LParenLoc = Tok.getLocation();
419 :
0: branch 1 not taken
16: branch 2 taken
420 16: if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
421 : "decltype")) {
422 0: SkipUntil(tok::r_paren);
423 0: return;
424 : }
425 :
426 : // Parse the expression
427 :
428 : // C++0x [dcl.type.simple]p4:
429 : // The operand of the decltype specifier is an unevaluated operand.
430 : EnterExpressionEvaluationContext Unevaluated(Actions,
431 16: Action::Unevaluated);
432 16: OwningExprResult Result = ParseExpression();
0: branch 1 not taken
16: branch 2 taken
433 16: if (Result.isInvalid()) {
434 0: SkipUntil(tok::r_paren);
435 0: return;
436 : }
437 :
438 : // Match the ')'
439 16: SourceLocation RParenLoc;
16: branch 1 taken
0: branch 2 not taken
440 16: if (Tok.is(tok::r_paren))
441 16: RParenLoc = ConsumeParen();
442 : else
443 0: MatchRHSPunctuation(tok::r_paren, LParenLoc);
444 :
0: branch 1 not taken
16: branch 2 taken
445 16: if (RParenLoc.isInvalid())
446 : return;
447 :
448 16: const char *PrevSpec = 0;
449 : unsigned DiagID;
450 : // Check for duplicate type specifiers (e.g. "int decltype(a)").
0: branch 2 not taken
16: branch 3 taken
451 16: if (DS.SetTypeSpecType(DeclSpec::TST_decltype, StartLoc, PrevSpec,
452 : DiagID, Result.release()))
16: branch 4 taken
0: branch 5 not taken
16: branch 7 taken
0: branch 8 not taken
453 0: Diag(StartLoc, DiagID) << PrevSpec;
454 : }
455 :
456 : /// ParseClassName - Parse a C++ class-name, which names a class. Note
457 : /// that we only check that the result names a type; semantic analysis
458 : /// will need to verify that the type names a class. The result is
459 : /// either a type or NULL, depending on whether a type name was
460 : /// found.
461 : ///
462 : /// class-name: [C++ 9.1]
463 : /// identifier
464 : /// simple-template-id
465 : ///
466 : Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation,
467 : const CXXScopeSpec *SS,
468 901: bool DestrExpected) {
469 : // Check whether we have a template-id that names a type.
81: branch 1 taken
820: branch 2 taken
470 901: if (Tok.is(tok::annot_template_id)) {
471 : TemplateIdAnnotation *TemplateId
472 81: = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
2: branch 0 taken
79: branch 1 taken
2: branch 2 taken
0: branch 3 not taken
473 81: if (TemplateId->Kind == TNK_Type_template ||
474 : TemplateId->Kind == TNK_Dependent_template_name) {
475 81: AnnotateTemplateIdTokenAsType(SS);
476 :
81: branch 1 taken
0: branch 2 not taken
477 81: assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
478 81: TypeTy *Type = Tok.getAnnotationValue();
479 81: EndLocation = Tok.getAnnotationEndLoc();
480 81: ConsumeToken();
481 :
80: branch 0 taken
1: branch 1 taken
482 81: if (Type)
483 80: return Type;
484 1: return true;
485 : }
486 :
487 : // Fall through to produce an error below.
488 : }
489 :
0: branch 1 not taken
820: branch 2 taken
490 820: if (Tok.isNot(tok::identifier)) {
491 0: Diag(Tok, diag::err_expected_class_name);
492 0: return true;
493 : }
494 :
495 820: IdentifierInfo *Id = Tok.getIdentifierInfo();
496 820: SourceLocation IdLoc = ConsumeToken();
497 :
2: branch 1 taken
818: branch 2 taken
498 820: if (Tok.is(tok::less)) {
499 : // It looks the user intended to write a template-id here, but the
500 : // template-name was wrong. Try to fix that.
501 2: TemplateNameKind TNK = TNK_Type_template;
502 2: TemplateTy Template;
1: branch 1 taken
1: branch 2 taken
503 2: if (!Actions.DiagnoseUnknownTemplateName(*Id, IdLoc, CurScope,
504 : SS, Template, TNK)) {
505 : Diag(IdLoc, diag::err_unknown_template_name)
506 1: << Id;
507 : }
508 :
1: branch 1 taken
1: branch 2 taken
509 2: if (!Template)
510 1: return true;
511 :
512 : // Form the template name
513 1: UnqualifiedId TemplateName;
514 1: TemplateName.setIdentifier(Id, IdLoc);
515 :
516 : // Parse the full template-id, then turn it into a type.
0: branch 2 not taken
1: branch 3 taken
517 1: if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateName,
518 : SourceLocation(), true))
519 0: return true;
1: branch 0 taken
0: branch 1 not taken
520 1: if (TNK == TNK_Dependent_template_name)
521 1: AnnotateTemplateIdTokenAsType(SS);
522 :
523 : // If we didn't end up with a typename token, there's nothing more we
524 : // can do.
0: branch 1 not taken
1: branch 2 taken
525 1: if (Tok.isNot(tok::annot_typename))
526 0: return true;
527 :
528 : // Retrieve the type from the annotation token, consume that token, and
529 : // return.
530 1: EndLocation = Tok.getAnnotationEndLoc();
531 1: TypeTy *Type = Tok.getAnnotationValue();
532 1: ConsumeToken();
533 1: return Type;
534 : }
535 :
536 : // We have an identifier; check whether it is actually a type.
537 818: TypeTy *Type = Actions.getTypeName(*Id, IdLoc, CurScope, SS, true);
0: branch 0 not taken
818: branch 1 taken
538 818: if (!Type) {
539 : Diag(IdLoc, DestrExpected ? diag::err_destructor_class_name
0: branch 0 not taken
0: branch 1 not taken
540 0: : diag::err_expected_class_name);
541 0: return true;
542 : }
543 :
544 : // Consume the identifier.
545 818: EndLocation = IdLoc;
546 818: return Type;
547 : }
548 :
549 : /// ParseClassSpecifier - Parse a C++ class-specifier [C++ class] or
550 : /// elaborated-type-specifier [C++ dcl.type.elab]; we can't tell which
551 : /// until we reach the start of a definition or see a token that
552 : /// cannot start a definition. If SuppressDeclarations is true, we do know.
553 : ///
554 : /// class-specifier: [C++ class]
555 : /// class-head '{' member-specification[opt] '}'
556 : /// class-head '{' member-specification[opt] '}' attributes[opt]
557 : /// class-head:
558 : /// class-key identifier[opt] base-clause[opt]
559 : /// class-key nested-name-specifier identifier base-clause[opt]
560 : /// class-key nested-name-specifier[opt] simple-template-id
561 : /// base-clause[opt]
562 : /// [GNU] class-key attributes[opt] identifier[opt] base-clause[opt]
563 : /// [GNU] class-key attributes[opt] nested-name-specifier
564 : /// identifier base-clause[opt]
565 : /// [GNU] class-key attributes[opt] nested-name-specifier[opt]
566 : /// simple-template-id base-clause[opt]
567 : /// class-key:
568 : /// 'class'
569 : /// 'struct'
570 : /// 'union'
571 : ///
572 : /// elaborated-type-specifier: [C++ dcl.type.elab]
573 : /// class-key ::[opt] nested-name-specifier[opt] identifier
574 : /// class-key ::[opt] nested-name-specifier[opt] 'template'[opt]
575 : /// simple-template-id
576 : ///
577 : /// Note that the C++ class-specifier and elaborated-type-specifier,
578 : /// together, subsume the C99 struct-or-union-specifier:
579 : ///
580 : /// struct-or-union-specifier: [C99 6.7.2.1]
581 : /// struct-or-union identifier[opt] '{' struct-contents '}'
582 : /// struct-or-union identifier
583 : /// [GNU] struct-or-union attributes[opt] identifier[opt] '{' struct-contents
584 : /// '}' attributes[opt]
585 : /// [GNU] struct-or-union attributes[opt] identifier
586 : /// struct-or-union:
587 : /// 'struct'
588 : /// 'union'
589 : void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
590 : SourceLocation StartLoc, DeclSpec &DS,
591 : const ParsedTemplateInfo &TemplateInfo,
592 7114: AccessSpecifier AS, bool SuppressDeclarations){
593 : DeclSpec::TST TagType;
5928: branch 0 taken
1186: branch 1 taken
594 7114: if (TagTokKind == tok::kw_struct)
595 5928: TagType = DeclSpec::TST_struct;
885: branch 0 taken
301: branch 1 taken
596 1186: else if (TagTokKind == tok::kw_class)
597 885: TagType = DeclSpec::TST_class;
598 : else {
0: branch 0 not taken
301: branch 1 taken
599 301: assert(TagTokKind == tok::kw_union && "Not a class specifier");
600 301: TagType = DeclSpec::TST_union;
601 : }
602 :
3: branch 1 taken
7111: branch 2 taken
603 7114: if (Tok.is(tok::code_completion)) {
604 : // Code completion for a struct, class, or union name.
605 3: Actions.CodeCompleteTag(CurScope, TagType);
606 3: ConsumeToken();
607 : }
608 :
609 7114: AttributeList *AttrList = 0;
610 : // If attributes exist after tag, parse them.
18: branch 1 taken
7096: branch 2 taken
611 7114: if (Tok.is(tok::kw___attribute))
612 18: AttrList = ParseGNUAttributes();
613 :
614 : // If declspecs exist after tag, parse them.
0: branch 1 not taken
7114: branch 2 taken
615 7114: if (Tok.is(tok::kw___declspec))
616 0: AttrList = ParseMicrosoftDeclSpec(AttrList);
617 :
618 : // If C++0x attributes exist here, parse them.
619 : // FIXME: Are we consistent with the ordering of parsing of different
620 : // styles of attributes?
3: branch 1 taken
7111: branch 2 taken
621 7114: if (isCXX0XAttributeSpecifier())
622 3: AttrList = addAttributeLists(AttrList, ParseCXX0XAttributes().AttrList);
623 :
5928: branch 0 taken
1186: branch 1 taken
1: branch 3 taken
5927: branch 4 taken
1: branch 5 taken
7113: branch 6 taken
624 7114: if (TagType == DeclSpec::TST_struct && Tok.is(tok::kw___is_pod)) {
625 : // GNU libstdc++ 4.2 uses __is_pod as the name of a struct template, but
626 : // __is_pod is a keyword in GCC >= 4.3. Therefore, when we see the
627 : // token sequence "struct __is_pod", make __is_pod into a normal
628 : // identifier rather than a keyword, to allow libstdc++ 4.2 to work
629 : // properly.
630 1: Tok.getIdentifierInfo()->setTokenID(tok::identifier);
631 1: Tok.setKind(tok::identifier);
632 : }
633 :
5928: branch 0 taken
1186: branch 1 taken
0: branch 3 not taken
5928: branch 4 taken
0: branch 5 not taken
7114: branch 6 taken
634 7114: if (TagType == DeclSpec::TST_struct && Tok.is(tok::kw___is_empty)) {
635 : // GNU libstdc++ 4.2 uses __is_empty as the name of a struct template, but
636 : // __is_empty is a keyword in GCC >= 4.3. Therefore, when we see the
637 : // token sequence "struct __is_empty", make __is_empty into a normal
638 : // identifier rather than a keyword, to allow libstdc++ 4.2 to work
639 : // properly.
640 0: Tok.getIdentifierInfo()->setTokenID(tok::identifier);
641 0: Tok.setKind(tok::identifier);
642 : }
643 :
644 : // Parse the (optional) nested-name-specifier.
645 7114: CXXScopeSpec &SS = DS.getTypeSpecScope();
4181: branch 1 taken
2933: branch 2 taken
646 7114: if (getLang().CPlusPlus) {
647 : // "FOO : BAR" is not a potential typo for "FOO::BAR".
648 4181: ColonProtectionRAIIObject X(*this);
649 :
125: branch 1 taken
4056: branch 2 taken
650 4181: if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true))
54: branch 1 taken
71: branch 2 taken
0: branch 4 not taken
54: branch 5 taken
0: branch 6 not taken
125: branch 7 taken
651 125: if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
652 0: Diag(Tok, diag::err_expected_ident);
653 : }
654 :
655 7114: TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;
656 :
657 : // Parse the (optional) class name or simple-template-id.
658 7114: IdentifierInfo *Name = 0;
659 7114: SourceLocation NameLoc;
660 7114: TemplateIdAnnotation *TemplateId = 0;
6113: branch 1 taken
1001: branch 2 taken
661 7114: if (Tok.is(tok::identifier)) {
662 6113: Name = Tok.getIdentifierInfo();
663 6113: NameLoc = ConsumeToken();
664 :
3: branch 1 taken
6110: branch 2 taken
665 6113: if (Tok.is(tok::less)) {
666 : // The name was supposed to refer to a template, but didn't.
667 : // Eat the template argument list and try to continue parsing this as
668 : // a class (or template thereof).
669 3: TemplateArgList TemplateArgs;
670 3: SourceLocation LAngleLoc, RAngleLoc;
0: branch 2 not taken
3: branch 3 taken
671 3: if (ParseTemplateIdAfterTemplateName(TemplateTy(), NameLoc, &SS,
672 : true, LAngleLoc,
673 : TemplateArgs, RAngleLoc)) {
674 : // We couldn't parse the template argument list at all, so don't
675 : // try to give any location information for the list.
676 0: LAngleLoc = RAngleLoc = SourceLocation();
677 : }
678 :
679 : Diag(NameLoc, diag::err_explicit_spec_non_template)
680 : << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
681 : << (TagType == DeclSpec::TST_class? 0
682 : : TagType == DeclSpec::TST_struct? 1
683 : : 2)
684 : << Name
1: branch 1 taken
2: branch 2 taken
1: branch 3 taken
0: branch 4 not taken
685 3: << SourceRange(LAngleLoc, RAngleLoc);
686 :
687 : // Strip off the last template parameter list if it was empty, since
688 : // we've removed its template argument list.
2: branch 0 taken
1: branch 1 taken
2: branch 2 taken
0: branch 3 not taken
689 5: if (TemplateParams && TemplateInfo.LastParameterListWasEmpty) {
2: branch 0 taken
0: branch 1 not taken
0: branch 3 not taken
2: branch 4 taken
0: branch 5 not taken
2: branch 6 taken
690 2: if (TemplateParams && TemplateParams->size() > 1) {
691 0: TemplateParams->pop_back();
692 : } else {
693 2: TemplateParams = 0;
694 : const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind
695 2: = ParsedTemplateInfo::NonTemplate;
696 : }
1: branch 0 taken
0: branch 1 not taken
697 1: } else if (TemplateInfo.Kind
698 : == ParsedTemplateInfo::ExplicitInstantiation) {
699 : // Pretend this is just a forward declaration.
700 1: TemplateParams = 0;
701 : const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind
702 1: = ParsedTemplateInfo::NonTemplate;
703 : const_cast<ParsedTemplateInfo&>(TemplateInfo).TemplateLoc
704 1: = SourceLocation();
705 : const_cast<ParsedTemplateInfo&>(TemplateInfo).ExternLoc
706 1: = SourceLocation();
707 3: }
708 :
709 :
710 : }
441: branch 1 taken
560: branch 2 taken
711 1001: } else if (Tok.is(tok::annot_template_id)) {
712 441: TemplateId = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
713 441: NameLoc = ConsumeToken();
714 :
1: branch 0 taken
440: branch 1 taken
715 441: if (TemplateId->Kind != TNK_Type_template) {
716 : // The template-name in the simple-template-id refers to
717 : // something other than a class template. Give an appropriate
718 : // error message and skip to the ';'.
719 1: SourceRange Range(NameLoc);
0: branch 1 not taken
1: branch 2 taken
720 1: if (SS.isNotEmpty())
721 0: Range.setBegin(SS.getBeginLoc());
722 :
723 : Diag(TemplateId->LAngleLoc, diag::err_template_spec_syntax_non_template)
724 1: << Name << static_cast<int>(TemplateId->Kind) << Range;
725 :
726 1: DS.SetTypeSpecError();
727 1: SkipUntil(tok::semi, false, true);
728 1: TemplateId->Destroy();
729 1: return;
730 : }
731 : }
732 :
733 : // There are four options here. If we have 'struct foo;', then this
734 : // is either a forward declaration or a friend declaration, which
735 : // have to be treated differently. If we have 'struct foo {...' or
736 : // 'struct foo :...' then this is a definition. Otherwise we have
737 : // something like 'struct foo xyz', a reference.
738 : // However, in some contexts, things look like declarations but are just
739 : // references, e.g.
740 : // new struct s;
741 : // or
742 : // &T::operator struct s;
743 : // For these, SuppressDeclarations is true.
744 : Action::TagUseKind TUK;
3: branch 0 taken
7110: branch 1 taken
745 7113: if (SuppressDeclarations)
746 3: TUK = Action::TUK_Reference;
2991: branch 1 taken
4119: branch 2 taken
1474: branch 4 taken
1517: branch 5 taken
701: branch 7 taken
773: branch 8 taken
4820: branch 9 taken
2290: branch 10 taken
747 7110: else if (Tok.is(tok::l_brace) || (getLang().CPlusPlus && Tok.is(tok::colon))){
1: branch 1 taken
4819: branch 2 taken
748 4820: if (DS.isFriendSpecified()) {
749 : // C++ [class.friend]p2:
750 : // A class shall not be defined in a friend declaration.
751 : Diag(Tok.getLocation(), diag::err_friend_decl_defines_class)
752 1: << SourceRange(DS.getFriendSpecLoc());
753 :
754 : // Skip everything up to the semicolon, so that this looks like a proper
755 : // friend class (or template thereof) declaration.
756 1: SkipUntil(tok::semi, true, true);
757 1: TUK = Action::TUK_Friend;
758 : } else {
759 : // Okay, this is a class definition.
760 4819: TUK = Action::TUK_Definition;
761 : }
711: branch 1 taken
1579: branch 2 taken
762 2290: } else if (Tok.is(tok::semi))
42: branch 1 taken
669: branch 2 taken
763 711: TUK = DS.isFriendSpecified() ? Action::TUK_Friend : Action::TUK_Declaration;
764 : else
765 1579: TUK = Action::TUK_Reference;
766 :
1000: branch 0 taken
6113: branch 1 taken
560: branch 2 taken
440: branch 3 taken
5: branch 4 taken
555: branch 5 taken
767 7113: if (!Name && !TemplateId && TUK != Action::TUK_Definition) {
768 : // We have a declaration or reference to an anonymous class.
769 : Diag(StartLoc, diag::err_anon_type_definition)
770 5: << DeclSpec::getSpecifierName(TagType);
771 :
772 5: SkipUntil(tok::comma, true);
773 :
0: branch 0 not taken
5: branch 1 taken
774 5: if (TemplateId)
775 0: TemplateId->Destroy();
776 5: return;
777 : }
778 :
779 : // Create the tag portion of the class or class template.
780 7108: Action::DeclResult TagOrTempResult = true; // invalid
781 7108: Action::TypeResult TypeResult = true; // invalid
782 :
783 : // FIXME: When TUK == TUK_Reference and we have a template-id, we need
784 : // to turn that template-id into a type.
785 :
786 7108: bool Owned = false;
440: branch 0 taken
6668: branch 1 taken
787 7108: if (TemplateId) {
788 : // Explicit specialization, class template partial specialization,
789 : // or explicit instantiation.
790 : ASTTemplateArgsPtr TemplateArgsPtr(Actions,
791 : TemplateId->getTemplateArgs(),
792 440: TemplateId->NumArgs);
235: branch 0 taken
205: branch 1 taken
234: branch 2 taken
1: branch 3 taken
793 674: if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
794 : TUK == Action::TUK_Declaration) {
795 : // This is an explicit instantiation of a class template.
796 : TagOrTempResult
797 : = Actions.ActOnExplicitInstantiation(CurScope,
798 : TemplateInfo.ExternLoc,
799 : TemplateInfo.TemplateLoc,
800 : TagType,
801 : StartLoc,
802 : SS,
803 : TemplateTy::make(TemplateId->Template),
804 : TemplateId->TemplateNameLoc,
805 : TemplateId->LAngleLoc,
806 : TemplateArgsPtr,
807 : TemplateId->RAngleLoc,
808 234: AttrList);
8: branch 0 taken
198: branch 1 taken
809 206: } else if (TUK == Action::TUK_Reference) {
810 : TypeResult
811 : = Actions.ActOnTemplateIdType(TemplateTy::make(TemplateId->Template),
812 : TemplateId->TemplateNameLoc,
813 : TemplateId->LAngleLoc,
814 : TemplateArgsPtr,
815 8: TemplateId->RAngleLoc);
816 :
817 : TypeResult = Actions.ActOnTagTemplateIdType(TypeResult, TUK,
818 8: TagType, StartLoc);
819 : } else {
820 : // This is an explicit specialization or a class template
821 : // partial specialization.
822 198: TemplateParameterLists FakedParamLists;
823 :
1: branch 0 taken
197: branch 1 taken
824 198: if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {
825 : // This looks like an explicit instantiation, because we have
826 : // something like
827 : //
828 : // template class Foo<X>
829 : //
830 : // but it actually has a definition. Most likely, this was
831 : // meant to be an explicit specialization, but the user forgot
832 : // the '<>' after 'template'.
0: branch 0 not taken
1: branch 1 taken
833 1: assert(TUK == Action::TUK_Definition && "Expected a definition here");
834 :
835 : SourceLocation LAngleLoc
836 1: = PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);
837 : Diag(TemplateId->TemplateNameLoc,
838 : diag::err_explicit_instantiation_with_definition)
839 : << SourceRange(TemplateInfo.TemplateLoc)
840 1: << CodeModificationHint::CreateInsertion(LAngleLoc, "<>");
841 :
842 : // Create a fake template parameter list that contains only
843 : // "template<>", so that we treat this construct as a class
844 : // template specialization.
845 : FakedParamLists.push_back(
846 : Actions.ActOnTemplateParameterList(0, SourceLocation(),
847 : TemplateInfo.TemplateLoc,
848 : LAngleLoc,
849 : 0, 0,
850 1: LAngleLoc));
851 1: TemplateParams = &FakedParamLists;
852 : }
853 :
854 : // Build the class template specialization.
855 : TagOrTempResult
856 : = Actions.ActOnClassTemplateSpecialization(CurScope, TagType, TUK,
857 : StartLoc, SS,
858 : TemplateTy::make(TemplateId->Template),
859 : TemplateId->TemplateNameLoc,
860 : TemplateId->LAngleLoc,
861 : TemplateArgsPtr,
862 : TemplateId->RAngleLoc,
863 : AttrList,
864 : Action::MultiTemplateParamsArg(Actions,
865 : TemplateParams? &(*TemplateParams)[0] : 0,
193: branch 0 taken
5: branch 1 taken
193: branch 3 taken
5: branch 4 taken
866 198: TemplateParams? TemplateParams->size() : 0));
867 : }
868 440: TemplateId->Destroy();
15: branch 0 taken
6653: branch 1 taken
15: branch 2 taken
0: branch 3 not taken
869 6683: } else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
870 : TUK == Action::TUK_Declaration) {
871 : // Explicit instantiation of a member of a class template
872 : // specialization, e.g.,
873 : //
874 : // template struct Outer<int>::Inner;
875 : //
876 : TagOrTempResult
877 : = Actions.ActOnExplicitInstantiation(CurScope,
878 : TemplateInfo.ExternLoc,
879 : TemplateInfo.TemplateLoc,
880 : TagType, StartLoc, SS, Name,
881 15: NameLoc, AttrList);
882 : } else {
883 6653: if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
884 : TUK == Action::TUK_Definition) {
885 : // FIXME: Diagnose this particular error.
886 : }
887 :
888 6653: bool IsDependent = false;
889 :
890 : // Declaration or definition of a class type
891 : TagOrTempResult = Actions.ActOnTag(CurScope, TagType, TUK, StartLoc, SS,
892 : Name, NameLoc, AttrList, AS,
893 : Action::MultiTemplateParamsArg(Actions,
894 : TemplateParams? &(*TemplateParams)[0] : 0,
895 : TemplateParams? TemplateParams->size() : 0),
993: branch 0 taken
5660: branch 1 taken
993: branch 3 taken
5660: branch 4 taken
896 6653: Owned, IsDependent);
897 :
898 : // If ActOnTag said the type was dependent, try again with the
899 : // less common call.
3: branch 0 taken
6650: branch 1 taken
900 6653: if (IsDependent)
901 : TypeResult = Actions.ActOnDependentTag(CurScope, TagType, TUK,
902 3: SS, Name, StartLoc, NameLoc);
903 : }
904 :
905 : // If there is a body, parse it and inform the actions module.
4819: branch 0 taken
2289: branch 1 taken
906 7108: if (TUK == Action::TUK_Definition) {
907 : assert(Tok.is(tok::l_brace) ||
701: branch 1 taken
4118: branch 2 taken
701: branch 4 taken
0: branch 5 not taken
0: branch 7 not taken
701: branch 8 taken
908 4819: (getLang().CPlusPlus && Tok.is(tok::colon)));
3403: branch 1 taken
1416: branch 2 taken
909 4819: if (getLang().CPlusPlus)
910 3403: ParseCXXMemberSpecification(StartLoc, TagType, TagOrTempResult.get());
911 : else
912 1416: ParseStructUnionBody(StartLoc, TagType, TagOrTempResult.get());
913 : }
914 :
915 : void *Result;
11: branch 1 taken
7097: branch 2 taken
916 7108: if (!TypeResult.isInvalid()) {
917 11: TagType = DeclSpec::TST_typename;
918 11: Result = TypeResult.get();
919 11: Owned = false;
7080: branch 1 taken
17: branch 2 taken
920 7097: } else if (!TagOrTempResult.isInvalid()) {
921 7080: Result = TagOrTempResult.get().getAs<void>();
922 : } else {
923 17: DS.SetTypeSpecError();
924 17: return;
925 : }
926 :
927 7091: const char *PrevSpec = 0;
928 : unsigned DiagID;
929 :
930 : // FIXME: The DeclSpec should keep the locations of both the keyword and the
931 : // name (if there is one).
6536: branch 1 taken
555: branch 2 taken
932 7091: SourceLocation TSTLoc = NameLoc.isValid()? NameLoc : StartLoc;
933 :
0: branch 1 not taken
7091: branch 2 taken
934 7091: if (DS.SetTypeSpecType(TagType, TSTLoc, PrevSpec, DiagID,
935 : Result, Owned))
936 0: Diag(StartLoc, DiagID) << PrevSpec;
937 :
938 : // At this point, we've successfully parsed a class-specifier in 'definition'
939 : // form (e.g. "struct foo { int x; }". While we could just return here, we're
940 : // going to look at what comes after it to improve error recovery. If an
941 : // impossible token occurs next, we assume that the programmer forgot a ; at
942 : // the end of the declaration and recover that way.
943 : //
944 : // This switch enumerates the valid "follow" set for definition.
4811: branch 0 taken
2280: branch 1 taken
945 7091: if (TUK == Action::TUK_Definition) {
4806: branch 1 taken
1: branch 2 taken
4: branch 3 taken
946 4811: switch (Tok.getKind()) {
947 : case tok::semi: // struct foo {...} ;
948 : case tok::star: // struct foo {...} * P;
949 : case tok::amp: // struct foo {...} & R = ...
950 : case tok::identifier: // struct foo {...} V ;
951 : case tok::r_paren: //(struct foo {...} ) {4}
952 : case tok::annot_cxxscope: // struct foo {...} a:: b;
953 : case tok::annot_typename: // struct foo {...} a ::b;
954 : case tok::annot_template_id: // struct foo {...} a<int> ::b;
955 : case tok::l_paren: // struct foo {...} ( x);
956 : case tok::comma: // __builtin_offsetof(struct foo{...} ,
957 : // Storage-class specifiers
958 : case tok::kw_static: // struct foo {...} static x;
959 : case tok::kw_extern: // struct foo {...} extern x;
960 : case tok::kw_typedef: // struct foo {...} typedef x;
961 : case tok::kw_register: // struct foo {...} register x;
962 : case tok::kw_auto: // struct foo {...} auto x;
963 : // Type qualifiers
964 : case tok::kw_const: // struct foo {...} const x;
965 : case tok::kw_volatile: // struct foo {...} volatile x;
966 : case tok::kw_restrict: // struct foo {...} restrict x;
967 : case tok::kw_inline: // struct foo {...} inline foo() {};
968 4806: break;
969 :
970 : case tok::r_brace: // struct bar { struct foo {...} }
971 : // Missing ';' at end of struct is accepted as an extension in C mode.
0: branch 1 not taken
1: branch 2 taken
972 1: if (!getLang().CPlusPlus) break;
973 : // FALL THROUGH.
974 : default:
975 : ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
976 : TagType == DeclSpec::TST_class ? "class"
4: branch 0 taken
0: branch 1 not taken
4: branch 2 taken
0: branch 3 not taken
977 4: : TagType == DeclSpec::TST_struct? "struct" : "union");
978 : // Push this token back into the preprocessor and change our current token
979 : // to ';' so that the rest of the code recovers as though there were an
980 : // ';' after the definition.
981 4: PP.EnterToken(Tok);
982 4: Tok.setKind(tok::semi);
983 : break;
984 : }
985 : }
986 : }
987 :
988 : /// ParseBaseClause - Parse the base-clause of a C++ class [C++ class.derived].
989 : ///
990 : /// base-clause : [C++ class.derived]
991 : /// ':' base-specifier-list
992 : /// base-specifier-list:
993 : /// base-specifier '...'[opt]
994 : /// base-specifier-list ',' base-specifier '...'[opt]
995 701: void Parser::ParseBaseClause(DeclPtrTy ClassDecl) {
701: branch 1 taken
0: branch 2 not taken
996 701: assert(Tok.is(tok::colon) && "Not a base clause");
997 701: ConsumeToken();
998 :
999 : // Build up an array of parsed base specifiers.
1000 701: llvm::SmallVector<BaseTy *, 8> BaseInfo;
1001 :
1002 200: while (true) {
1003 : // Parse a base-specifier.
1004 901: BaseResult Result = ParseBaseSpecifier(ClassDecl);
9: branch 1 taken
892: branch 2 taken
1005 901: if (Result.isInvalid()) {
1006 : // Skip the rest of this base specifier, up until the comma or
1007 : // opening brace.
1008 9: SkipUntil(tok::comma, tok::l_brace, true, true);
1009 : } else {
1010 : // Add this to our array of base specifiers.
1011 892: BaseInfo.push_back(Result.get());
1012 : }
1013 :
1014 : // If the next token is a comma, consume it and keep reading
1015 : // base-specifiers.
200: branch 1 taken
701: branch 2 taken
1016 901: if (Tok.isNot(tok::comma)) break;
1017 :
1018 : // Consume the comma.
1019 200: ConsumeToken();
1020 : }
1021 :
1022 : // Attach the base specifiers
1023 701: Actions.ActOnBaseSpecifiers(ClassDecl, BaseInfo.data(), BaseInfo.size());
1024 701: }
1025 :
1026 : /// ParseBaseSpecifier - Parse a C++ base-specifier. A base-specifier is
1027 : /// one entry in the base class list of a class specifier, for example:
1028 : /// class foo : public bar, virtual private baz {
1029 : /// 'public bar' and 'virtual private baz' are each base-specifiers.
1030 : ///
1031 : /// base-specifier: [C++ class.derived]
1032 : /// ::[opt] nested-name-specifier[opt] class-name
1033 : /// 'virtual' access-specifier[opt] ::[opt] nested-name-specifier[opt]
1034 : /// class-name
1035 : /// access-specifier 'virtual'[opt] ::[opt] nested-name-specifier[opt]
1036 : /// class-name
1037 901: Parser::BaseResult Parser::ParseBaseSpecifier(DeclPtrTy ClassDecl) {
1038 901: bool IsVirtual = false;
1039 901: SourceLocation StartLoc = Tok.getLocation();
1040 :
1041 : // Parse the 'virtual' keyword.
163: branch 1 taken
738: branch 2 taken
1042 901: if (Tok.is(tok::kw_virtual)) {
1043 163: ConsumeToken();
1044 163: IsVirtual = true;
1045 : }
1046 :
1047 : // Parse an (optional) access specifier.
1048 901: AccessSpecifier Access = getAccessSpecifierIfPresent();
294: branch 0 taken
607: branch 1 taken
1049 901: if (Access != AS_none)
1050 294: ConsumeToken();
1051 :
1052 : // Parse the 'virtual' keyword (again!), in case it came after the
1053 : // access specifier.
36: branch 1 taken
865: branch 2 taken
1054 901: if (Tok.is(tok::kw_virtual)) {
1055 36: SourceLocation VirtualLoc = ConsumeToken();
2: branch 0 taken
34: branch 1 taken
1056 36: if (IsVirtual) {
1057 : // Complain about duplicate 'virtual'
1058 : Diag(VirtualLoc, diag::err_dup_virtual)
1059 2: << CodeModificationHint::CreateRemoval(VirtualLoc);
1060 : }
1061 :
1062 36: IsVirtual = true;
1063 : }
1064 :
1065 : // Parse optional '::' and optional nested-name-specifier.
1066 901: CXXScopeSpec SS;
1067 901: ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true);
1068 :
1069 : // The location of the base class itself.
1070 901: SourceLocation BaseLoc = Tok.getLocation();
1071 :
1072 : // Parse the class-name.
1073 901: SourceLocation EndLocation;
1074 901: TypeResult BaseType = ParseClassName(EndLocation, &SS);
2: branch 1 taken
899: branch 2 taken
1075 901: if (BaseType.isInvalid())
1076 2: return true;
1077 :
1078 : // Find the complete source range for the base-specifier.
1079 899: SourceRange Range(StartLoc, EndLocation);
1080 :
1081 : // Notify semantic analysis that we have parsed a complete
1082 : // base-specifier.
1083 : return Actions.ActOnBaseSpecifier(ClassDecl, Range, IsVirtual, Access,
1084 899: BaseType.get(), BaseLoc);
1085 : }
1086 :
1087 : /// getAccessSpecifierIfPresent - Determine whether the next token is
1088 : /// a C++ access-specifier.
1089 : ///
1090 : /// access-specifier: [C++ class.derived]
1091 : /// 'private'
1092 : /// 'protected'
1093 : /// 'public'
1094 6133: AccessSpecifier Parser::getAccessSpecifierIfPresent() const {
5617: branch 1 taken
41: branch 2 taken
23: branch 3 taken
452: branch 4 taken
1095 6133: switch (Tok.getKind()) {
1096 5617: default: return AS_none;
1097 41: case tok::kw_private: return AS_private;
1098 23: case tok::kw_protected: return AS_protected;
1099 452: case tok::kw_public: return AS_public;
1100 : }
1101 : }
1102 :
1103 : void Parser::HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo,
1104 2736: DeclPtrTy ThisDecl) {
1105 : // We just declared a member function. If this member function
1106 : // has any default arguments, we'll need to parse them later.
1107 2736: LateParsedMethodDeclaration *LateMethod = 0;
1108 : DeclaratorChunk::FunctionTypeInfo &FTI
1109 2736: = DeclaratorInfo.getTypeObject(0).Fun;
1201: branch 0 taken
2736: branch 1 taken
1110 3937: for (unsigned ParamIdx = 0; ParamIdx < FTI.NumArgs; ++ParamIdx) {
1187: branch 0 taken
14: branch 1 taken
68: branch 2 taken
1119: branch 3 taken
1111 1201: if (LateMethod || FTI.ArgInfo[ParamIdx].DefaultArgTokens) {
68: branch 0 taken
14: branch 1 taken
1112 82: if (!LateMethod) {
1113 : // Push this method onto the stack of late-parsed method
1114 : // declarations.
1115 : getCurrentClass().MethodDecls.push_back(
1116 68: LateParsedMethodDeclaration(ThisDecl));
1117 68: LateMethod = &getCurrentClass().MethodDecls.back();
1118 68: LateMethod->TemplateScope = CurScope->isTemplateParamScope();
1119 :
1120 : // Add all of the parameters prior to this one (they don't
1121 : // have default arguments).
1122 68: LateMethod->DefaultArgs.reserve(FTI.NumArgs);
25: branch 0 taken
68: branch 1 taken
1123 93: for (unsigned I = 0; I < ParamIdx; ++I)
1124 : LateMethod->DefaultArgs.push_back(
1125 25: LateParsedDefaultArgument(FTI.ArgInfo[ParamIdx].Param));
1126 : }
1127 :
1128 : // Add this parameter to the list of parameters (it or may
1129 : // not have a default argument).
1130 : LateMethod->DefaultArgs.push_back(
1131 : LateParsedDefaultArgument(FTI.ArgInfo[ParamIdx].Param,
1132 82: FTI.ArgInfo[ParamIdx].DefaultArgTokens));
1133 : }
1134 : }
1135 2736: }
1136 :
1137 : /// ParseCXXClassMemberDeclaration - Parse a C++ class member declaration.
1138 : ///
1139 : /// member-declaration:
1140 : /// decl-specifier-seq[opt] member-declarator-list[opt] ';'
1141 : /// function-definition ';'[opt]
1142 : /// ::[opt] nested-name-specifier template[opt] unqualified-id ';'[TODO]
1143 : /// using-declaration [TODO]
1144 : /// [C++0x] static_assert-declaration
1145 : /// template-declaration
1146 : /// [GNU] '__extension__' member-declaration
1147 : ///
1148 : /// member-declarator-list:
1149 : /// member-declarator
1150 : /// member-declarator-list ',' member-declarator
1151 : ///
1152 : /// member-declarator:
1153 : /// declarator pure-specifier[opt]
1154 : /// declarator constant-initializer[opt]
1155 : /// identifier[opt] ':' constant-expression
1156 : ///
1157 : /// pure-specifier:
1158 : /// '= 0'
1159 : ///
1160 : /// constant-initializer:
1161 : /// '=' constant-expression
1162 : ///
1163 : void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
1164 5222: const ParsedTemplateInfo &TemplateInfo) {
1165 : // Access declarations.
5021: branch 0 taken
201: branch 1 taken
4065: branch 3 taken
956: branch 4 taken
0: branch 6 not taken
4065: branch 7 taken
45: branch 9 taken
911: branch 10 taken
2: branch 12 taken
43: branch 13 taken
2: branch 14 taken
5220: branch 15 taken
1166 5222: if (!TemplateInfo.Kind &&
1167 : (Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) &&
1168 : TryAnnotateCXXScopeToken() &&
1169 : Tok.is(tok::annot_cxxscope)) {
1170 2: bool isAccessDecl = false;
2: branch 2 taken
0: branch 3 not taken
1171 2: if (NextToken().is(tok::identifier))
1172 2: isAccessDecl = GetLookAheadToken(2).is(tok::semi);
1173 : else
1174 0: isAccessDecl = NextToken().is(tok::kw_operator);
1175 :
1: branch 0 taken
1: branch 1 taken
1176 2: if (isAccessDecl) {
1177 : // Collect the scope specifier token we annotated earlier.
1178 1: CXXScopeSpec SS;
1179 1: ParseOptionalCXXScopeSpecifier(SS, /*ObjectType*/ 0, false);
1180 :
1181 : // Try to parse an unqualified-id.
1182 1: UnqualifiedId Name;
0: branch 1 not taken
1: branch 2 taken
1183 1: if (ParseUnqualifiedId(SS, false, true, true, /*ObjectType*/ 0, Name)) {
1184 0: SkipUntil(tok::semi);
1185 : return;
1186 : }
1187 :
1188 : // TODO: recover from mistakenly-qualified operator declarations.
1: branch 1 taken
0: branch 2 not taken
1189 1: if (ExpectAndConsume(tok::semi,
1190 : diag::err_expected_semi_after,
1191 : "access declaration",
1192 : tok::semi))
1193 : return;
1194 :
1195 : Actions.ActOnUsingDeclaration(CurScope, AS,
1196 : false, SourceLocation(),
1197 : SS, Name,
1198 : /* AttrList */ 0,
1199 : /* IsTypeName */ false,
1200 1: SourceLocation());
1201 1: return;
1202 : }
1203 : }
1204 :
1205 : // static_assert-declaration
3: branch 1 taken
5218: branch 2 taken
1206 5221: if (Tok.is(tok::kw_static_assert)) {
1207 : // FIXME: Check for templates
1208 3: SourceLocation DeclEnd;
1209 3: ParseStaticAssertDeclaration(DeclEnd);
1210 3: return;
1211 : }
1212 :
201: branch 1 taken
5017: branch 2 taken
1213 5218: if (Tok.is(tok::kw_template)) {
1214 : assert(!TemplateInfo.TemplateParams &&
0: branch 0 not taken
201: branch 1 taken
1215 201: "Nested template improperly parsed?");
1216 201: SourceLocation DeclEnd;
1217 : ParseDeclarationStartingWithTemplate(Declarator::MemberContext, DeclEnd,
1218 201: AS);
1219 201: return;
1220 : }
1221 :
1222 : // Handle: member-declaration ::= '__extension__' member-declaration
11: branch 1 taken
5006: branch 2 taken
1223 5017: if (Tok.is(tok::kw___extension__)) {
1224 : // __extension__ silences extension warnings in the subexpression.
1225 11: ExtensionRAIIObject O(Diags); // Use RAII to do this.
1226 11: ConsumeToken();
1227 11: return ParseCXXClassMemberDeclaration(AS, TemplateInfo);
1228 : }
1229 :
1230 : // Don't parse FOO:BAR as if it were a typo for FOO::BAR, in this context it
1231 : // is a bitfield.
1232 5006: ColonProtectionRAIIObject X(*this);
1233 :
1234 5006: CXX0XAttributeList AttrList;
1235 : // Optional C++0x attribute-specifier
980: branch 1 taken
4026: branch 2 taken
0: branch 4 not taken
980: branch 5 taken
0: branch 6 not taken
5006: branch 7 taken
1236 5006: if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
1237 0: AttrList = ParseCXX0XAttributes();
1238 :
75: branch 1 taken
4931: branch 2 taken
1239 5006: if (Tok.is(tok::kw_using)) {
1240 : // FIXME: Check for template aliases
1241 :
0: branch 0 not taken
75: branch 1 taken
1242 75: if (AttrList.HasAttr)
1243 : Diag(AttrList.Range.getBegin(), diag::err_attributes_not_allowed)
1244 0: << AttrList.Range;
1245 :
1246 : // Eat 'using'.
1247 75: SourceLocation UsingLoc = ConsumeToken();
1248 :
3: branch 1 taken
72: branch 2 taken
1249 75: if (Tok.is(tok::kw_namespace)) {
1250 3: Diag(UsingLoc, diag::err_using_namespace_in_class);
1251 3: SkipUntil(tok::semi, true, true);
1252 : } else {
1253 72: SourceLocation DeclEnd;
1254 : // Otherwise, it must be using-declaration.
1255 72: ParseUsingDeclaration(Declarator::MemberContext, UsingLoc, DeclEnd, AS);
1256 : }
1257 1438: return;
1258 : }
1259 :
1260 4931: SourceLocation DSStart = Tok.getLocation();
1261 : // decl-specifier-seq:
1262 : // Parse the common declaration-specifiers piece.
1263 4931: ParsingDeclSpec DS(*this);
1264 4931: DS.AddAttributes(AttrList.AttrList);
1265 4931: ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class);
1266 :
1267 : Action::MultiTemplateParamsArg TemplateParams(Actions,
1268 : TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data() : 0,
201: branch 0 taken
4730: branch 1 taken
201: branch 3 taken
4730: branch 4 taken
1269 4931: TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->size() : 0);
1270 :
308: branch 1 taken
4623: branch 2 taken
1271 4931: if (Tok.is(tok::semi)) {
1272 308: ConsumeToken();
1273 308: Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
1274 : return;
1275 : }
1276 :
1277 4623: ParsingDeclarator DeclaratorInfo(*this, DS, Declarator::MemberContext);
1278 :
4615: branch 1 taken
8: branch 2 taken
1279 4623: if (Tok.isNot(tok::colon)) {
1280 : // Don't parse FOO:BAR as if it were a typo for FOO::BAR.
1281 4615: ColonProtectionRAIIObject X(*this);
1282 :
1283 : // Parse the first declarator.
1284 4615: ParseDeclarator(DeclaratorInfo);
1285 : // Error parsing the declarator?
2: branch 1 taken
4613: branch 2 taken
1286 4615: if (!DeclaratorInfo.hasName()) {
1287 : // If so, skip until the semi-colon or a }.
1288 2: SkipUntil(tok::r_brace, true);
1: branch 1 taken
1: branch 2 taken
1289 2: if (Tok.is(tok::semi))
1290 1: ConsumeToken();
1291 : return;
1292 : }
1293 :
1294 : // If attributes exist after the declarator, but before an '{', parse them.
21: branch 1 taken
4592: branch 2 taken
1295 4613: if (Tok.is(tok::kw___attribute)) {
1296 21: SourceLocation Loc;
1297 21: AttributeList *AttrList = ParseGNUAttributes(&Loc);
1298 21: DeclaratorInfo.AddAttributes(AttrList, Loc);
1299 : }
1300 :
1301 : // function-definition:
3724: branch 1 taken
889: branch 2 taken
1846: branch 4 taken
1878: branch 5 taken
1687: branch 7 taken
159: branch 8 taken
3: branch 10 taken
1684: branch 11 taken
1051: branch 12 taken
3562: branch 13 taken
1302 4613: if (Tok.is(tok::l_brace)
1303 : || (DeclaratorInfo.isFunctionDeclarator() &&
1304 : (Tok.is(tok::colon) || Tok.is(tok::kw_try)))) {
0: branch 1 not taken
1051: branch 2 taken
1305 1051: if (!DeclaratorInfo.isFunctionDeclarator()) {
1306 0: Diag(Tok, diag::err_func_def_no_params);
1307 0: ConsumeBrace();
1308 0: SkipUntil(tok::r_brace, true);
1309 : return;
1310 : }
1311 :
0: branch 1 not taken
1051: branch 2 taken
1312 1051: if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
1313 0: Diag(Tok, diag::err_function_declared_typedef);
1314 : // This recovery skips the entire function body. It would be nice
1315 : // to simply call ParseCXXInlineMethodDef() below, however Sema
1316 : // assumes the declarator represents a function, not a typedef.
1317 0: ConsumeBrace();
1318 0: SkipUntil(tok::r_brace, true);
1319 : return;
1320 : }
1321 :
1322 1051: ParseCXXInlineMethodDef(AS, DeclaratorInfo, TemplateInfo);
1323 : return;
3562: branch 1 taken
1053: branch 2 taken
1324 4615: }
1325 : }
1326 :
1327 : // member-declarator-list:
1328 : // member-declarator
1329 : // member-declarator-list ',' member-declarator
1330 :
1331 3570: llvm::SmallVector<DeclPtrTy, 8> DeclsInGroup;
1332 3570: OwningExprResult BitfieldSize(Actions);
1333 3570: OwningExprResult Init(Actions);
1334 3570: bool Deleted = false;
1335 :
1336 61: while (1) {
1337 : // member-declarator:
1338 : // declarator pure-specifier[opt]
1339 : // declarator constant-initializer[opt]
1340 : // identifier[opt] ':' constant-expression
1341 :
65: branch 1 taken
3566: branch 2 taken
1342 3631: if (Tok.is(tok::colon)) {
1343 65: ConsumeToken();
1344 65: BitfieldSize = ParseConstantExpression();
0: branch 1 not taken
65: branch 2 taken
1345 65: if (BitfieldSize.isInvalid())
1346 0: SkipUntil(tok::comma, true, true);
1347 : }
1348 :
1349 : // pure-specifier:
1350 : // '= 0'
1351 : //
1352 : // constant-initializer:
1353 : // '=' constant-expression
1354 : //
1355 : // defaulted/deleted function-definition:
1356 : // '=' 'default' [TODO]
1357 : // '=' 'delete'
1358 :
166: branch 1 taken
3465: branch 2 taken
1359 3631: if (Tok.is(tok::equal)) {
1360 166: ConsumeToken();
34: branch 1 taken
132: branch 2 taken
8: branch 4 taken
26: branch 5 taken
8: branch 6 taken
158: branch 7 taken
1361 166: if (getLang().CPlusPlus0x && Tok.is(tok::kw_delete)) {
1362 8: ConsumeToken();
1363 8: Deleted = true;
1364 : } else {
1365 158: Init = ParseInitializer();
1: branch 1 taken
157: branch 2 taken
1366 158: if (Init.isInvalid())
1367 1: SkipUntil(tok::comma, true, true);
1368 : }
1369 : }
1370 :
1371 : // If attributes exist after the declarator, parse them.
0: branch 1 not taken
3631: branch 2 taken
1372 3631: if (Tok.is(tok::kw___attribute)) {
1373 0: SourceLocation Loc;
1374 0: AttributeList *AttrList = ParseGNUAttributes(&Loc);
1375 0: DeclaratorInfo.AddAttributes(AttrList, Loc);
1376 : }
1377 :
1378 : // NOTE: If Sema is the Action module and declarator is an instance field,
1379 : // this call will *not* return the created decl; It will return null.
1380 : // See Sema::ActOnCXXMemberDeclarator for details.
1381 :
1382 3631: DeclPtrTy ThisDecl;
38: branch 1 taken
3593: branch 2 taken
1383 3631: if (DS.isFriendSpecified()) {
1384 : // TODO: handle initializers, bitfields, 'delete'
1385 : ThisDecl = Actions.ActOnFriendFunctionDecl(CurScope, DeclaratorInfo,
1386 : /*IsDefinition*/ false,
1387 38: move(TemplateParams));
1388 : } else {
1389 : ThisDecl = Actions.ActOnCXXMemberDeclarator(CurScope, AS,
1390 : DeclaratorInfo,
1391 : move(TemplateParams),
1392 : BitfieldSize.release(),
1393 : Init.release(),
1394 : /*IsDefinition*/Deleted,
1395 3593: Deleted);
1396 : }
2072: branch 1 taken
1559: branch 2 taken
1397 3631: if (ThisDecl)
1398 2072: DeclsInGroup.push_back(ThisDecl);
1399 :
1687: branch 1 taken
1944: branch 2 taken
1685: branch 5 taken
2: branch 6 taken
1685: branch 7 taken
1946: branch 8 taken
1400 3631: if (DeclaratorInfo.isFunctionDeclarator() &&
1401 : DeclaratorInfo.getDeclSpec().getStorageClassSpec()
1402 : != DeclSpec::SCS_typedef) {
1403 1685: HandleMemberFunctionDefaultArgs(DeclaratorInfo, ThisDecl);
1404 : }
1405 :
1406 3631: DeclaratorInfo.complete(ThisDecl);
1407 :
1408 : // If we don't have a comma, it is either the end of the list (a ';')
1409 : // or an error, bail out.
61: branch 1 taken
3570: branch 2 taken
1410 3631: if (Tok.isNot(tok::comma))
1411 3570: break;
1412 :
1413 : // Consume the comma.
1414 61: ConsumeToken();
1415 :
1416 : // Parse the next declarator.
1417 61: DeclaratorInfo.clear();
1418 61: BitfieldSize = 0;
1419 61: Init = 0;
1420 61: Deleted = false;
1421 :
1422 : // Attributes are only allowed on the second declarator.
0: branch 1 not taken
61: branch 2 taken
1423 61: if (Tok.is(tok::kw___attribute)) {
1424 0: SourceLocation Loc;
1425 0: AttributeList *AttrList = ParseGNUAttributes(&Loc);
1426 0: DeclaratorInfo.AddAttributes(AttrList, Loc);
1427 : }
1428 :
59: branch 1 taken
2: branch 2 taken
1429 61: if (Tok.isNot(tok::colon))
1430 59: ParseDeclarator(DeclaratorInfo);
1431 : }
1432 :
2: branch 1 taken
3568: branch 2 taken
1433 3570: if (ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list)) {
1434 : // Skip to end of block or statement.
1435 2: SkipUntil(tok::r_brace, true, true);
1436 : // If we stopped at a ';', eat it.
1: branch 1 taken
1: branch 2 taken
1437 2: if (Tok.is(tok::semi)) ConsumeToken();
1438 : return;
1439 : }
1440 :
1441 : Actions.FinalizeDeclaratorGroup(CurScope, DS, DeclsInGroup.data(),
3568: branch 4 taken
2: branch 5 taken
3568: branch 7 taken
2: branch 8 taken
3568: branch 10 taken
2: branch 11 taken
3568: branch 13 taken
1055: branch 14 taken
3568: branch 16 taken
1363: branch 17 taken
3568: branch 19 taken
1438: branch 20 taken
1442 3568: DeclsInGroup.size());
1443 : }
1444 :
1445 : /// ParseCXXMemberSpecification - Parse the class definition.
1446 : ///
1447 : /// member-specification:
1448 : /// member-declaration member-specification[opt]
1449 : /// access-specifier ':' member-specification[opt]
1450 : ///
1451 : void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
1452 3403: unsigned TagType, DeclPtrTy TagDecl) {
1453 : assert((TagType == DeclSpec::TST_struct ||
1454 : TagType == DeclSpec::TST_union ||
773: branch 0 taken
2630: branch 1 taken
689: branch 2 taken
84: branch 3 taken
0: branch 4 not taken
689: branch 5 taken
1455 3403: TagType == DeclSpec::TST_class) && "Invalid TagType!");
1456 :
1457 : PrettyStackTraceActionsDecl CrashInfo(TagDecl, RecordLoc, Actions,
1458 : PP.getSourceManager(),
1459 3403: "parsing struct/union/class body");
1460 :
1461 : // Determine whether this is a non-nested class. Note that local
1462 : // classes are *not* considered to be nested classes.
1463 3403: bool NonNestedClass = true;
228: branch 1 taken
3175: branch 2 taken
1464 3403: if (!ClassStack.empty()) {
282: branch 1 taken
0: branch 2 not taken
1465 282: for (const Scope *S = CurScope; S; S = S->getParent()) {
220: branch 1 taken
62: branch 2 taken
1466 282: if (S->isClassScope()) {
1467 : // We're inside a class scope, so this is a nested class.
1468 220: NonNestedClass = false;
1469 220: break;
1470 : }
1471 :
8: branch 1 taken
54: branch 2 taken
1472 62: if ((S->getFlags() & Scope::FnScope)) {
1473 : // If we're in a function or function template declared in the
1474 : // body of a class, then this is a local class rather than a
1475 : // nested class.
1476 8: const Scope *Parent = S->getParent();
1: branch 1 taken
7: branch 2 taken
1477 8: if (Parent->isTemplateParamScope())
1478 1: Parent = Parent->getParent();
8: branch 1 taken
0: branch 2 not taken
1479 8: if (Parent->isClassScope())
1480 8: break;
1481 : }
1482 : }
1483 : }
1484 :
1485 : // Enter a scope for the class.
1486 3403: ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope);
1487 :
1488 : // Note that we are parsing a new (potentially-nested) class definition.
1489 3403: ParsingClassDefinition ParsingDef(*this, TagDecl, NonNestedClass);
1490 :
3394: branch 1 taken
9: branch 2 taken
1491 3403: if (TagDecl)
1492 3394: Actions.ActOnTagStartDefinition(CurScope, TagDecl);
1493 :
701: branch 1 taken
2702: branch 2 taken
1494 3403: if (Tok.is(tok::colon)) {
1495 701: ParseBaseClause(TagDecl);
1496 :
0: branch 1 not taken
701: branch 2 taken
1497 701: if (!Tok.is(tok::l_brace)) {
1498 0: Diag(Tok, diag::err_expected_lbrace_after_base_specifiers);
1499 9: return;
1500 : }
1501 : }
1502 :
0: branch 1 not taken
3403: branch 2 taken
1503 3403: assert(Tok.is(tok::l_brace));
1504 :
1505 3403: SourceLocation LBraceLoc = ConsumeBrace();
1506 :
9: branch 1 taken
3394: branch 2 taken
1507 3403: if (!TagDecl) {
1508 9: SkipUntil(tok::r_brace, false, false);
1509 : return;
1510 : }
1511 :
1512 3394: Actions.ActOnStartCXXMemberDeclarations(CurScope, TagDecl, LBraceLoc);
1513 :
1514 : // C++ 11p3: Members of a class defined with the keyword class are private
1515 : // by default. Members of a class defined with the keywords struct or union
1516 : // are public by default.
1517 : AccessSpecifier CurAS;
686: branch 0 taken
2708: branch 1 taken
1518 3394: if (TagType == DeclSpec::TST_class)
1519 686: CurAS = AS_private;
1520 : else
1521 2708: CurAS = AS_public;
1522 :
1523 : // While we still have something to read, read the member-declarations.
5251: branch 1 taken
3393: branch 2 taken
5250: branch 4 taken
1: branch 5 taken
5250: branch 6 taken
3394: branch 7 taken
1524 12038: while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
1525 : // Each iteration of this loop reads one member-declaration.
1526 :
1527 : // Check for extraneous top-level semicolon.
18: branch 1 taken
5232: branch 2 taken
1528 5250: if (Tok.is(tok::semi)) {
1529 : Diag(Tok, diag::ext_extra_struct_semi)
1530 18: << CodeModificationHint::CreateRemoval(Tok.getLocation());
1531 18: ConsumeToken();
1532 18: continue;
1533 : }
1534 :
1535 5232: AccessSpecifier AS = getAccessSpecifierIfPresent();
222: branch 0 taken
5010: branch 1 taken
1536 5232: if (AS != AS_none) {
1537 : // Current token is a C++ access specifier.
1538 222: CurAS = AS;
1539 222: ConsumeToken();
1540 222: ExpectAndConsume(tok::colon, diag::err_expected_colon);
1541 222: continue;
1542 : }
1543 :
1544 : // FIXME: Make sure we don't have a template here.
1545 :
1546 : // Parse all the comma separated declarators.
1547 5010: ParseCXXClassMemberDeclaration(CurAS);
1548 : }
1549 :
1550 3394: SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc);
1551 :
1552 3394: AttributeList *AttrList = 0;
1553 : // If attributes exist after class contents, parse them.
0: branch 1 not taken
3394: branch 2 taken
1554 3394: if (Tok.is(tok::kw___attribute))
1555 0: AttrList = ParseGNUAttributes(); // FIXME: where should I put them?
1556 :
1557 : Actions.ActOnFinishCXXMemberSpecification(CurScope, RecordLoc, TagDecl,
1558 3394: LBraceLoc, RBraceLoc);
1559 :
1560 : // C++ 9.2p2: Within the class member-specification, the class is regarded as
1561 : // complete within function bodies, default arguments,
1562 : // exception-specifications, and constructor ctor-initializers (including
1563 : // such things in nested classes).
1564 : //
1565 : // FIXME: Only function bodies and constructor ctor-initializers are
1566 : // parsed correctly, fix the rest.
3174: branch 0 taken
220: branch 1 taken
1567 3394: if (NonNestedClass) {
1568 : // We are not inside a nested class. This class and its nested classes
1569 : // are complete and we can parse the delayed portions of method
1570 : // declarations and the lexed inline method definitions.
1571 3174: ParseLexedMethodDeclarations(getCurrentClass());
1572 3174: ParseLexedMethodDefs(getCurrentClass());
1573 : }
1574 :
1575 : // Leave the class scope.
1576 3394: ParsingDef.Pop();
1577 3394: ClassScope.Exit();
1578 :
3394: branch 2 taken
9: branch 3 taken
3394: branch 5 taken
9: branch 6 taken
3394: branch 8 taken
9: branch 9 taken
1579 3394: Actions.ActOnTagFinishDefinition(CurScope, TagDecl, RBraceLoc);
1580 : }
1581 :
1582 : /// ParseConstructorInitializer - Parse a C++ constructor initializer,
1583 : /// which explicitly initializes the members or base classes of a
1584 : /// class (C++ [class.base.init]). For example, the three initializers
1585 : /// after the ':' in the Derived constructor below:
1586 : ///
1587 : /// @code
1588 : /// class Base { };
1589 : /// class Derived : Base {
1590 : /// int x;
1591 : /// float f;
1592 : /// public:
1593 : /// Derived(float f) : Base(), x(17), f(f) { }
1594 : /// };
1595 : /// @endcode
1596 : ///
1597 : /// [C++] ctor-initializer:
1598 : /// ':' mem-initializer-list
1599 : ///
1600 : /// [C++] mem-initializer-list:
1601 : /// mem-initializer
1602 : /// mem-initializer , mem-initializer-list
1603 165: void Parser::ParseConstructorInitializer(DeclPtrTy ConstructorDecl) {
165: branch 1 taken
0: branch 2 not taken
1604 165: assert(Tok.is(tok::colon) && "Constructor initializer always starts with ':'");
1605 :
1606 165: SourceLocation ColonLoc = ConsumeToken();
1607 :
1608 165: llvm::SmallVector<MemInitTy*, 4> MemInitializers;
1609 165: bool AnyErrors = false;
1610 :
1611 142: do {
1612 307: MemInitResult MemInit = ParseMemInitializer(ConstructorDecl);
288: branch 1 taken
19: branch 2 taken
1613 307: if (!MemInit.isInvalid())
1614 288: MemInitializers.push_back(MemInit.get());
1615 : else
1616 19: AnyErrors = true;
1617 :
142: branch 1 taken
165: branch 2 taken
1618 307: if (Tok.is(tok::comma))
1619 142: ConsumeToken();
163: branch 1 taken
2: branch 2 taken
1620 165: else if (Tok.is(tok::l_brace))
1621 163: break;
1622 : else {
1623 : // Skip over garbage, until we get to '{'. Don't eat the '{'.
1624 2: Diag(Tok.getLocation(), diag::err_expected_lbrace_or_comma);
1625 2: SkipUntil(tok::l_brace, true, true);
1626 2: break;
1627 : }
1628 : } while (true);
1629 :
1630 : Actions.ActOnMemInitializers(ConstructorDecl, ColonLoc,
1631 : MemInitializers.data(), MemInitializers.size(),
1632 165: AnyErrors);
1633 165: }
1634 :
1635 : /// ParseMemInitializer - Parse a C++ member initializer, which is
1636 : /// part of a constructor initializer that explicitly initializes one
1637 : /// member or base class (C++ [class.base.init]). See
1638 : /// ParseConstructorInitializer for an example.
1639 : ///
1640 : /// [C++] mem-initializer:
1641 : /// mem-initializer-id '(' expression-list[opt] ')'
1642 : ///
1643 : /// [C++] mem-initializer-id:
1644 : /// '::'[opt] nested-name-specifier[opt] class-name
1645 : /// identifier
1646 307: Parser::MemInitResult Parser::ParseMemInitializer(DeclPtrTy ConstructorDecl) {
1647 : // parse '::'[opt] nested-name-specifier[opt]
1648 307: CXXScopeSpec SS;
1649 307: ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
1650 307: TypeTy *TemplateTypeTy = 0;
10: branch 1 taken
297: branch 2 taken
1651 307: if (Tok.is(tok::annot_template_id)) {
1652 : TemplateIdAnnotation *TemplateId
1653 10: = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
2: branch 0 taken
8: branch 1 taken
2: branch 2 taken
0: branch 3 not taken
1654 10: if (TemplateId->Kind == TNK_Type_template ||
1655 : TemplateId->Kind == TNK_Dependent_template_name) {
1656 10: AnnotateTemplateIdTokenAsType(&SS);
10: branch 1 taken
0: branch 2 not taken
1657 10: assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
1658 10: TemplateTypeTy = Tok.getAnnotationValue();
1659 : }
1660 : }
297: branch 0 taken
10: branch 1 taken
0: branch 3 not taken
297: branch 4 taken
0: branch 5 not taken
307: branch 6 taken
1661 307: if (!TemplateTypeTy && Tok.isNot(tok::identifier)) {
1662 0: Diag(Tok, diag::err_expected_member_or_base_name);
1663 0: return true;
1664 : }
1665 :
1666 : // Get the identifier. This may be a member name or a class name,
1667 : // but we'll let the semantic analysis determine which it is.
297: branch 1 taken
10: branch 2 taken
1668 307: IdentifierInfo *II = Tok.is(tok::identifier) ? Tok.getIdentifierInfo() : 0;
1669 307: SourceLocation IdLoc = ConsumeToken();
1670 :
1671 : // Parse the '('.
0: branch 1 not taken
307: branch 2 taken
1672 307: if (Tok.isNot(tok::l_paren)) {
1673 0: Diag(Tok, diag::err_expected_lparen);
1674 0: return true;
1675 : }
1676 307: SourceLocation LParenLoc = ConsumeParen();
1677 :
1678 : // Parse the optional expression-list.
1679 307: ExprVector ArgExprs(Actions);
1680 307: CommaLocsTy CommaLocs;
246: branch 1 taken
61: branch 2 taken
0: branch 4 not taken
246: branch 5 taken
0: branch 6 not taken
307: branch 7 taken
1681 307: if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, CommaLocs)) {
1682 0: SkipUntil(tok::r_paren);
1683 0: return true;
1684 : }
1685 :
1686 307: SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
1687 :
1688 : return Actions.ActOnMemInitializer(ConstructorDecl, CurScope, SS, II,
1689 : TemplateTypeTy, IdLoc,
1690 : LParenLoc, ArgExprs.take(),
1691 : ArgExprs.size(), CommaLocs.data(),
1692 307: RParenLoc);
1693 : }
1694 :
1695 : /// ParseExceptionSpecification - Parse a C++ exception-specification
1696 : /// (C++ [except.spec]).
1697 : ///
1698 : /// exception-specification:
1699 : /// 'throw' '(' type-id-list [opt] ')'
1700 : /// [MS] 'throw' '(' '...' ')'
1701 : ///
1702 : /// type-id-list:
1703 : /// type-id
1704 : /// type-id-list ',' type-id
1705 : ///
1706 : bool Parser::ParseExceptionSpecification(SourceLocation &EndLoc,
1707 : llvm::SmallVector<TypeTy*, 2>
1708 : &Exceptions,
1709 : llvm::SmallVector<SourceRange, 2>
1710 : &Ranges,
1711 328: bool &hasAnyExceptionSpec) {
328: branch 1 taken
0: branch 2 not taken
1712 328: assert(Tok.is(tok::kw_throw) && "expected throw");
1713 :
1714 328: SourceLocation ThrowLoc = ConsumeToken();
1715 :
0: branch 1 not taken
328: branch 2 taken
1716 328: if (!Tok.is(tok::l_paren)) {
1717 0: return Diag(Tok, diag::err_expected_lparen_after) << "throw";
1718 : }
1719 328: SourceLocation LParenLoc = ConsumeParen();
1720 :
1721 : // Parse throw(...), a Microsoft extension that means "this function
1722 : // can throw anything".
5: branch 1 taken
323: branch 2 taken
1723 328: if (Tok.is(tok::ellipsis)) {
1724 5: hasAnyExceptionSpec = true;
1725 5: SourceLocation EllipsisLoc = ConsumeToken();
0: branch 1 not taken
5: branch 2 taken
1726 5: if (!getLang().Microsoft)
1727 0: Diag(EllipsisLoc, diag::ext_ellipsis_exception_spec);
1728 5: EndLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
1729 5: return false;
1730 : }
1731 :
1732 : // Parse the sequence of type-ids.
1733 323: SourceRange Range;
102: branch 1 taken
241: branch 2 taken
1734 666: while (Tok.isNot(tok::r_paren)) {
1735 102: TypeResult Res(ParseTypeName(&Range));
102: branch 1 taken
0: branch 2 not taken
1736 102: if (!Res.isInvalid()) {
1737 102: Exceptions.push_back(Res.get());
1738 102: Ranges.push_back(Range);
1739 : }
82: branch 1 taken
20: branch 2 taken
1740 102: if (Tok.is(tok::comma))
1741 20: ConsumeToken();
1742 : else
1743 82: break;
1744 : }
1745 :
1746 323: EndLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
1747 323: return false;
1748 : }
1749 :
1750 : /// \brief We have just started parsing the definition of a new class,
1751 : /// so push that class onto our stack of classes that is currently
1752 : /// being parsed.
1753 3403: void Parser::PushParsingClass(DeclPtrTy ClassDecl, bool NonNestedClass) {
1754 : assert((NonNestedClass || !ClassStack.empty()) &&
220: branch 0 taken
3183: branch 1 taken
220: branch 3 taken
0: branch 4 not taken
1755 3403: "Nested class without outer class");
1756 3403: ClassStack.push(new ParsingClass(ClassDecl, NonNestedClass));
1757 3403: }
1758 :
1759 : /// \brief Deallocate the given parsed class and all of its nested
1760 : /// classes.
1761 3208: void Parser::DeallocateParsedClasses(Parser::ParsingClass *Class) {
25: branch 1 taken
3208: branch 2 taken
1762 3233: for (unsigned I = 0, N = Class->NestedClasses.size(); I != N; ++I)
1763 25: DeallocateParsedClasses(Class->NestedClasses[I]);
3208: branch 0 taken
0: branch 1 not taken
1764 3208: delete Class;
1765 3208: }
1766 :
1767 : /// \brief Pop the top class of the stack of classes that are
1768 : /// currently being parsed.
1769 : ///
1770 : /// This routine should be called when we have finished parsing the
1771 : /// definition of a class, but have not yet popped the Scope
1772 : /// associated with the class's definition.
1773 : ///
1774 : /// \returns true if the class we've popped is a top-level class,
1775 : /// false otherwise.
1776 3403: void Parser::PopParsingClass() {
3403: branch 1 taken
0: branch 2 not taken
1777 3403: assert(!ClassStack.empty() && "Mismatched push/pop for class parsing");
1778 :
1779 3403: ParsingClass *Victim = ClassStack.top();
1780 3403: ClassStack.pop();
3183: branch 0 taken
220: branch 1 taken
1781 3403: if (Victim->TopLevelClass) {
1782 : // Deallocate all of the nested classes of this class,
1783 : // recursively: we don't need to keep any of this information.
1784 3183: DeallocateParsedClasses(Victim);
1785 3183: return;
1786 : }
220: branch 1 taken
0: branch 2 not taken
1787 220: assert(!ClassStack.empty() && "Missing top-level class?");
1788 :
219: branch 1 taken
1: branch 2 taken
200: branch 4 taken
19: branch 5 taken
195: branch 7 taken
5: branch 8 taken
195: branch 9 taken
25: branch 10 taken
1789 439: if (Victim->MethodDecls.empty() && Victim->MethodDefs.empty() &&
1790 : Victim->NestedClasses.empty()) {
1791 : // The victim is a nested class, but we will not need to perform
1792 : // any processing after the definition of this class since it has
1793 : // no members whose handling was delayed. Therefore, we can just
1794 : // remove this nested class.
195: branch 0 taken
0: branch 1 not taken
1795 195: delete Victim;
1796 195: return;
1797 : }
1798 :
1799 : // This nested class has some members that will need to be processed
1800 : // after the top-level class is completely defined. Therefore, add
1801 : // it to the list of nested classes within its parent.
25: branch 1 taken
0: branch 2 not taken
1802 25: assert(CurScope->isClassScope() && "Nested class outside of class scope?");
1803 25: ClassStack.top()->NestedClasses.push_back(Victim);
1804 25: Victim->TemplateScope = CurScope->getParent()->isTemplateParamScope();
1805 : }
1806 :
1807 : /// ParseCXX0XAttributes - Parse a C++0x attribute-specifier. Currently only
1808 : /// parses standard attributes.
1809 : ///
1810 : /// [C++0x] attribute-specifier:
1811 : /// '[' '[' attribute-list ']' ']'
1812 : ///
1813 : /// [C++0x] attribute-list:
1814 : /// attribute[opt]
1815 : /// attribute-list ',' attribute[opt]
1816 : ///
1817 : /// [C++0x] attribute:
1818 : /// attribute-token attribute-argument-clause[opt]
1819 : ///
1820 : /// [C++0x] attribute-token:
1821 : /// identifier
1822 : /// attribute-scoped-token
1823 : ///
1824 : /// [C++0x] attribute-scoped-token:
1825 : /// attribute-namespace '::' identifier
1826 : ///
1827 : /// [C++0x] attribute-namespace:
1828 : /// identifier
1829 : ///
1830 : /// [C++0x] attribute-argument-clause:
1831 : /// '(' balanced-token-seq ')'
1832 : ///
1833 : /// [C++0x] balanced-token-seq:
1834 : /// balanced-token
1835 : /// balanced-token-seq balanced-token
1836 : ///
1837 : /// [C++0x] balanced-token:
1838 : /// '(' balanced-token-seq ')'
1839 : /// '[' balanced-token-seq ']'
1840 : /// '{' balanced-token-seq '}'
1841 : /// any token but '(', ')', '[', ']', '{', or '}'
1842 51: CXX0XAttributeList Parser::ParseCXX0XAttributes(SourceLocation *EndLoc) {
1843 : assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square)
51: branch 1 taken
0: branch 2 not taken
51: branch 5 taken
0: branch 6 not taken
1844 51: && "Not a C++0x attribute list");
1845 :
1846 51: SourceLocation StartLoc = Tok.getLocation(), Loc;
1847 51: AttributeList *CurrAttr = 0;
1848 :
1849 51: ConsumeBracket();
1850 51: ConsumeBracket();
1851 :
1: branch 1 taken
50: branch 2 taken
1852 51: if (Tok.is(tok::comma)) {
1853 1: Diag(Tok.getLocation(), diag::err_expected_ident);
1854 1: ConsumeToken();
1855 : }
1856 :
54: branch 1 taken
21: branch 2 taken
3: branch 4 taken
51: branch 5 taken
24: branch 6 taken
51: branch 7 taken
1857 126: while (Tok.is(tok::identifier) || Tok.is(tok::comma)) {
1858 : // attribute not present
3: branch 1 taken
21: branch 2 taken
1859 24: if (Tok.is(tok::comma)) {
1860 3: ConsumeToken();
1861 3: continue;
1862 : }
1863 :
1864 21: IdentifierInfo *ScopeName = 0, *AttrName = Tok.getIdentifierInfo();
1865 21: SourceLocation ScopeLoc, AttrLoc = ConsumeToken();
1866 :
1867 : // scoped attribute
2: branch 1 taken
19: branch 2 taken
1868 21: if (Tok.is(tok::coloncolon)) {
1869 2: ConsumeToken();
1870 :
1: branch 1 taken
1: branch 2 taken
1871 2: if (!Tok.is(tok::identifier)) {
1872 1: Diag(Tok.getLocation(), diag::err_expected_ident);
1873 1: SkipUntil(tok::r_square, tok::comma, true, true);
1874 1: continue;
1875 : }
1876 :
1877 1: ScopeName = AttrName;
1878 1: ScopeLoc = AttrLoc;
1879 :
1880 1: AttrName = Tok.getIdentifierInfo();
1881 1: AttrLoc = ConsumeToken();
1882 : }
1883 :
1884 20: bool AttrParsed = false;
1885 : // No scoped names are supported; ideally we could put all non-standard
1886 : // attributes into namespaces.
19: branch 0 taken
1: branch 1 taken
1887 20: if (!ScopeName) {
9: branch 1 taken
10: branch 2 taken
0: branch 3 not taken
1888 19: switch(AttributeList::getKind(AttrName))
1889 : {
1890 : // No arguments
1891 : case AttributeList::AT_base_check:
1892 : case AttributeList::AT_carries_dependency:
1893 : case AttributeList::AT_final:
1894 : case AttributeList::AT_hiding:
1895 : case AttributeList::AT_noreturn:
1896 : case AttributeList::AT_override: {
1: branch 1 taken
8: branch 2 taken
1897 9: if (Tok.is(tok::l_paren)) {
1898 : Diag(Tok.getLocation(), diag::err_cxx0x_attribute_forbids_arguments)
1899 1: << AttrName->getName();
1900 1: break;
1901 : }
1902 :
1903 : CurrAttr = new AttributeList(AttrName, AttrLoc, 0, AttrLoc, 0,
1904 : SourceLocation(), 0, 0, CurrAttr, false,
1905 8: true);
1906 8: AttrParsed = true;
1907 8: break;
1908 : }
1909 :
1910 : // One argument; must be a type-id or assignment-expression
1911 : case AttributeList::AT_aligned: {
1: branch 1 taken
9: branch 2 taken
1912 10: if (Tok.isNot(tok::l_paren)) {
1913 : Diag(Tok.getLocation(), diag::err_cxx0x_attribute_requires_arguments)
1914 1: << AttrName->getName();
1915 1: break;
1916 : }
1917 9: SourceLocation ParamLoc = ConsumeParen();
1918 :
1919 9: OwningExprResult ArgExpr = ParseCXX0XAlignArgument(ParamLoc);
1920 :
1921 9: MatchRHSPunctuation(tok::r_paren, ParamLoc);
1922 :
1923 9: ExprVector ArgExprs(Actions);
1924 9: ArgExprs.push_back(ArgExpr.release());
1925 : CurrAttr = new AttributeList(AttrName, AttrLoc, 0, AttrLoc,
1926 : 0, ParamLoc, ArgExprs.take(), 1, CurrAttr,
1927 9: false, true);
1928 :
1929 9: AttrParsed = true;
1930 9: break;
1931 : }
1932 :
1933 : // Silence warnings
1934 : default: break;
1935 : }
1936 : }
1937 :
1938 : // Skip the entire parameter clause, if any
3: branch 0 taken
17: branch 1 taken
2: branch 3 taken
1: branch 4 taken
2: branch 5 taken
18: branch 6 taken
1939 20: if (!AttrParsed && Tok.is(tok::l_paren)) {
1940 2: ConsumeParen();
1941 : // SkipUntil maintains the balancedness of tokens.
1942 2: SkipUntil(tok::r_paren, false);
1943 : }
1944 : }
1945 :
0: branch 1 not taken
51: branch 2 taken
1946 51: if (ExpectAndConsume(tok::r_square, diag::err_expected_rsquare))
1947 0: SkipUntil(tok::r_square, false);
1948 51: Loc = Tok.getLocation();
0: branch 1 not taken
51: branch 2 taken
1949 51: if (ExpectAndConsume(tok::r_square, diag::err_expected_rsquare))
1950 0: SkipUntil(tok::r_square, false);
1951 :
1952 51: CXX0XAttributeList Attr (CurrAttr, SourceRange(StartLoc, Loc), true);
1953 : return Attr;
1954 : }
1955 :
1956 : /// ParseCXX0XAlignArgument - Parse the argument to C++0x's [[align]]
1957 : /// attribute.
1958 : ///
1959 : /// FIXME: Simply returns an alignof() expression if the argument is a
1960 : /// type. Ideally, the type should be propagated directly into Sema.
1961 : ///
1962 : /// [C++0x] 'align' '(' type-id ')'
1963 : /// [C++0x] 'align' '(' assignment-expression ')'
1964 9: Parser::OwningExprResult Parser::ParseCXX0XAlignArgument(SourceLocation Start) {
1: branch 1 taken
8: branch 2 taken
1965 9: if (isTypeIdInParens()) {
1966 : EnterExpressionEvaluationContext Unevaluated(Actions,
1967 1: Action::Unevaluated);
1968 1: SourceLocation TypeLoc = Tok.getLocation();
1969 1: TypeTy *Ty = ParseTypeName().get();
1970 1: SourceRange TypeRange(Start, Tok.getLocation());
1971 : return Actions.ActOnSizeOfAlignOfExpr(TypeLoc, false, true, Ty,
1972 1: TypeRange);
1973 : } else
1974 8: return ParseConstantExpression();
1975 : }
Generated: 2010-02-10 01:31 by zcov