 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
80.2% |
855 / 1066 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
94.6% |
1008 / 1066 |
| |
|
Line Coverage: |
86.7% |
1068 / 1232 |
| |
 |
|
 |
1 : //===--- ParseDecl.cpp - 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 Declaration portions of the Parser interfaces.
11 : //
12 : //===----------------------------------------------------------------------===//
13 :
14 : #include "clang/Parse/Parser.h"
15 : #include "clang/Parse/ParseDiagnostic.h"
16 : #include "clang/Parse/Scope.h"
17 : #include "clang/Parse/Template.h"
18 : #include "RAIIObjectsForParser.h"
19 : #include "llvm/ADT/SmallSet.h"
20 : using namespace clang;
21 :
22 : //===----------------------------------------------------------------------===//
23 : // C99 6.7: Declarations.
24 : //===----------------------------------------------------------------------===//
25 :
26 : /// ParseTypeName
27 : /// type-name: [C99 6.7.6]
28 : /// specifier-qualifier-list abstract-declarator[opt]
29 : ///
30 : /// Called type-id in C++.
31 13818: Action::TypeResult Parser::ParseTypeName(SourceRange *Range) {
32 : // Parse the common declaration-specifiers piece.
33 13818: DeclSpec DS;
34 13818: ParseSpecifierQualifierList(DS);
35 :
36 : // Parse the abstract-declarator, if present.
37 13818: Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
38 13818: ParseDeclarator(DeclaratorInfo);
102: branch 0 taken
13716: branch 1 taken
39 13818: if (Range)
40 102: *Range = DeclaratorInfo.getSourceRange();
41 :
1: branch 1 taken
13817: branch 2 taken
42 13818: if (DeclaratorInfo.isInvalidType())
43 1: return true;
44 :
45 13817: return Actions.ActOnTypeName(CurScope, DeclaratorInfo);
46 : }
47 :
48 : /// ParseGNUAttributes - Parse a non-empty attributes list.
49 : ///
50 : /// [GNU] attributes:
51 : /// attribute
52 : /// attributes attribute
53 : ///
54 : /// [GNU] attribute:
55 : /// '__attribute__' '(' '(' attribute-list ')' ')'
56 : ///
57 : /// [GNU] attribute-list:
58 : /// attrib
59 : /// attribute_list ',' attrib
60 : ///
61 : /// [GNU] attrib:
62 : /// empty
63 : /// attrib-name
64 : /// attrib-name '(' identifier ')'
65 : /// attrib-name '(' identifier ',' nonempty-expr-list ')'
66 : /// attrib-name '(' argument-expression-list [C99 6.5.2] ')'
67 : ///
68 : /// [GNU] attrib-name:
69 : /// identifier
70 : /// typespec
71 : /// typequal
72 : /// storageclass
73 : ///
74 : /// FIXME: The GCC grammar/code for this construct implies we need two
75 : /// token lookahead. Comment from gcc: "If they start with an identifier
76 : /// which is followed by a comma or close parenthesis, then the arguments
77 : /// start with that identifier; otherwise they are an expression list."
78 : ///
79 : /// At the moment, I am not doing 2 token lookahead. I am also unaware of
80 : /// any attributes that don't work (based on my limited testing). Most
81 : /// attributes are very simple in practice. Until we find a bug, I don't see
82 : /// a pressing need to implement the 2 token lookahead.
83 :
84 3261: AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) {
3261: branch 1 taken
0: branch 2 not taken
85 3261: assert(Tok.is(tok::kw___attribute) && "Not a GNU attribute list!");
86 :
87 3261: AttributeList *CurrAttr = 0;
88 :
3592: branch 1 taken
3261: branch 2 taken
89 10114: while (Tok.is(tok::kw___attribute)) {
90 3592: ConsumeToken();
0: branch 1 not taken
3592: branch 2 taken
91 3592: if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
92 : "attribute")) {
93 0: SkipUntil(tok::r_paren, true); // skip until ) or ;
94 0: return CurrAttr;
95 : }
0: branch 1 not taken
3592: branch 2 taken
96 3592: if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "(")) {
97 0: SkipUntil(tok::r_paren, true); // skip until ) or ;
98 0: return CurrAttr;
99 : }
100 : // Parse the attribute-list. e.g. __attribute__(( weak, alias("__f") ))
4914: branch 1 taken
4802: branch 2 taken
4865: branch 4 taken
49: branch 5 taken
1273: branch 7 taken
3592: branch 8 taken
6124: branch 9 taken
3592: branch 10 taken
101 13308: while (Tok.is(tok::identifier) || isDeclarationSpecifier() ||
102 : Tok.is(tok::comma)) {
103 :
1273: branch 1 taken
4851: branch 2 taken
104 6124: if (Tok.is(tok::comma)) {
105 : // allows for empty/non-empty attributes. ((__vector_size__(16),,,,))
106 1273: ConsumeToken();
107 1273: continue;
108 : }
109 : // we have an identifier or declaration specifier (const, int, etc.)
110 4851: IdentifierInfo *AttrName = Tok.getIdentifierInfo();
111 4851: SourceLocation AttrNameLoc = ConsumeToken();
112 :
113 : // check if we have a "paramterized" attribute
1239: branch 1 taken
3612: branch 2 taken
114 4851: if (Tok.is(tok::l_paren)) {
115 1239: ConsumeParen(); // ignore the left paren loc for now
116 :
400: branch 1 taken
839: branch 2 taken
117 1239: if (Tok.is(tok::identifier)) {
118 400: IdentifierInfo *ParmName = Tok.getIdentifierInfo();
119 400: SourceLocation ParmLoc = ConsumeToken();
120 :
324: branch 1 taken
76: branch 2 taken
121 400: if (Tok.is(tok::r_paren)) {
122 : // __attribute__(( mode(byte) ))
123 324: ConsumeParen(); // ignore the right paren loc for now
124 : CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc,
125 324: ParmName, ParmLoc, 0, 0, CurrAttr);
76: branch 1 taken
0: branch 2 not taken
126 76: } else if (Tok.is(tok::comma)) {
127 76: ConsumeToken();
128 : // __attribute__(( format(printf, 1, 2) ))
129 76: ExprVector ArgExprs(Actions);
130 76: bool ArgExprsOk = true;
131 :
132 : // now parse the non-empty comma separated list of expressions
75: branch 1 taken
76: branch 2 taken
133 151: while (1) {
134 151: OwningExprResult ArgExpr(ParseAssignmentExpression());
0: branch 1 not taken
151: branch 2 taken
135 151: if (ArgExpr.isInvalid()) {
136 0: ArgExprsOk = false;
137 0: SkipUntil(tok::r_paren);
138 : break;
139 : } else {
140 151: ArgExprs.push_back(ArgExpr.release());
141 : }
76: branch 1 taken
75: branch 2 taken
142 151: if (Tok.isNot(tok::comma))
143 : break;
144 75: ConsumeToken(); // Eat the comma, move to the next argument
145 : }
76: branch 0 taken
0: branch 1 not taken
76: branch 3 taken
0: branch 4 not taken
76: branch 5 taken
0: branch 6 not taken
146 76: if (ArgExprsOk && Tok.is(tok::r_paren)) {
147 76: ConsumeParen(); // ignore the right paren loc for now
148 : CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0,
149 : AttrNameLoc, ParmName, ParmLoc,
150 : ArgExprs.take(), ArgExprs.size(),
151 76: CurrAttr);
152 76: }
153 : }
154 : } else { // not an identifier
4: branch 1 taken
0: branch 2 not taken
835: branch 3 taken
155 839: switch (Tok.getKind()) {
156 : case tok::r_paren:
157 : // parse a possibly empty comma separated list of expressions
158 : // __attribute__(( nonnull() ))
159 4: ConsumeParen(); // ignore the right paren loc for now
160 : CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc,
161 4: 0, SourceLocation(), 0, 0, CurrAttr);
162 4: break;
163 : case tok::kw_char:
164 : case tok::kw_wchar_t:
165 : case tok::kw_char16_t:
166 : case tok::kw_char32_t:
167 : case tok::kw_bool:
168 : case tok::kw_short:
169 : case tok::kw_int:
170 : case tok::kw_long:
171 : case tok::kw_signed:
172 : case tok::kw_unsigned:
173 : case tok::kw_float:
174 : case tok::kw_double:
175 : case tok::kw_void:
176 : case tok::kw_typeof:
177 : // If it's a builtin type name, eat it and expect a rparen
178 : // __attribute__(( vec_type_hint(char) ))
179 0: ConsumeToken();
180 : CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc,
181 0: 0, SourceLocation(), 0, 0, CurrAttr);
0: branch 1 not taken
0: branch 2 not taken
182 0: if (Tok.is(tok::r_paren))
183 0: ConsumeParen();
184 0: break;
185 : default:
186 : // __attribute__(( aligned(16) ))
187 835: ExprVector ArgExprs(Actions);
188 835: bool ArgExprsOk = true;
189 :
190 : // now parse the list of expressions
202: branch 1 taken
835: branch 2 taken
191 1037: while (1) {
192 1037: OwningExprResult ArgExpr(ParseAssignmentExpression());
0: branch 1 not taken
1037: branch 2 taken
193 1037: if (ArgExpr.isInvalid()) {
194 0: ArgExprsOk = false;
195 0: SkipUntil(tok::r_paren);
196 : break;
197 : } else {
198 1037: ArgExprs.push_back(ArgExpr.release());
199 : }
835: branch 1 taken
202: branch 2 taken
200 1037: if (Tok.isNot(tok::comma))
201 : break;
202 202: ConsumeToken(); // Eat the comma, move to the next argument
203 : }
204 : // Match the ')'.
835: branch 0 taken
0: branch 1 not taken
835: branch 3 taken
0: branch 4 not taken
835: branch 5 taken
0: branch 6 not taken
205 835: if (ArgExprsOk && Tok.is(tok::r_paren)) {
206 835: ConsumeParen(); // ignore the right paren loc for now
207 : CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0,
208 : AttrNameLoc, 0, SourceLocation(), ArgExprs.take(),
209 : ArgExprs.size(),
210 835: CurrAttr);
211 : }
212 835: break;
213 : }
214 : }
215 : } else {
216 : CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc,
217 3612: 0, SourceLocation(), 0, 0, CurrAttr);
218 : }
219 : }
0: branch 1 not taken
3592: branch 2 taken
220 3592: if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
221 0: SkipUntil(tok::r_paren, false);
222 3592: SourceLocation Loc = Tok.getLocation();
0: branch 1 not taken
3592: branch 2 taken
223 3592: if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) {
224 0: SkipUntil(tok::r_paren, false);
225 : }
1678: branch 0 taken
1914: branch 1 taken
226 3592: if (EndLoc)
227 1678: *EndLoc = Loc;
228 : }
229 3261: return CurrAttr;
230 : }
231 :
232 : /// ParseMicrosoftDeclSpec - Parse an __declspec construct
233 : ///
234 : /// [MS] decl-specifier:
235 : /// __declspec ( extended-decl-modifier-seq )
236 : ///
237 : /// [MS] extended-decl-modifier-seq:
238 : /// extended-decl-modifier[opt]
239 : /// extended-decl-modifier extended-decl-modifier-seq
240 :
241 11: AttributeList* Parser::ParseMicrosoftDeclSpec(AttributeList *CurrAttr) {
11: branch 1 taken
0: branch 2 not taken
242 11: assert(Tok.is(tok::kw___declspec) && "Not a declspec!");
243 :
244 11: ConsumeToken();
0: branch 1 not taken
11: branch 2 taken
245 11: if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
246 : "declspec")) {
247 0: SkipUntil(tok::r_paren, true); // skip until ) or ;
248 0: return CurrAttr;
249 : }
11: branch 1 taken
11: branch 2 taken
250 33: while (Tok.getIdentifierInfo()) {
251 11: IdentifierInfo *AttrName = Tok.getIdentifierInfo();
252 11: SourceLocation AttrNameLoc = ConsumeToken();
1: branch 1 taken
10: branch 2 taken
253 11: if (Tok.is(tok::l_paren)) {
254 1: ConsumeParen();
255 : // FIXME: This doesn't parse __declspec(property(get=get_func_name))
256 : // correctly.
257 1: OwningExprResult ArgExpr(ParseAssignmentExpression());
1: branch 1 taken
0: branch 2 not taken
258 1: if (!ArgExpr.isInvalid()) {
259 1: ExprTy* ExprList = ArgExpr.take();
260 : CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
261 : SourceLocation(), &ExprList, 1,
262 1: CurrAttr, true);
263 : }
0: branch 1 not taken
1: branch 2 taken
264 1: if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
265 0: SkipUntil(tok::r_paren, false);
266 : } else {
267 : CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc,
268 10: 0, SourceLocation(), 0, 0, CurrAttr, true);
269 : }
270 : }
0: branch 1 not taken
11: branch 2 taken
271 11: if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen))
272 0: SkipUntil(tok::r_paren, false);
273 11: return CurrAttr;
274 : }
275 :
276 11: AttributeList* Parser::ParseMicrosoftTypeAttributes(AttributeList *CurrAttr) {
277 : // Treat these like attributes
278 : // FIXME: Allow Sema to distinguish between these and real attributes!
22: branch 1 taken
1: branch 2 taken
17: branch 4 taken
5: branch 5 taken
14: branch 7 taken
3: branch 8 taken
12: branch 10 taken
2: branch 11 taken
1: branch 13 taken
11: branch 14 taken
12: branch 15 taken
11: branch 16 taken
279 34: while (Tok.is(tok::kw___fastcall) || Tok.is(tok::kw___stdcall) ||
280 : Tok.is(tok::kw___cdecl) || Tok.is(tok::kw___ptr64) ||
281 : Tok.is(tok::kw___w64)) {
282 12: IdentifierInfo *AttrName = Tok.getIdentifierInfo();
283 12: SourceLocation AttrNameLoc = ConsumeToken();
12: branch 1 taken
0: branch 2 not taken
0: branch 4 not taken
12: branch 5 taken
0: branch 6 not taken
12: branch 7 taken
284 12: if (Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64))
285 : // FIXME: Support these properly!
286 0: continue;
287 : CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
288 12: SourceLocation(), 0, 0, CurrAttr, true);
289 : }
290 11: return CurrAttr;
291 : }
292 :
293 : /// ParseDeclaration - Parse a full 'declaration', which consists of
294 : /// declaration-specifiers, some number of declarators, and a semicolon.
295 : /// 'Context' should be a Declarator::TheContext value. This returns the
296 : /// location of the semicolon in DeclEnd.
297 : ///
298 : /// declaration: [C99 6.7]
299 : /// block-declaration ->
300 : /// simple-declaration
301 : /// others [FIXME]
302 : /// [C++] template-declaration
303 : /// [C++] namespace-definition
304 : /// [C++] using-directive
305 : /// [C++] using-declaration
306 : /// [C++0x] static_assert-declaration
307 : /// others... [FIXME]
308 : ///
309 : Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context,
310 : SourceLocation &DeclEnd,
311 15888: CXX0XAttributeList Attr) {
312 15888: DeclPtrTy SingleDecl;
1990: branch 1 taken
694: branch 2 taken
150: branch 3 taken
58: branch 4 taken
12996: branch 5 taken
313 15888: switch (Tok.getKind()) {
314 : case tok::kw_template:
315 : case tok::kw_export:
1: branch 0 taken
1989: branch 1 taken
316 1990: if (Attr.HasAttr)
317 : Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
318 1: << Attr.Range;
319 1990: SingleDecl = ParseDeclarationStartingWithTemplate(Context, DeclEnd);
320 1990: break;
321 : case tok::kw_namespace:
1: branch 0 taken
693: branch 1 taken
322 694: if (Attr.HasAttr)
323 : Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
324 1: << Attr.Range;
325 694: SingleDecl = ParseNamespace(Context, DeclEnd);
326 694: break;
327 : case tok::kw_using:
328 150: SingleDecl = ParseUsingDirectiveOrDeclaration(Context, DeclEnd, Attr);
329 150: break;
330 : case tok::kw_static_assert:
1: branch 0 taken
57: branch 1 taken
331 58: if (Attr.HasAttr)
332 : Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
333 1: << Attr.Range;
334 58: SingleDecl = ParseStaticAssertDeclaration(DeclEnd);
335 58: break;
336 : default:
337 12996: return ParseSimpleDeclaration(Context, DeclEnd, Attr.AttrList);
338 : }
339 :
340 : // This routine returns a DeclGroup, if the thing we parsed only contains a
341 : // single decl, convert it now.
342 2892: return Actions.ConvertDeclToDeclGroup(SingleDecl);
343 : }
344 :
345 : /// simple-declaration: [C99 6.7: declaration] [C++ 7p1: dcl.dcl]
346 : /// declaration-specifiers init-declarator-list[opt] ';'
347 : ///[C90/C++]init-declarator-list ';' [TODO]
348 : /// [OMP] threadprivate-directive [TODO]
349 : ///
350 : /// If RequireSemi is false, this does not check for a ';' at the end of the
351 : /// declaration.
352 : Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context,
353 : SourceLocation &DeclEnd,
354 13127: AttributeList *Attr) {
355 : // Parse the common declaration-specifiers piece.
356 13127: ParsingDeclSpec DS(*this);
0: branch 0 not taken
13127: branch 1 taken
357 13127: if (Attr)
358 0: DS.AddAttributes(Attr);
359 : ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none,
360 13127: getDeclSpecContextFromDeclaratorContext(Context));
361 :
362 : // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
363 : // declaration-specifiers init-declarator-list[opt] ';'
92: branch 1 taken
13035: branch 2 taken
364 13127: if (Tok.is(tok::semi)) {
365 92: ConsumeToken();
366 92: DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
367 92: DS.complete(TheDecl);
368 92: return Actions.ConvertDeclToDeclGroup(TheDecl);
369 : }
370 :
371 : DeclGroupPtrTy DG = ParseDeclGroup(DS, Context, /*FunctionDefs=*/ false,
372 13035: &DeclEnd);
373 13035: return DG;
374 : }
375 :
376 : /// ParseDeclGroup - Having concluded that this is either a function
377 : /// definition or a group of object declarations, actually parse the
378 : /// result.
379 : Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
380 : unsigned Context,
381 : bool AllowFunctionDefinitions,
382 26190: SourceLocation *DeclEnd) {
383 : // Parse the first declarator.
384 26190: ParsingDeclarator D(*this, DS, static_cast<Declarator::TheContext>(Context));
385 26190: ParseDeclarator(D);
386 :
387 : // Bail out if the first declarator didn't seem well-formed.
25: branch 1 taken
26165: branch 2 taken
25: branch 4 taken
0: branch 5 not taken
25: branch 6 taken
26165: branch 7 taken
388 26190: if (!D.hasName() && !D.mayOmitIdentifier()) {
389 : // Skip until ; or }.
390 25: SkipUntil(tok::r_brace, true, true);
18: branch 1 taken
7: branch 2 taken
391 25: if (Tok.is(tok::semi))
392 18: ConsumeToken();
393 25: return DeclGroupPtrTy();
394 : }
395 :
13136: branch 0 taken
13029: branch 1 taken
10033: branch 3 taken
3103: branch 4 taken
10033: branch 5 taken
16132: branch 6 taken
396 26165: if (AllowFunctionDefinitions && D.isFunctionDeclarator()) {
6915: branch 1 taken
3118: branch 2 taken
397 10033: if (isDeclarationAfterDeclarator()) {
398 : // Fall though. We have to check this first, though, because
399 : // __attribute__ might be the start of a function definition in
400 : // (extended) K&R C.
6913: branch 1 taken
2: branch 2 taken
401 6915: } else if (isStartOfFunctionDefinition()) {
1: branch 1 taken
6912: branch 2 taken
402 6913: if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
403 1: Diag(Tok, diag::err_function_declared_typedef);
404 :
405 : // Recover by treating the 'typedef' as spurious.
406 1: DS.ClearStorageClassSpecs();
407 : }
408 :
409 6913: DeclPtrTy TheDecl = ParseFunctionDefinition(D);
410 6913: return Actions.ConvertDeclToDeclGroup(TheDecl);
411 : } else {
412 2: Diag(Tok, diag::err_expected_fn_body);
413 2: SkipUntil(tok::semi);
414 2: return DeclGroupPtrTy();
415 : }
416 : }
417 :
418 19250: llvm::SmallVector<DeclPtrTy, 8> DeclsInGroup;
419 19250: DeclPtrTy FirstDecl = ParseDeclarationAfterDeclarator(D);
420 19250: D.complete(FirstDecl);
18982: branch 1 taken
268: branch 2 taken
421 19250: if (FirstDecl.get())
422 18982: DeclsInGroup.push_back(FirstDecl);
423 :
424 : // If we don't have a comma, it is either the end of the list (a ';') or an
425 : // error, bail out.
368: branch 1 taken
19250: branch 2 taken
426 38868: while (Tok.is(tok::comma)) {
427 : // Consume the comma.
428 368: ConsumeToken();
429 :
430 : // Parse the next declarator.
431 368: D.clear();
432 :
433 : // Accept attributes in an init-declarator. In the first declarator in a
434 : // declaration, these would be part of the declspec. In subsequent
435 : // declarators, they become part of the declarator itself, so that they
436 : // don't apply to declarators after *this* one. Examples:
437 : // short __attribute__((common)) var; -> declspec
438 : // short var __attribute__((common)); -> declarator
439 : // short x, __attribute__((common)) var; -> declarator
2: branch 1 taken
366: branch 2 taken
440 368: if (Tok.is(tok::kw___attribute)) {
441 2: SourceLocation Loc;
442 2: AttributeList *AttrList = ParseGNUAttributes(&Loc);
443 2: D.AddAttributes(AttrList, Loc);
444 : }
445 :
446 368: ParseDeclarator(D);
447 :
448 368: DeclPtrTy ThisDecl = ParseDeclarationAfterDeclarator(D);
449 368: D.complete(ThisDecl);
346: branch 1 taken
22: branch 2 taken
450 368: if (ThisDecl.get())
451 346: DeclsInGroup.push_back(ThisDecl);
452 : }
453 :
13029: branch 0 taken
6221: branch 1 taken
454 19250: if (DeclEnd)
455 13029: *DeclEnd = Tok.getLocation();
456 :
19119: branch 0 taken
131: branch 1 taken
12160: branch 2 taken
6959: branch 3 taken
6: branch 5 taken
19113: branch 6 taken
6: branch 7 taken
19244: branch 8 taken
457 19250: if (Context != Declarator::ForContext &&
458 : ExpectAndConsume(tok::semi,
459 : Context == Declarator::FileContext
460 : ? diag::err_invalid_token_after_toplevel_declarator
461 : : diag::err_expected_semi_declaration)) {
462 6: SkipUntil(tok::r_brace, true, true);
2: branch 1 taken
4: branch 2 taken
463 6: if (Tok.is(tok::semi))
464 2: ConsumeToken();
465 : }
466 :
467 : return Actions.FinalizeDeclaratorGroup(CurScope, DS,
468 : DeclsInGroup.data(),
469 19250: DeclsInGroup.size());
470 : }
471 :
472 : /// \brief Parse 'declaration' after parsing 'declaration-specifiers
473 : /// declarator'. This method parses the remainder of the declaration
474 : /// (including any attributes or initializer, among other things) and
475 : /// finalizes the declaration.
476 : ///
477 : /// init-declarator: [C99 6.7]
478 : /// declarator
479 : /// declarator '=' initializer
480 : /// [GNU] declarator simple-asm-expr[opt] attributes[opt]
481 : /// [GNU] declarator simple-asm-expr[opt] attributes[opt] '=' initializer
482 : /// [C++] declarator initializer[opt]
483 : ///
484 : /// [C++] initializer:
485 : /// [C++] '=' initializer-clause
486 : /// [C++] '(' expression-list ')'
487 : /// [C++0x] '=' 'default' [TODO]
488 : /// [C++0x] '=' 'delete'
489 : ///
490 : /// According to the standard grammar, =default and =delete are function
491 : /// definitions, but that definitely doesn't fit with the parser here.
492 : ///
493 : Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D,
494 19966: const ParsedTemplateInfo &TemplateInfo) {
495 : // If a simple-asm-expr is present, parse it.
29: branch 1 taken
19937: branch 2 taken
496 19966: if (Tok.is(tok::kw_asm)) {
497 29: SourceLocation Loc;
498 29: OwningExprResult AsmLabel(ParseSimpleAsm(&Loc));
0: branch 1 not taken
29: branch 2 taken
499 29: if (AsmLabel.isInvalid()) {
500 0: SkipUntil(tok::semi, true, true);
501 0: return DeclPtrTy();
502 : }
503 :
504 29: D.setAsmLabel(AsmLabel.release());
29: branch 2 taken
0: branch 3 not taken
505 29: D.SetRangeEnd(Loc);
506 : }
507 :
508 : // If attributes are present, parse them.
1306: branch 1 taken
18660: branch 2 taken
509 19966: if (Tok.is(tok::kw___attribute)) {
510 1306: SourceLocation Loc;
511 1306: AttributeList *AttrList = ParseGNUAttributes(&Loc);
512 1306: D.AddAttributes(AttrList, Loc);
513 : }
514 :
515 : // Inform the current actions module that we just parsed this declarator.
516 19966: DeclPtrTy ThisDecl;
19618: branch 0 taken
225: branch 1 taken
123: branch 2 taken
0: branch 3 not taken
517 19966: switch (TemplateInfo.Kind) {
518 : case ParsedTemplateInfo::NonTemplate:
519 19618: ThisDecl = Actions.ActOnDeclarator(CurScope, D);
520 19618: break;
521 :
522 : case ParsedTemplateInfo::Template:
523 : case ParsedTemplateInfo::ExplicitSpecialization:
524 : ThisDecl = Actions.ActOnTemplateDeclarator(CurScope,
525 : Action::MultiTemplateParamsArg(Actions,
526 : TemplateInfo.TemplateParams->data(),
527 : TemplateInfo.TemplateParams->size()),
528 225: D);
529 225: break;
530 :
531 : case ParsedTemplateInfo::ExplicitInstantiation: {
532 : Action::DeclResult ThisRes
533 : = Actions.ActOnExplicitInstantiation(CurScope,
534 : TemplateInfo.ExternLoc,
535 : TemplateInfo.TemplateLoc,
536 123: D);
15: branch 1 taken
108: branch 2 taken
537 123: if (ThisRes.isInvalid()) {
538 15: SkipUntil(tok::semi, true, true);
539 15: return DeclPtrTy();
540 : }
541 :
542 108: ThisDecl = ThisRes.get();
543 : break;
544 : }
545 : }
546 :
547 : // Parse declarator '=' initializer.
5377: branch 1 taken
14574: branch 2 taken
548 19951: if (Tok.is(tok::equal)) {
549 5377: ConsumeToken();
181: branch 1 taken
5196: branch 2 taken
5: branch 4 taken
176: branch 5 taken
5: branch 6 taken
5372: branch 7 taken
550 5377: if (getLang().CPlusPlus0x && Tok.is(tok::kw_delete)) {
551 5: SourceLocation DelLoc = ConsumeToken();
552 5: Actions.SetDeclDeleted(ThisDecl, DelLoc);
553 : } else {
1548: branch 1 taken
3824: branch 2 taken
38: branch 5 taken
1510: branch 6 taken
38: branch 7 taken
5334: branch 8 taken
554 5372: if (getLang().CPlusPlus && D.getCXXScopeSpec().isSet()) {
555 38: EnterScope(0);
556 38: Actions.ActOnCXXEnterDeclInitializer(CurScope, ThisDecl);
557 : }
558 :
559 5372: OwningExprResult Init(ParseInitializer());
560 :
1548: branch 1 taken
3824: branch 2 taken
38: branch 5 taken
1510: branch 6 taken
38: branch 7 taken
5334: branch 8 taken
561 5372: if (getLang().CPlusPlus && D.getCXXScopeSpec().isSet()) {
562 38: Actions.ActOnCXXExitDeclInitializer(CurScope, ThisDecl);
563 38: ExitScope();
564 : }
565 :
92: branch 1 taken
5280: branch 2 taken
566 5372: if (Init.isInvalid()) {
567 92: SkipUntil(tok::semi, true, true);
568 184: return DeclPtrTy();
569 : }
5280: branch 7 taken
92: branch 8 taken
570 5280: Actions.AddInitializerToDecl(ThisDecl, move(Init));
571 : }
109: branch 1 taken
14465: branch 2 taken
572 14574: } else if (Tok.is(tok::l_paren)) {
573 : // Parse C++ direct initializer: '(' expression-list ')'
574 109: SourceLocation LParenLoc = ConsumeParen();
575 109: ExprVector Exprs(Actions);
576 109: CommaLocsTy CommaLocs;
577 :
109: branch 1 taken
0: branch 2 not taken
1: branch 5 taken
108: branch 6 taken
1: branch 7 taken
108: branch 8 taken
578 109: if (getLang().CPlusPlus && D.getCXXScopeSpec().isSet()) {
579 1: EnterScope(0);
580 1: Actions.ActOnCXXEnterDeclInitializer(CurScope, ThisDecl);
581 : }
582 :
2: branch 1 taken
107: branch 2 taken
583 109: if (ParseExpressionList(Exprs, CommaLocs)) {
584 2: SkipUntil(tok::r_paren);
585 :
2: branch 1 taken
0: branch 2 not taken
0: branch 5 not taken
2: branch 6 taken
0: branch 7 not taken
2: branch 8 taken
586 2: if (getLang().CPlusPlus && D.getCXXScopeSpec().isSet()) {
587 0: Actions.ActOnCXXExitDeclInitializer(CurScope, ThisDecl);
588 0: ExitScope();
589 : }
590 : } else {
591 : // Match the ')'.
592 107: SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
593 :
594 : assert(!Exprs.empty() && Exprs.size()-1 == CommaLocs.size() &&
107: branch 1 taken
0: branch 2 not taken
107: branch 5 taken
0: branch 6 not taken
595 107: "Unexpected number of commas!");
596 :
107: branch 1 taken
0: branch 2 not taken
1: branch 5 taken
106: branch 6 taken
1: branch 7 taken
106: branch 8 taken
597 214: if (getLang().CPlusPlus && D.getCXXScopeSpec().isSet()) {
598 1: Actions.ActOnCXXExitDeclInitializer(CurScope, ThisDecl);
599 1: ExitScope();
600 : }
601 :
602 : Actions.AddCXXDirectInitializerToDecl(ThisDecl, LParenLoc,
603 : move_arg(Exprs),
604 107: CommaLocs.data(), RParenLoc);
605 109: }
606 : } else {
607 : bool TypeContainsUndeducedAuto =
608 14465: D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto;
609 14465: Actions.ActOnUninitializedDecl(ThisDecl, TypeContainsUndeducedAuto);
610 : }
611 :
612 19859: return ThisDecl;
613 : }
614 :
615 : /// ParseSpecifierQualifierList
616 : /// specifier-qualifier-list:
617 : /// type-specifier specifier-qualifier-list[opt]
618 : /// type-qualifier specifier-qualifier-list[opt]
619 : /// [GNU] attributes specifier-qualifier-list[opt]
620 : ///
621 17492: void Parser::ParseSpecifierQualifierList(DeclSpec &DS) {
622 : /// specifier-qualifier-list is a subset of declaration-specifiers. Just
623 : /// parse declaration-specifiers and complain about extra stuff.
624 17492: ParseDeclarationSpecifiers(DS);
625 :
626 : // Validate declspec for type-name.
627 17492: unsigned Specs = DS.getParsedSpecifiers();
19: branch 0 taken
17473: branch 1 taken
17: branch 3 taken
2: branch 4 taken
10: branch 6 taken
7: branch 7 taken
10: branch 8 taken
17482: branch 9 taken
628 17492: if (Specs == DeclSpec::PQ_None && !DS.getNumProtocolQualifiers() &&
629 : !DS.getAttributes())
630 10: Diag(Tok, diag::err_typename_requires_specqual);
631 :
632 : // Issue diagnostic and remove storage class if present.
1: branch 0 taken
17491: branch 1 taken
633 17492: if (Specs & DeclSpec::PQ_StorageClassSpecifier) {
0: branch 2 not taken
1: branch 3 taken
634 1: if (DS.getStorageClassSpecLoc().isValid())
635 0: Diag(DS.getStorageClassSpecLoc(),diag::err_typename_invalid_storageclass);
636 : else
637 1: Diag(DS.getThreadSpecLoc(), diag::err_typename_invalid_storageclass);
638 1: DS.ClearStorageClassSpecs();
639 : }
640 :
641 : // Issue diagnostic and remove function specfier if present.
0: branch 0 not taken
17492: branch 1 taken
642 17492: if (Specs & DeclSpec::PQ_FunctionSpecifier) {
0: branch 1 not taken
0: branch 2 not taken
643 0: if (DS.isInlineSpecified())
644 0: Diag(DS.getInlineSpecLoc(), diag::err_typename_invalid_functionspec);
0: branch 1 not taken
0: branch 2 not taken
645 0: if (DS.isVirtualSpecified())
646 0: Diag(DS.getVirtualSpecLoc(), diag::err_typename_invalid_functionspec);
0: branch 1 not taken
0: branch 2 not taken
647 0: if (DS.isExplicitSpecified())
648 0: Diag(DS.getExplicitSpecLoc(), diag::err_typename_invalid_functionspec);
649 0: DS.ClearFunctionSpecs();
650 : }
651 17492: }
652 :
653 : /// isValidAfterIdentifierInDeclaratorAfterDeclSpec - Return true if the
654 : /// specified token is valid after the identifier in a declarator which
655 : /// immediately follows the declspec. For example, these things are valid:
656 : ///
657 : /// int x [ 4]; // direct-declarator
658 : /// int x ( int y); // direct-declarator
659 : /// int(int x ) // direct-declarator
660 : /// int x ; // simple-declaration
661 : /// int x = 17; // init-declarator-list
662 : /// int x , y; // init-declarator-list
663 : /// int x __asm__ ("foo"); // init-declarator-list
664 : /// int x : 4; // struct-declarator
665 : /// int x { 5}; // C++'0x unified initializers
666 : ///
667 : /// This is not, because 'x' does not immediately follow the declspec (though
668 : /// ')' happens to be valid anyway).
669 : /// int (x)
670 : ///
671 62: static bool isValidAfterIdentifierInDeclarator(const Token &T) {
672 : return T.is(tok::l_square) || T.is(tok::l_paren) || T.is(tok::r_paren) ||
673 : T.is(tok::semi) || T.is(tok::comma) || T.is(tok::equal) ||
62: branch 1 taken
0: branch 2 not taken
55: branch 4 taken
7: branch 5 taken
50: branch 7 taken
5: branch 8 taken
39: branch 10 taken
11: branch 11 taken
37: branch 13 taken
2: branch 14 taken
35: branch 16 taken
2: branch 17 taken
34: branch 19 taken
1: branch 20 taken
34: branch 22 taken
0: branch 23 not taken
1: branch 25 taken
33: branch 26 taken
674 62: T.is(tok::kw_asm) || T.is(tok::l_brace) || T.is(tok::colon);
675 : }
676 :
677 :
678 : /// ParseImplicitInt - This method is called when we have an non-typename
679 : /// identifier in a declspec (which normally terminates the decl spec) when
680 : /// the declspec has no type specifier. In this case, the declspec is either
681 : /// malformed or is "implicit int" (in K&R and C89).
682 : ///
683 : /// This method handles diagnosing this prettily and returns false if the
684 : /// declspec is done being processed. If it recovers and thinks there may be
685 : /// other pieces of declspec after it, it returns true.
686 : ///
687 : bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
688 : const ParsedTemplateInfo &TemplateInfo,
689 62: AccessSpecifier AS) {
62: branch 1 taken
0: branch 2 not taken
690 62: assert(Tok.is(tok::identifier) && "should have identifier");
691 :
692 62: SourceLocation Loc = Tok.getLocation();
693 : // If we see an identifier that is not a type name, we normally would
694 : // parse it as the identifer being declared. However, when a typename
695 : // is typo'd or the definition is not included, this will incorrectly
696 : // parse the typename as the identifier name and fall over misparsing
697 : // later parts of the diagnostic.
698 : //
699 : // As such, we try to do some look-ahead in cases where this would
700 : // otherwise be an "implicit-int" case to see if this is invalid. For
701 : // example: "static foo_t x = 4;" In this case, if we parsed foo_t as
702 : // an identifier with implicit int, we'd get a parse error because the
703 : // next token is obviously invalid for a type. Parse these as a case
704 : // with an invalid type specifier.
62: branch 1 taken
0: branch 2 not taken
705 62: assert(!DS.hasTypeSpecifier() && "Type specifier checked above");
706 :
707 : // Since we know that this either implicit int (which is rare) or an
708 : // error, we'd do lookahead to try to do better recovery.
29: branch 2 taken
33: branch 3 taken
709 62: if (isValidAfterIdentifierInDeclarator(NextToken())) {
710 : // If this token is valid for implicit int, e.g. "static x = 4", then
711 : // we just avoid eating the identifier, so it will be parsed as the
712 : // identifier in the declarator.
713 29: return false;
714 : }
715 :
716 : // Otherwise, if we don't consume this token, we are going to emit an
717 : // error anyway. Try to recover from various common problems. Check
718 : // to see if this was a reference to a tag name without a tag specified.
719 : // This is a common problem in C (saying 'foo' instead of 'struct foo').
720 : //
721 : // C++ doesn't need this, and isTagName doesn't take SS.
17: branch 0 taken
16: branch 1 taken
722 33: if (SS == 0) {
723 17: const char *TagName = 0;
724 17: tok::TokenKind TagKind = tok::unknown;
725 :
15: branch 2 taken
1: branch 3 taken
0: branch 4 not taken
1: branch 5 taken
0: branch 6 not taken
726 17: switch (Actions.isTagName(*Tok.getIdentifierInfo(), CurScope)) {
727 15: default: break;
728 1: case DeclSpec::TST_enum: TagName="enum" ;TagKind=tok::kw_enum ;break;
729 0: case DeclSpec::TST_union: TagName="union" ;TagKind=tok::kw_union ;break;
730 1: case DeclSpec::TST_struct:TagName="struct";TagKind=tok::kw_struct;break;
731 0: case DeclSpec::TST_class: TagName="class" ;TagKind=tok::kw_class ;break;
732 : }
733 :
2: branch 0 taken
15: branch 1 taken
734 17: if (TagName) {
735 : Diag(Loc, diag::err_use_of_tag_name_without_tag)
736 : << Tok.getIdentifierInfo() << TagName
737 2: << CodeModificationHint::CreateInsertion(Tok.getLocation(),TagName);
738 :
739 : // Parse this as a tag as if the missing tag were present.
1: branch 0 taken
1: branch 1 taken
740 2: if (TagKind == tok::kw_enum)
741 1: ParseEnumSpecifier(Loc, DS, AS);
742 : else
743 1: ParseClassSpecifier(TagKind, Loc, DS, TemplateInfo, AS);
744 2: return true;
745 : }
746 : }
747 :
748 : // This is almost certainly an invalid type name. Let the action emit a
749 : // diagnostic and attempt to recover.
750 31: Action::TypeTy *T = 0;
31: branch 2 taken
0: branch 3 not taken
751 31: if (Actions.DiagnoseUnknownTypeName(*Tok.getIdentifierInfo(), Loc,
752 : CurScope, SS, T)) {
753 : // The action emitted a diagnostic, so we don't have to.
6: branch 0 taken
25: branch 1 taken
754 31: if (T) {
755 : // The action has suggested that the type T could be used. Set that as
756 : // the type in the declaration specifiers, consume the would-be type
757 : // name token, and we're done.
758 : const char *PrevSpec;
759 : unsigned DiagID;
760 : DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, T,
761 6: false);
762 6: DS.SetRangeEnd(Tok.getLocation());
763 6: ConsumeToken();
764 :
765 : // There may be other declaration specifiers after this.
766 6: return true;
767 : }
768 :
769 : // Fall through; the action had no suggestion for us.
770 : } else {
771 : // The action did not emit a diagnostic, so emit one now.
772 0: SourceRange R;
0: branch 0 not taken
0: branch 1 not taken
773 0: if (SS) R = SS->getRange();
774 0: Diag(Loc, diag::err_unknown_typename) << Tok.getIdentifierInfo() << R;
775 : }
776 :
777 : // Mark this as an error.
778 : const char *PrevSpec;
779 : unsigned DiagID;
780 25: DS.SetTypeSpecType(DeclSpec::TST_error, Loc, PrevSpec, DiagID);
781 25: DS.SetRangeEnd(Tok.getLocation());
782 25: ConsumeToken();
783 :
784 : // TODO: Could inject an invalid typedef decl in an enclosing scope to
785 : // avoid rippling error messages on subsequent uses of the same type,
786 : // could be useful if #include was forgotten.
787 25: return false;
788 : }
789 :
790 : /// \brief Determine the declaration specifier context from the declarator
791 : /// context.
792 : ///
793 : /// \param Context the declarator context, which is one of the
794 : /// Declarator::TheContext enumerator values.
795 : Parser::DeclSpecContext
796 15133: Parser::getDeclSpecContextFromDeclaratorContext(unsigned Context) {
0: branch 0 not taken
15133: branch 1 taken
797 15133: if (Context == Declarator::MemberContext)
798 0: return DSC_class;
7951: branch 0 taken
7182: branch 1 taken
799 15133: if (Context == Declarator::FileContext)
800 7951: return DSC_top_level;
801 7182: return DSC_normal;
802 : }
803 :
804 : /// ParseDeclarationSpecifiers
805 : /// declaration-specifiers: [C99 6.7]
806 : /// storage-class-specifier declaration-specifiers[opt]
807 : /// type-specifier declaration-specifiers[opt]
808 : /// [C99] function-specifier declaration-specifiers[opt]
809 : /// [GNU] attributes declaration-specifiers[opt]
810 : ///
811 : /// storage-class-specifier: [C99 6.7.1]
812 : /// 'typedef'
813 : /// 'extern'
814 : /// 'static'
815 : /// 'auto'
816 : /// 'register'
817 : /// [C++] 'mutable'
818 : /// [GNU] '__thread'
819 : /// function-specifier: [C99 6.7.4]
820 : /// [C99] 'inline'
821 : /// [C++] 'virtual'
822 : /// [C++] 'explicit'
823 : /// 'friend': [C++ dcl.friend]
824 : /// 'constexpr': [C++0x dcl.constexpr]
825 :
826 : ///
827 : void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
828 : const ParsedTemplateInfo &TemplateInfo,
829 : AccessSpecifier AS,
830 68202: DeclSpecContext DSContext) {
1: branch 1 taken
68201: branch 2 taken
831 68202: if (Tok.is(tok::code_completion)) {
832 1: Action::CodeCompletionContext CCC = Action::CCC_Namespace;
0: branch 0 not taken
1: branch 1 taken
833 1: if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate)
834 : CCC = DSContext == DSC_class? Action::CCC_MemberTemplate
0: branch 0 not taken
0: branch 1 not taken
835 0: : Action::CCC_Template;
1: branch 0 taken
0: branch 1 not taken
836 1: else if (DSContext == DSC_class)
837 1: CCC = Action::CCC_Class;
0: branch 1 not taken
0: branch 2 not taken
838 0: else if (ObjCImpDecl)
839 0: CCC = Action::CCC_ObjCImplementation;
840 :
841 1: Actions.CodeCompleteOrdinaryName(CurScope, CCC);
842 1: ConsumeToken();
843 : }
844 :
845 68202: DS.SetRangeStart(Tok.getLocation());
846 89325: while (1) {
847 157527: bool isInvalid = false;
848 157527: const char *PrevSpec = 0;
849 157527: unsigned DiagID = 0;
850 :
851 157527: SourceLocation Loc = Tok.getLocation();
852 :
34535: branch 1 taken
21: branch 2 taken
710: branch 3 taken
11977: branch 4 taken
42614: branch 5 taken
492: branch 6 taken
1766: branch 7 taken
11: branch 8 taken
1: branch 9 taken
4: branch 10 taken
6304: branch 11 taken
1909: branch 12 taken
19: branch 13 taken
2050: branch 14 taken
15: branch 15 taken
64: branch 16 taken
20: branch 17 taken
20: branch 18 taken
1407: branch 19 taken
557: branch 20 taken
31: branch 21 taken
97: branch 22 taken
0: branch 23 not taken
742: branch 24 taken
2083: branch 25 taken
420: branch 26 taken
2647: branch 27 taken
195: branch 28 taken
0: branch 29 not taken
11765: branch 30 taken
5462: branch 31 taken
16069: branch 32 taken
1626: branch 33 taken
985: branch 34 taken
20: branch 35 taken
2: branch 36 taken
2: branch 37 taken
346: branch 38 taken
1: branch 39 taken
0: branch 40 not taken
0: branch 41 not taken
84: branch 42 taken
4: branch 43 taken
7110: branch 44 taken
380: branch 45 taken
2395: branch 46 taken
151: branch 47 taken
9: branch 48 taken
125: branch 49 taken
260: branch 50 taken
16: branch 51 taken
4: branch 52 taken
853 157527: switch (Tok.getKind()) {
854 : default:
855 68202: DoneWithDeclSpec:
856 : // If this is not a declaration specifier token, we're done reading decl
857 : // specifiers. First verify that DeclSpec's are consistent.
858 68202: DS.Finish(Diags, PP);
859 : return;
860 :
861 : case tok::coloncolon: // ::foo::bar
862 : // Annotate C++ scope specifiers. If we get one, loop.
21: branch 1 taken
0: branch 2 not taken
863 21: if (TryAnnotateCXXScopeToken(true))
864 21: continue;
865 0: goto DoneWithDeclSpec;
866 :
867 : case tok::annot_cxxscope: {
465: branch 1 taken
245: branch 2 taken
868 710: if (DS.hasTypeSpecifier())
869 465: goto DoneWithDeclSpec;
870 :
871 245: CXXScopeSpec SS;
872 245: SS.setScopeRep(Tok.getAnnotationValue());
873 245: SS.setRange(Tok.getAnnotationRange());
874 :
875 : // We are looking for a qualified typename.
876 245: Token Next = NextToken();
41: branch 1 taken
204: branch 2 taken
41: branch 4 taken
0: branch 5 not taken
41: branch 6 taken
204: branch 7 taken
877 245: if (Next.is(tok::annot_template_id) &&
878 : static_cast<TemplateIdAnnotation *>(Next.getAnnotationValue())
879 : ->Kind == TNK_Type_template) {
880 : // We have a qualified template-id, e.g., N::A<int>
881 :
882 : // C++ [class.qual]p2:
883 : // In a lookup in which the constructor is an acceptable lookup
884 : // result and the nested-name-specifier nominates a class C:
885 : //
886 : // - if the name specified after the
887 : // nested-name-specifier, when looked up in C, is the
888 : // injected-class-name of C (Clause 9), or
889 : //
890 : // - if the name specified after the nested-name-specifier
891 : // is the same as the identifier or the
892 : // simple-template-id's template-name in the last
893 : // component of the nested-name-specifier,
894 : //
895 : // the name is instead considered to name the constructor of
896 : // class C.
897 : //
898 : // Thus, if the template-name is actually the constructor
899 : // name, then the code is ill-formed; this interpretation is
900 : // reinforced by the NAD status of core issue 635.
901 : TemplateIdAnnotation *TemplateId
902 41: = static_cast<TemplateIdAnnotation *>(Next.getAnnotationValue());
23: branch 0 taken
18: branch 1 taken
23: branch 2 taken
0: branch 3 not taken
4: branch 5 taken
19: branch 6 taken
4: branch 7 taken
37: branch 8 taken
903 41: if (DSContext == DSC_top_level && TemplateId->Name &&
904 : Actions.isCurrentClassName(*TemplateId->Name, CurScope, &SS)) {
1: branch 1 taken
3: branch 2 taken
905 4: if (isConstructorDeclarator()) {
906 : // The user meant this to be an out-of-line constructor
907 : // definition, but template arguments are not allowed
908 : // there. Just allow this as a constructor; we'll
909 : // complain about it later.
910 1: goto DoneWithDeclSpec;
911 : }
912 :
913 : // The user meant this to name a type, but it actually names
914 : // a constructor with some extraneous template
915 : // arguments. Complain, then parse it as a type as the user
916 : // intended.
917 : Diag(TemplateId->TemplateNameLoc,
918 : diag::err_out_of_line_template_id_names_constructor)
919 3: << TemplateId->Name;
920 : }
921 :
922 40: DS.getTypeSpecScope() = SS;
923 40: ConsumeToken(); // The C++ scope.
924 : assert(Tok.is(tok::annot_template_id) &&
40: branch 1 taken
0: branch 2 not taken
925 40: "ParseOptionalCXXScopeSpecifier not working");
926 40: AnnotateTemplateIdTokenAsType(&SS);
927 40: continue;
928 : }
929 :
0: branch 1 not taken
204: branch 2 taken
930 204: if (Next.is(tok::annot_typename)) {
931 0: DS.getTypeSpecScope() = SS;
932 0: ConsumeToken(); // The C++ scope.
0: branch 1 not taken
0: branch 2 not taken
933 0: if (Tok.getAnnotationValue())
934 : isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc,
935 : PrevSpec, DiagID,
936 0: Tok.getAnnotationValue());
937 : else
938 0: DS.SetTypeSpecError();
939 0: DS.SetRangeEnd(Tok.getAnnotationEndLoc());
940 0: ConsumeToken(); // The typename
941 : }
942 :
41: branch 1 taken
163: branch 2 taken
943 204: if (Next.isNot(tok::identifier))
944 41: goto DoneWithDeclSpec;
945 :
946 : // If we're in a context where the identifier could be a class name,
947 : // check whether this is a constructor declaration.
135: branch 0 taken
28: branch 1 taken
58: branch 4 taken
77: branch 5 taken
58: branch 6 taken
105: branch 7 taken
948 163: if (DSContext == DSC_top_level &&
949 : Actions.isCurrentClassName(*Next.getIdentifierInfo(), CurScope,
950 : &SS)) {
55: branch 1 taken
3: branch 2 taken
951 58: if (isConstructorDeclarator())
952 55: goto DoneWithDeclSpec;
953 :
954 : // As noted in C++ [class.qual]p2 (cited above), when the name
955 : // of the class is qualified in a context where it could name
956 : // a constructor, its a constructor name. However, we've
957 : // looked at the declarator, and the user probably meant this
958 : // to be a type. Complain that it isn't supposed to be treated
959 : // as a type, then proceed to parse it as a type.
960 : Diag(Next.getLocation(), diag::err_out_of_line_type_names_constructor)
961 3: << Next.getIdentifierInfo();
962 : }
963 :
964 : TypeTy *TypeRep = Actions.getTypeName(*Next.getIdentifierInfo(),
965 108: Next.getLocation(), CurScope, &SS);
966 :
967 : // If the referenced identifier is not a type, then this declspec is
968 : // erroneous: We already checked about that it has no type specifier, and
969 : // C++ doesn't have implicit int. Diagnose it as a typo w.r.t. to the
970 : // typename.
17: branch 0 taken
91: branch 1 taken
971 108: if (TypeRep == 0) {
972 17: ConsumeToken(); // Eat the scope spec so the identifier is current.
13: branch 1 taken
4: branch 2 taken
973 17: if (ParseImplicitInt(DS, &SS, TemplateInfo, AS)) continue;
974 13: goto DoneWithDeclSpec;
975 : }
976 :
977 91: DS.getTypeSpecScope() = SS;
978 91: ConsumeToken(); // The C++ scope.
979 :
980 : isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
981 91: DiagID, TypeRep);
91: branch 0 taken
0: branch 1 not taken
982 91: if (isInvalid)
983 0: break;
984 :
985 91: DS.SetRangeEnd(Tok.getLocation());
986 91: ConsumeToken(); // The typename.
987 :
988 91: continue;
989 : }
990 :
991 : case tok::annot_typename: {
11921: branch 1 taken
56: branch 2 taken
992 11977: if (Tok.getAnnotationValue())
993 : isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
994 11921: DiagID, Tok.getAnnotationValue());
995 : else
996 56: DS.SetTypeSpecError();
997 11977: DS.SetRangeEnd(Tok.getAnnotationEndLoc());
998 11977: ConsumeToken(); // The typename
999 :
1000 : // Objective-C supports syntax of the form 'id<proto1,proto2>' where 'id'
1001 : // is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an
1002 : // Objective-C interface. If we don't have Objective-C or a '<', this is
1003 : // just a normal reference to a typedef name.
218: branch 1 taken
11759: branch 2 taken
0: branch 4 not taken
218: branch 5 taken
11759: branch 6 taken
218: branch 7 taken
1004 11977: if (!Tok.is(tok::less) || !getLang().ObjC1)
1005 11759: continue;
1006 :
1007 218: SourceLocation LAngleLoc, EndProtoLoc;
1008 218: llvm::SmallVector<DeclPtrTy, 8> ProtocolDecl;
1009 218: llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
1010 : ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
1011 218: LAngleLoc, EndProtoLoc);
1012 : DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(),
1013 218: ProtocolLocs.data(), LAngleLoc);
1014 :
1015 218: DS.SetRangeEnd(EndProtoLoc);
1016 218: continue;
1017 : }
1018 :
1019 : // typedef-name
1020 : case tok::identifier: {
1021 : // In C++, check to see if this is a scope specifier like foo::bar::, if
1022 : // so handle it as such. This is important for ctor parsing.
16211: branch 1 taken
26403: branch 2 taken
1139: branch 4 taken
15072: branch 5 taken
1139: branch 6 taken
41475: branch 7 taken
1023 42614: if (getLang().CPlusPlus && TryAnnotateCXXScopeToken(true))
1024 1139: continue;
1025 :
1026 : // This identifier can only be a typedef name if we haven't already seen
1027 : // a type-specifier. Without this check we misparse:
1028 : // typedef int X; struct Y { short X; }; as 'short int'.
32399: branch 1 taken
9076: branch 2 taken
1029 41475: if (DS.hasTypeSpecifier())
1030 32399: goto DoneWithDeclSpec;
1031 :
1032 : // Check for need to substitute AltiVec keyword tokens.
64: branch 1 taken
9012: branch 2 taken
1033 9076: if (TryAltiVecToken(DS, Loc, PrevSpec, DiagID, isInvalid))
1034 64: break;
1035 :
1036 : // It has to be available as a typedef too!
1037 : TypeTy *TypeRep = Actions.getTypeName(*Tok.getIdentifierInfo(),
1038 9012: Tok.getLocation(), CurScope);
1039 :
1040 : // If this is not a typedef name, don't parse it as part of the declspec,
1041 : // it must be an implicit int or an error.
45: branch 0 taken
8967: branch 1 taken
1042 9012: if (TypeRep == 0) {
41: branch 1 taken
4: branch 2 taken
1043 45: if (ParseImplicitInt(DS, 0, TemplateInfo, AS)) continue;
1044 41: goto DoneWithDeclSpec;
1045 : }
1046 :
1047 : // If we're in a context where the identifier could be a class name,
1048 : // check whether this is a constructor declaration.
4024: branch 1 taken
4943: branch 2 taken
1203: branch 3 taken
2821: branch 4 taken
722: branch 7 taken
481: branch 8 taken
588: branch 10 taken
134: branch 11 taken
588: branch 12 taken
8379: branch 13 taken
1049 8967: if (getLang().CPlusPlus && DSContext == DSC_class &&
1050 : Actions.isCurrentClassName(*Tok.getIdentifierInfo(), CurScope) &&
1051 : isConstructorDeclarator())
1052 588: goto DoneWithDeclSpec;
1053 :
1054 : isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
1055 8379: DiagID, TypeRep);
0: branch 0 not taken
8379: branch 1 taken
1056 8379: if (isInvalid)
1057 0: break;
1058 :
1059 8379: DS.SetRangeEnd(Tok.getLocation());
1060 8379: ConsumeToken(); // The identifier
1061 :
1062 : // Objective-C supports syntax of the form 'id<proto1,proto2>' where 'id'
1063 : // is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an
1064 : // Objective-C interface. If we don't have Objective-C or a '<', this is
1065 : // just a normal reference to a typedef name.
116: branch 1 taken
8263: branch 2 taken
0: branch 4 not taken
116: branch 5 taken
8263: branch 6 taken
116: branch 7 taken
1066 8379: if (!Tok.is(tok::less) || !getLang().ObjC1)
1067 8263: continue;
1068 :
1069 116: SourceLocation LAngleLoc, EndProtoLoc;
1070 116: llvm::SmallVector<DeclPtrTy, 8> ProtocolDecl;
1071 116: llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
1072 : ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
1073 116: LAngleLoc, EndProtoLoc);
1074 : DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(),
1075 116: ProtocolLocs.data(), LAngleLoc);
1076 :
1077 116: DS.SetRangeEnd(EndProtoLoc);
1078 :
1079 : // Need to support trailing type qualifiers (e.g. "id<p> const").
1080 : // If a type specifier follows, it will be diagnosed elsewhere.
1081 116: continue;
1082 : }
1083 :
1084 : // type-name
1085 : case tok::annot_template_id: {
1086 : TemplateIdAnnotation *TemplateId
1087 492: = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
60: branch 0 taken
432: branch 1 taken
1088 492: if (TemplateId->Kind != TNK_Type_template) {
1089 : // This template-id does not refer to a type name, so we're
1090 : // done with the type-specifiers.
1091 60: goto DoneWithDeclSpec;
1092 : }
1093 :
1094 : // If we're in a context where the template-id could be a
1095 : // constructor name or specialization, check whether this is a
1096 : // constructor declaration.
432: branch 1 taken
0: branch 2 not taken
80: branch 3 taken
352: branch 4 taken
15: branch 6 taken
65: branch 7 taken
3: branch 9 taken
12: branch 10 taken
3: branch 11 taken
429: branch 12 taken
1097 432: if (getLang().CPlusPlus && DSContext == DSC_class &&
1098 : Actions.isCurrentClassName(*TemplateId->Name, CurScope) &&
1099 : isConstructorDeclarator())
1100 3: goto DoneWithDeclSpec;
1101 :
1102 : // Turn the template-id annotation token into a type annotation
1103 : // token, then try again to parse it as a type-specifier.
1104 429: AnnotateTemplateIdTokenAsType();
1105 429: continue;
1106 : }
1107 :
1108 : // GNU attributes support.
1109 : case tok::kw___attribute:
1110 1766: DS.AddAttributes(ParseGNUAttributes());
1111 1766: continue;
1112 :
1113 : // Microsoft declspec support.
1114 : case tok::kw___declspec:
1115 11: DS.AddAttributes(ParseMicrosoftDeclSpec());
1116 11: continue;
1117 :
1118 : // Microsoft single token adornments.
1119 : case tok::kw___forceinline:
1120 : // FIXME: Add handling here!
1121 1: break;
1122 :
1123 : case tok::kw___ptr64:
1124 : case tok::kw___w64:
1125 : case tok::kw___cdecl:
1126 : case tok::kw___stdcall:
1127 : case tok::kw___fastcall:
1128 4: DS.AddAttributes(ParseMicrosoftTypeAttributes());
1129 4: continue;
1130 :
1131 : // storage-class-specifier
1132 : case tok::kw_typedef:
1133 : isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, Loc, PrevSpec,
1134 6304: DiagID);
1135 6304: break;
1136 : case tok::kw_extern:
2: branch 1 taken
1907: branch 2 taken
1137 1909: if (DS.isThreadSpecified())
1138 2: Diag(Tok, diag::ext_thread_before) << "extern";
1139 : isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_extern, Loc, PrevSpec,
1140 1909: DiagID);
1141 1909: break;
1142 : case tok::kw___private_extern__:
1143 : isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_private_extern, Loc,
1144 19: PrevSpec, DiagID);
1145 19: break;
1146 : case tok::kw_static:
4: branch 1 taken
2046: branch 2 taken
1147 2050: if (DS.isThreadSpecified())
1148 4: Diag(Tok, diag::ext_thread_before) << "static";
1149 : isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_static, Loc, PrevSpec,
1150 2050: DiagID);
1151 2050: break;
1152 : case tok::kw_auto:
10: branch 1 taken
5: branch 2 taken
1153 15: if (getLang().CPlusPlus0x)
1154 : isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec,
1155 10: DiagID);
1156 : else
1157 : isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec,
1158 5: DiagID);
1159 15: break;
1160 : case tok::kw_register:
1161 : isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_register, Loc, PrevSpec,
1162 64: DiagID);
1163 64: break;
1164 : case tok::kw_mutable:
1165 : isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_mutable, Loc, PrevSpec,
1166 20: DiagID);
1167 20: break;
1168 : case tok::kw___thread:
1169 20: isInvalid = DS.SetStorageClassSpecThread(Loc, PrevSpec, DiagID);
1170 20: break;
1171 :
1172 : // function-specifier
1173 : case tok::kw_inline:
1174 1407: isInvalid = DS.SetFunctionSpecInline(Loc, PrevSpec, DiagID);
1175 1407: break;
1176 : case tok::kw_virtual:
1177 557: isInvalid = DS.SetFunctionSpecVirtual(Loc, PrevSpec, DiagID);
1178 557: break;
1179 : case tok::kw_explicit:
1180 31: isInvalid = DS.SetFunctionSpecExplicit(Loc, PrevSpec, DiagID);
1181 31: break;
1182 :
1183 : // friend
1184 : case tok::kw_friend:
91: branch 0 taken
6: branch 1 taken
1185 97: if (DSContext == DSC_class)
1186 91: isInvalid = DS.SetFriendSpec(Loc, PrevSpec, DiagID);
1187 : else {
1188 6: PrevSpec = ""; // not actually used by the diagnostic
1189 6: DiagID = diag::err_friend_invalid_in_context;
1190 6: isInvalid = true;
1191 : }
1192 97: break;
1193 :
1194 : // constexpr
1195 : case tok::kw_constexpr:
1196 0: isInvalid = DS.SetConstexprSpec(Loc, PrevSpec, DiagID);
1197 0: break;
1198 :
1199 : // type-specifier
1200 : case tok::kw_short:
1201 : isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec,
1202 742: DiagID);
1203 742: break;
1204 : case tok::kw_long:
1563: branch 1 taken
520: branch 2 taken
1205 2083: if (DS.getTypeSpecWidth() != DeclSpec::TSW_long)
1206 : isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec,
1207 1563: DiagID);
1208 : else
1209 : isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec,
1210 520: DiagID);
1211 2083: break;
1212 : case tok::kw_signed:
1213 : isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec,
1214 420: DiagID);
1215 420: break;
1216 : case tok::kw_unsigned:
1217 : isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec,
1218 2647: DiagID);
1219 2647: break;
1220 : case tok::kw__Complex:
1221 : isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, Loc, PrevSpec,
1222 195: DiagID);
1223 195: break;
1224 : case tok::kw__Imaginary:
1225 : isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, Loc, PrevSpec,
1226 0: DiagID);
1227 0: break;
1228 : case tok::kw_void:
1229 : isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec,
1230 11765: DiagID);
1231 11765: break;
1232 : case tok::kw_char:
1233 : isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec,
1234 5462: DiagID);
1235 5462: break;
1236 : case tok::kw_int:
1237 : isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec,
1238 16069: DiagID);
1239 16069: break;
1240 : case tok::kw_float:
1241 : isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec,
1242 1626: DiagID);
1243 1626: break;
1244 : case tok::kw_double:
1245 : isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec,
1246 985: DiagID);
1247 985: break;
1248 : case tok::kw_wchar_t:
1249 : isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec,
1250 20: DiagID);
1251 20: break;
1252 : case tok::kw_char16_t:
1253 : isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec,
1254 2: DiagID);
1255 2: break;
1256 : case tok::kw_char32_t:
1257 : isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec,
1258 2: DiagID);
1259 2: break;
1260 : case tok::kw_bool:
1261 : case tok::kw__Bool:
1262 : isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec,
1263 346: DiagID);
1264 346: break;
1265 : case tok::kw__Decimal32:
1266 : isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, Loc, PrevSpec,
1267 1: DiagID);
1268 1: break;
1269 : case tok::kw__Decimal64:
1270 : isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, Loc, PrevSpec,
1271 0: DiagID);
1272 0: break;
1273 : case tok::kw__Decimal128:
1274 : isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, Loc, PrevSpec,
1275 0: DiagID);
1276 0: break;
1277 : case tok::kw___vector:
1278 84: isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID);
1279 84: break;
1280 : case tok::kw___pixel:
1281 4: isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID);
1282 4: break;
1283 :
1284 : // class-specifier:
1285 : case tok::kw_class:
1286 : case tok::kw_struct:
1287 : case tok::kw_union: {
1288 7110: tok::TokenKind Kind = Tok.getKind();
1289 7110: ConsumeToken();
1290 7110: ParseClassSpecifier(Kind, Loc, DS, TemplateInfo, AS);
1291 7110: continue;
1292 : }
1293 :
1294 : // enum-specifier:
1295 : case tok::kw_enum:
1296 380: ConsumeToken();
1297 380: ParseEnumSpecifier(Loc, DS, AS);
1298 380: continue;
1299 :
1300 : // cv-qualifier:
1301 : case tok::kw_const:
1302 : isInvalid = DS.SetTypeQual(DeclSpec::TQ_const, Loc, PrevSpec, DiagID,
1303 2395: getLang());
1304 2395: break;
1305 : case tok::kw_volatile:
1306 : isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID,
1307 151: getLang());
1308 151: break;
1309 : case tok::kw_restrict:
1310 : isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID,
1311 9: getLang());
1312 9: break;
1313 :
1314 : // C++ typename-specifier:
1315 : case tok::kw_typename:
123: branch 1 taken
2: branch 2 taken
1316 125: if (TryAnnotateTypeOrScopeToken())
1317 123: continue;
1318 2: break;
1319 :
1320 : // GNU typeof support.
1321 : case tok::kw_typeof:
1322 260: ParseTypeofSpecifier(DS);
1323 260: continue;
1324 :
1325 : case tok::kw_decltype:
1326 16: ParseDecltypeSpecifier(DS);
1327 16: continue;
1328 :
1329 : case tok::less:
1330 : // GCC ObjC supports types like "<SomeProtocol>" as a synonym for
1331 : // "id<SomeProtocol>". This is hopelessly old fashioned and dangerous,
1332 : // but we support it.
3: branch 1 taken
1: branch 2 taken
0: branch 4 not taken
3: branch 5 taken
1: branch 6 taken
3: branch 7 taken
1333 4: if (DS.hasTypeSpecifier() || !getLang().ObjC1)
1334 1: goto DoneWithDeclSpec;
1335 :
1336 : {
1337 3: SourceLocation LAngleLoc, EndProtoLoc;
1338 3: llvm::SmallVector<DeclPtrTy, 8> ProtocolDecl;
1339 3: llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
1340 : ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
1341 3: LAngleLoc, EndProtoLoc);
1342 : DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(),
1343 3: ProtocolLocs.data(), LAngleLoc);
1344 3: DS.SetRangeEnd(EndProtoLoc);
1345 :
1346 : Diag(Loc, diag::warn_objc_protocol_qualifier_missing_id)
1347 : << CodeModificationHint::CreateInsertion(Loc, "id")
1348 3: << SourceRange(Loc, EndProtoLoc);
1349 : // Need to support trailing type qualifiers (e.g. "id<p> const").
1350 : // If a type specifier follows, it will be diagnosed elsewhere.
1351 3: continue;
1352 : }
1353 : }
1354 : // If the specifier wasn't legal, issue a diagnostic.
55: branch 0 taken
57513: branch 1 taken
1355 57568: if (isInvalid) {
0: branch 0 not taken
55: branch 1 taken
1356 55: assert(PrevSpec && "Method did not return previous specifier!");
0: branch 0 not taken
55: branch 1 taken
1357 55: assert(DiagID);
1358 55: Diag(Tok, DiagID) << PrevSpec;
1359 : }
1360 57568: DS.SetRangeEnd(Tok.getLocation());
1361 57568: ConsumeToken();
1362 : }
1363 : }
1364 :
1365 : /// ParseOptionalTypeSpecifier - Try to parse a single type-specifier. We
1366 : /// primarily follow the C++ grammar with additions for C99 and GNU,
1367 : /// which together subsume the C grammar. Note that the C++
1368 : /// type-specifier also includes the C type-qualifier (for const,
1369 : /// volatile, and C99 restrict). Returns true if a type-specifier was
1370 : /// found (and parsed), false otherwise.
1371 : ///
1372 : /// type-specifier: [C++ 7.1.5]
1373 : /// simple-type-specifier
1374 : /// class-specifier
1375 : /// enum-specifier
1376 : /// elaborated-type-specifier [TODO]
1377 : /// cv-qualifier
1378 : ///
1379 : /// cv-qualifier: [C++ 7.1.5.1]
1380 : /// 'const'
1381 : /// 'volatile'
1382 : /// [C99] 'restrict'
1383 : ///
1384 : /// simple-type-specifier: [ C++ 7.1.5.2]
1385 : /// '::'[opt] nested-name-specifier[opt] type-name [TODO]
1386 : /// '::'[opt] nested-name-specifier 'template' template-id [TODO]
1387 : /// 'char'
1388 : /// 'wchar_t'
1389 : /// 'bool'
1390 : /// 'short'
1391 : /// 'int'
1392 : /// 'long'
1393 : /// 'signed'
1394 : /// 'unsigned'
1395 : /// 'float'
1396 : /// 'double'
1397 : /// 'void'
1398 : /// [C99] '_Bool'
1399 : /// [C99] '_Complex'
1400 : /// [C99] '_Imaginary' // Removed in TC2?
1401 : /// [GNU] '_Decimal32'
1402 : /// [GNU] '_Decimal64'
1403 : /// [GNU] '_Decimal128'
1404 : /// [GNU] typeof-specifier
1405 : /// [OBJC] class-name objc-protocol-refs[opt] [TODO]
1406 : /// [OBJC] typedef-name objc-protocol-refs[opt] [TODO]
1407 : /// [C++0x] 'decltype' ( expression )
1408 : /// [AltiVec] '__vector'
1409 : bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
1410 : const char *&PrevSpec,
1411 : unsigned &DiagID,
1412 : const ParsedTemplateInfo &TemplateInfo,
1413 1075: bool SuppressDeclarations) {
1414 1075: SourceLocation Loc = Tok.getLocation();
1415 :
231: branch 1 taken
0: branch 2 not taken
0: branch 3 not taken
215: branch 4 taken
5: branch 5 taken
5: branch 6 taken
1: branch 7 taken
3: branch 8 taken
1: branch 9 taken
0: branch 10 not taken
3: branch 11 taken
9: branch 12 taken
130: branch 13 taken
14: branch 14 taken
3: branch 15 taken
0: branch 16 not taken
0: branch 17 not taken
0: branch 18 not taken
19: branch 19 taken
0: branch 20 not taken
0: branch 21 not taken
0: branch 22 not taken
0: branch 23 not taken
0: branch 24 not taken
3: branch 25 taken
0: branch 26 not taken
22: branch 27 taken
6: branch 28 taken
0: branch 29 not taken
0: branch 30 not taken
0: branch 31 not taken
1: branch 32 taken
0: branch 33 not taken
404: branch 34 taken
1416 1075: switch (Tok.getKind()) {
1417 : case tok::identifier: // foo::bar
1418 : // Check for need to substitute AltiVec keyword tokens.
231: branch 1 taken
0: branch 2 not taken
1419 231: if (TryAltiVecToken(DS, Loc, PrevSpec, DiagID, isInvalid))
1420 0: break;
1421 : // Fall through.
1422 : case tok::kw_typename: // typename foo::bar
1423 : // Annotate typenames and C++ scope specifiers. If we get one, just
1424 : // recurse to handle whatever we get.
218: branch 1 taken
13: branch 2 taken
1425 231: if (TryAnnotateTypeOrScopeToken())
1426 : return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
1427 218: TemplateInfo, SuppressDeclarations);
1428 : // Otherwise, not a type specifier.
1429 13: return false;
1430 : case tok::coloncolon: // ::foo::bar
0: branch 2 not taken
0: branch 3 not taken
0: branch 6 not taken
0: branch 7 not taken
0: branch 8 not taken
0: branch 9 not taken
1431 0: if (NextToken().is(tok::kw_new) || // ::new
1432 : NextToken().is(tok::kw_delete)) // ::delete
1433 0: return false;
1434 :
1435 : // Annotate typenames and C++ scope specifiers. If we get one, just
1436 : // recurse to handle whatever we get.
0: branch 1 not taken
0: branch 2 not taken
1437 0: if (TryAnnotateTypeOrScopeToken())
1438 : return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
1439 0: TemplateInfo, SuppressDeclarations);
1440 : // Otherwise, not a type specifier.
1441 0: return false;
1442 :
1443 : // simple-type-specifier:
1444 : case tok::annot_typename: {
215: branch 1 taken
0: branch 2 not taken
1445 215: if (Tok.getAnnotationValue())
1446 : isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,
1447 215: DiagID, Tok.getAnnotationValue());
1448 : else
1449 0: DS.SetTypeSpecError();
1450 215: DS.SetRangeEnd(Tok.getAnnotationEndLoc());
1451 215: ConsumeToken(); // The typename
1452 :
1453 : // Objective-C supports syntax of the form 'id<proto1,proto2>' where 'id'
1454 : // is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an
1455 : // Objective-C interface. If we don't have Objective-C or a '<', this is
1456 : // just a normal reference to a typedef name.
0: branch 1 not taken
215: branch 2 taken
0: branch 4 not taken
0: branch 5 not taken
215: branch 6 taken
0: branch 7 not taken
1457 215: if (!Tok.is(tok::less) || !getLang().ObjC1)
1458 215: return true;
1459 :
1460 0: SourceLocation LAngleLoc, EndProtoLoc;
1461 0: llvm::SmallVector<DeclPtrTy, 8> ProtocolDecl;
1462 0: llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
1463 : ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false,
1464 0: LAngleLoc, EndProtoLoc);
1465 : DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(),
1466 0: ProtocolLocs.data(), LAngleLoc);
1467 :
1468 0: DS.SetRangeEnd(EndProtoLoc);
1469 0: return true;
1470 : }
1471 :
1472 : case tok::kw_short:
1473 5: isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, DiagID);
1474 5: break;
1475 : case tok::kw_long:
5: branch 1 taken
0: branch 2 not taken
1476 5: if (DS.getTypeSpecWidth() != DeclSpec::TSW_long)
1477 : isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec,
1478 5: DiagID);
1479 : else
1480 : isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec,
1481 0: DiagID);
1482 5: break;
1483 : case tok::kw_signed:
1484 1: isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec, DiagID);
1485 1: break;
1486 : case tok::kw_unsigned:
1487 : isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec,
1488 3: DiagID);
1489 3: break;
1490 : case tok::kw__Complex:
1491 : isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, Loc, PrevSpec,
1492 1: DiagID);
1493 1: break;
1494 : case tok::kw__Imaginary:
1495 : isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, Loc, PrevSpec,
1496 0: DiagID);
1497 0: break;
1498 : case tok::kw_void:
1499 3: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, DiagID);
1500 3: break;
1501 : case tok::kw_char:
1502 9: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, DiagID);
1503 9: break;
1504 : case tok::kw_int:
1505 130: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID);
1506 130: break;
1507 : case tok::kw_float:
1508 14: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID);
1509 14: break;
1510 : case tok::kw_double:
1511 3: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID);
1512 3: break;
1513 : case tok::kw_wchar_t:
1514 0: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID);
1515 0: break;
1516 : case tok::kw_char16_t:
1517 0: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, DiagID);
1518 0: break;
1519 : case tok::kw_char32_t:
1520 0: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec, DiagID);
1521 0: break;
1522 : case tok::kw_bool:
1523 : case tok::kw__Bool:
1524 19: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, DiagID);
1525 19: break;
1526 : case tok::kw__Decimal32:
1527 : isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, Loc, PrevSpec,
1528 0: DiagID);
1529 0: break;
1530 : case tok::kw__Decimal64:
1531 : isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, Loc, PrevSpec,
1532 0: DiagID);
1533 0: break;
1534 : case tok::kw__Decimal128:
1535 : isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, Loc, PrevSpec,
1536 0: DiagID);
1537 0: break;
1538 : case tok::kw___vector:
1539 0: isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID);
1540 0: break;
1541 : case tok::kw___pixel:
1542 0: isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID);
1543 0: break;
1544 :
1545 : // class-specifier:
1546 : case tok::kw_class:
1547 : case tok::kw_struct:
1548 : case tok::kw_union: {
1549 3: tok::TokenKind Kind = Tok.getKind();
1550 3: ConsumeToken();
1551 : ParseClassSpecifier(Kind, Loc, DS, TemplateInfo, AS_none,
1552 3: SuppressDeclarations);
1553 3: return true;
1554 : }
1555 :
1556 : // enum-specifier:
1557 : case tok::kw_enum:
1558 0: ConsumeToken();
1559 0: ParseEnumSpecifier(Loc, DS);
1560 0: return true;
1561 :
1562 : // cv-qualifier:
1563 : case tok::kw_const:
1564 : isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , Loc, PrevSpec,
1565 22: DiagID, getLang());
1566 22: break;
1567 : case tok::kw_volatile:
1568 : isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec,
1569 6: DiagID, getLang());
1570 6: break;
1571 : case tok::kw_restrict:
1572 : isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec,
1573 0: DiagID, getLang());
1574 0: break;
1575 :
1576 : // GNU typeof support.
1577 : case tok::kw_typeof:
1578 0: ParseTypeofSpecifier(DS);
1579 0: return true;
1580 :
1581 : // C++0x decltype support.
1582 : case tok::kw_decltype:
1583 0: ParseDecltypeSpecifier(DS);
1584 0: return true;
1585 :
1586 : // C++0x auto support.
1587 : case tok::kw_auto:
0: branch 1 not taken
1: branch 2 taken
1588 1: if (!getLang().CPlusPlus0x)
1589 0: return false;
1590 :
1591 1: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec, DiagID);
1592 1: break;
1593 : case tok::kw___ptr64:
1594 : case tok::kw___w64:
1595 : case tok::kw___cdecl:
1596 : case tok::kw___stdcall:
1597 : case tok::kw___fastcall:
1598 0: DS.AddAttributes(ParseMicrosoftTypeAttributes());
1599 0: return true;
1600 :
1601 : default:
1602 : // Not a type-specifier; do nothing.
1603 404: return false;
1604 : }
1605 :
1606 : // If the specifier combination wasn't legal, issue a diagnostic.
0: branch 0 not taken
222: branch 1 taken
1607 222: if (isInvalid) {
0: branch 0 not taken
0: branch 1 not taken
1608 0: assert(PrevSpec && "Method did not return previous specifier!");
1609 : // Pick between error or extwarn.
1610 0: Diag(Tok, DiagID) << PrevSpec;
1611 : }
1612 222: DS.SetRangeEnd(Tok.getLocation());
1613 222: ConsumeToken(); // whatever we parsed above.
1614 222: return true;
1615 : }
1616 :
1617 : /// ParseStructDeclaration - Parse a struct declaration without the terminating
1618 : /// semicolon.
1619 : ///
1620 : /// struct-declaration:
1621 : /// specifier-qualifier-list struct-declarator-list
1622 : /// [GNU] __extension__ struct-declaration
1623 : /// [GNU] specifier-qualifier-list
1624 : /// struct-declarator-list:
1625 : /// struct-declarator
1626 : /// struct-declarator-list ',' struct-declarator
1627 : /// [GNU] struct-declarator-list ',' attributes[opt] struct-declarator
1628 : /// struct-declarator:
1629 : /// declarator
1630 : /// [GNU] declarator attributes[opt]
1631 : /// declarator[opt] ':' constant-expression
1632 : /// [GNU] declarator[opt] ':' constant-expression attributes[opt]
1633 : ///
1634 : void Parser::
1635 3603: ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) {
21: branch 1 taken
3582: branch 2 taken
1636 3603: if (Tok.is(tok::kw___extension__)) {
1637 : // __extension__ silences extension warnings in the subexpression.
1638 21: ExtensionRAIIObject O(Diags); // Use RAII to do this.
1639 21: ConsumeToken();
1640 21: return ParseStructDeclaration(DS, Fields);
1641 : }
1642 :
1643 : // Parse the common specifier-qualifiers-list piece.
1644 3582: SourceLocation DSStart = Tok.getLocation();
1645 3582: ParseSpecifierQualifierList(DS);
1646 :
1647 : // If there are no declarators, this is a free-standing declaration
1648 : // specifier. Let the actions module cope with it.
24: branch 1 taken
3558: branch 2 taken
1649 3582: if (Tok.is(tok::semi)) {
1650 24: Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
1651 24: return;
1652 : }
1653 :
1654 : // Read struct-declarators until we find the semicolon.
1655 3558: bool FirstDeclarator = true;
180: branch 1 taken
3558: branch 2 taken
180: branch 4 taken
3558: branch 5 taken
1656 3738: while (1) {
1657 3738: ParsingDeclRAIIObject PD(*this);
1658 3738: FieldDeclarator DeclaratorInfo(DS);
1659 :
1660 : // Attributes are only allowed here on successive declarators.
180: branch 0 taken
3558: branch 1 taken
0: branch 3 not taken
180: branch 4 taken
0: branch 5 not taken
3738: branch 6 taken
1661 3738: if (!FirstDeclarator && Tok.is(tok::kw___attribute)) {
1662 0: SourceLocation Loc;
1663 0: AttributeList *AttrList = ParseGNUAttributes(&Loc);
1664 0: DeclaratorInfo.D.AddAttributes(AttrList, Loc);
1665 : }
1666 :
1667 : /// struct-declarator: declarator
1668 : /// struct-declarator: declarator[opt] ':' constant-expression
3695: branch 1 taken
43: branch 2 taken
1669 3738: if (Tok.isNot(tok::colon)) {
1670 : // Don't parse FOO:BAR as if it were a typo for FOO::BAR.
1671 3695: ColonProtectionRAIIObject X(*this);
1672 3695: ParseDeclarator(DeclaratorInfo.D);
1673 : }
1674 :
269: branch 1 taken
3469: branch 2 taken
1675 3738: if (Tok.is(tok::colon)) {
1676 269: ConsumeToken();
1677 269: OwningExprResult Res(ParseConstantExpression());
0: branch 1 not taken
269: branch 2 taken
1678 269: if (Res.isInvalid())
1679 0: SkipUntil(tok::semi, true, true);
1680 : else
1681 269: DeclaratorInfo.BitfieldSize = Res.release();
1682 : }
1683 :
1684 : // If attributes exist after the declarator, parse them.
25: branch 1 taken
3713: branch 2 taken
1685 3738: if (Tok.is(tok::kw___attribute)) {
1686 25: SourceLocation Loc;
1687 25: AttributeList *AttrList = ParseGNUAttributes(&Loc);
1688 25: DeclaratorInfo.D.AddAttributes(AttrList, Loc);
1689 : }
1690 :
1691 : // We're done with this declarator; invoke the callback.
1692 3738: DeclPtrTy D = Fields.invoke(DeclaratorInfo);
1693 3738: PD.complete(D);
1694 :
1695 : // If we don't have a comma, it is either the end of the list (a ';')
1696 : // or an error, bail out.
3558: branch 1 taken
180: branch 2 taken
1697 3738: if (Tok.isNot(tok::comma))
1698 3558: return;
1699 :
1700 : // Consume the comma.
1701 180: ConsumeToken();
1702 :
1703 180: FirstDeclarator = false;
1704 : }
1705 : }
1706 :
1707 : /// ParseStructUnionBody
1708 : /// struct-contents:
1709 : /// struct-declaration-list
1710 : /// [EXT] empty
1711 : /// [GNU] "struct-declaration-list" without terminatoring ';'
1712 : /// struct-declaration-list:
1713 : /// struct-declaration
1714 : /// struct-declaration-list struct-declaration
1715 : /// [OBC] '@' 'defs' '(' class-name ')'
1716 : ///
1717 : void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
1718 1416: unsigned TagType, DeclPtrTy TagDecl) {
1719 : PrettyStackTraceActionsDecl CrashInfo(TagDecl, RecordLoc, Actions,
1720 : PP.getSourceManager(),
1721 1416: "parsing struct/union body");
1722 :
1723 1416: SourceLocation LBraceLoc = ConsumeBrace();
1724 :
1725 1416: ParseScope StructScope(this, Scope::ClassScope|Scope::DeclScope);
1726 1416: Actions.ActOnTagStartDefinition(CurScope, TagDecl);
1727 :
1728 : // Empty structs are an extension in C (C99 6.7.2.1p7), but are allowed in
1729 : // C++.
174: branch 1 taken
1242: branch 2 taken
174: branch 4 taken
0: branch 5 not taken
174: branch 6 taken
1242: branch 7 taken
1730 1416: if (Tok.is(tok::r_brace) && !getLang().CPlusPlus)
1731 : Diag(Tok, diag::ext_empty_struct_union_enum)
1732 174: << DeclSpec::getSpecifierName((DeclSpec::TST)TagType);
1733 :
1734 1416: llvm::SmallVector<DeclPtrTy, 32> FieldDecls;
1735 :
1736 : // While we still have something to read, read the declarations in the struct.
2404: branch 1 taken
0: branch 2 not taken
6: branch 3 taken
2412: branch 5 taken
1410: branch 6 taken
2412: branch 8 taken
0: branch 9 not taken
2412: branch 10 taken
1410: branch 11 taken
1737 3826: while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
1738 : // Each iteration of this loop reads one struct-declaration.
1739 :
1740 : // Check for extraneous top-level semicolon.
2: branch 1 taken
2410: branch 2 taken
1741 2412: if (Tok.is(tok::semi)) {
1742 : Diag(Tok, diag::ext_extra_struct_semi)
1743 2: << CodeModificationHint::CreateRemoval(Tok.getLocation());
1744 2: ConsumeToken();
1745 2: continue;
1746 : }
1747 :
1748 : // Parse all the comma separated declarators.
1749 2410: DeclSpec DS;
1750 :
2400: branch 1 taken
10: branch 2 taken
1751 2410: if (!Tok.is(tok::at)) {
0: branch 1 not taken
0: branch 2 not taken
0: branch 5 not taken
2400: branch 6 taken
0: branch 9 not taken
0: branch 10 not taken
1752 2400: struct CFieldCallback : FieldCallback {
1753 : Parser &P;
1754 : DeclPtrTy TagDecl;
1755 : llvm::SmallVectorImpl<DeclPtrTy> &FieldDecls;
1756 :
1757 : CFieldCallback(Parser &P, DeclPtrTy TagDecl,
1758 2400: llvm::SmallVectorImpl<DeclPtrTy> &FieldDecls) :
1759 2400: P(P), TagDecl(TagDecl), FieldDecls(FieldDecls) {}
1760 :
1761 2546: virtual DeclPtrTy invoke(FieldDeclarator &FD) {
1762 : // Install the declarator into the current TagDecl.
1763 : DeclPtrTy Field = P.Actions.ActOnField(P.CurScope, TagDecl,
1764 : FD.D.getDeclSpec().getSourceRange().getBegin(),
1765 2546: FD.D, FD.BitfieldSize);
1766 2546: FieldDecls.push_back(Field);
1767 : return Field;
1768 : }
1769 2400: } Callback(*this, TagDecl, FieldDecls);
1770 :
1771 2400: ParseStructDeclaration(DS, Callback);
1772 : } else { // Handle @defs
1773 10: ConsumeToken();
0: branch 1 not taken
10: branch 2 taken
1774 10: if (!Tok.isObjCAtKeyword(tok::objc_defs)) {
1775 0: Diag(Tok, diag::err_unexpected_at);
1776 0: SkipUntil(tok::semi, true);
1777 0: continue;
1778 : }
1779 10: ConsumeToken();
1780 10: ExpectAndConsume(tok::l_paren, diag::err_expected_lparen);
0: branch 1 not taken
10: branch 2 taken
1781 10: if (!Tok.is(tok::identifier)) {
1782 0: Diag(Tok, diag::err_expected_ident);
1783 0: SkipUntil(tok::semi, true);
1784 : continue;
1785 : }
1786 10: llvm::SmallVector<DeclPtrTy, 16> Fields;
1787 : Actions.ActOnDefs(CurScope, TagDecl, Tok.getLocation(),
1788 10: Tok.getIdentifierInfo(), Fields);
1789 10: FieldDecls.insert(FieldDecls.end(), Fields.begin(), Fields.end());
1790 10: ConsumeToken();
1791 10: ExpectAndConsume(tok::r_paren, diag::err_expected_rparen);
1792 : }
1793 :
2403: branch 1 taken
7: branch 2 taken
1794 2410: if (Tok.is(tok::semi)) {
1795 2403: ConsumeToken();
6: branch 1 taken
1: branch 2 taken
1796 7: } else if (Tok.is(tok::r_brace)) {
1797 6: ExpectAndConsume(tok::semi, diag::ext_expected_semi_decl_list);
1798 6: break;
1799 : } else {
1800 1: ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list);
1801 : // Skip to end of block or statement to avoid ext-warning on extra ';'.
1802 1: SkipUntil(tok::r_brace, true, true);
1803 : // If we stopped at a ';', eat it.
1: branch 1 taken
0: branch 2 not taken
1804 1: if (Tok.is(tok::semi)) ConsumeToken();
1805 : }
1806 : }
1807 :
1808 1416: SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc);
1809 :
1810 1416: AttributeList *AttrList = 0;
1811 : // If attributes exist after struct contents, parse them.
11: branch 1 taken
1405: branch 2 taken
1812 1416: if (Tok.is(tok::kw___attribute))
1813 11: AttrList = ParseGNUAttributes();
1814 :
1815 : Actions.ActOnFields(CurScope,
1816 : RecordLoc, TagDecl, FieldDecls.data(), FieldDecls.size(),
1817 : LBraceLoc, RBraceLoc,
1818 1416: AttrList);
1819 1416: StructScope.Exit();
1820 1416: Actions.ActOnTagFinishDefinition(CurScope, TagDecl, RBraceLoc);
1821 1416: }
1822 :
1823 :
1824 : /// ParseEnumSpecifier
1825 : /// enum-specifier: [C99 6.7.2.2]
1826 : /// 'enum' identifier[opt] '{' enumerator-list '}'
1827 : ///[C99/C++]'enum' identifier[opt] '{' enumerator-list ',' '}'
1828 : /// [GNU] 'enum' attributes[opt] identifier[opt] '{' enumerator-list ',' [opt]
1829 : /// '}' attributes[opt]
1830 : /// 'enum' identifier
1831 : /// [GNU] 'enum' attributes[opt] identifier
1832 : ///
1833 : /// [C++] elaborated-type-specifier:
1834 : /// [C++] 'enum' '::'[opt] nested-name-specifier[opt] identifier
1835 : ///
1836 : void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
1837 381: AccessSpecifier AS) {
1838 : // Parse the tag portion of this.
1: branch 1 taken
380: branch 2 taken
1839 381: if (Tok.is(tok::code_completion)) {
1840 : // Code completion for an enum name.
1841 1: Actions.CodeCompleteTag(CurScope, DeclSpec::TST_enum);
1842 1: ConsumeToken();
1843 : }
1844 :
1845 381: AttributeList *Attr = 0;
1846 : // If attributes exist after tag, parse them.
0: branch 1 not taken
381: branch 2 taken
1847 381: if (Tok.is(tok::kw___attribute))
1848 0: Attr = ParseGNUAttributes();
1849 :
1850 381: CXXScopeSpec SS;
135: branch 1 taken
246: branch 2 taken
5: branch 4 taken
130: branch 5 taken
5: branch 6 taken
376: branch 7 taken
1851 381: if (getLang().CPlusPlus && ParseOptionalCXXScopeSpecifier(SS, 0, false)) {
0: branch 1 not taken
5: branch 2 taken
1852 5: if (Tok.isNot(tok::identifier)) {
1853 0: Diag(Tok, diag::err_expected_ident);
0: branch 1 not taken
0: branch 2 not taken
1854 0: if (Tok.isNot(tok::l_brace)) {
1855 : // Has no name and is not a definition.
1856 : // Skip the rest of this declarator, up until the comma or semicolon.
1857 0: SkipUntil(tok::comma, true);
1858 0: return;
1859 : }
1860 : }
1861 : }
1862 :
1863 : // Must have either 'enum name' or 'enum {...}'.
165: branch 1 taken
216: branch 2 taken
1: branch 4 taken
164: branch 5 taken
1: branch 6 taken
380: branch 7 taken
1864 381: if (Tok.isNot(tok::identifier) && Tok.isNot(tok::l_brace)) {
1865 1: Diag(Tok, diag::err_expected_ident_lbrace);
1866 :
1867 : // Skip the rest of this declarator, up until the comma or semicolon.
1868 1: SkipUntil(tok::comma, true);
1869 1: return;
1870 : }
1871 :
1872 : // If an identifier is present, consume and remember it.
1873 380: IdentifierInfo *Name = 0;
1874 380: SourceLocation NameLoc;
216: branch 1 taken
164: branch 2 taken
1875 380: if (Tok.is(tok::identifier)) {
1876 216: Name = Tok.getIdentifierInfo();
1877 216: NameLoc = ConsumeToken();
1878 : }
1879 :
1880 : // There are three options here. If we have 'enum foo;', then this is a
1881 : // forward declaration. If we have 'enum foo {...' then this is a
1882 : // definition. Otherwise we have something like 'enum foo xyz', a reference.
1883 : //
1884 : // This is needed to handle stuff like this right (C99 6.7.2.3p11):
1885 : // enum foo {..}; void bar() { enum foo; } <- new foo in bar.
1886 : // enum foo {..}; void bar() { enum foo x; } <- use of old foo.
1887 : //
1888 : Action::TagUseKind TUK;
319: branch 1 taken
61: branch 2 taken
1889 380: if (Tok.is(tok::l_brace))
1890 319: TUK = Action::TUK_Definition;
6: branch 1 taken
55: branch 2 taken
1891 61: else if (Tok.is(tok::semi))
1892 6: TUK = Action::TUK_Declaration;
1893 : else
1894 55: TUK = Action::TUK_Reference;
1895 380: bool Owned = false;
1896 380: bool IsDependent = false;
1897 : DeclPtrTy TagDecl = Actions.ActOnTag(CurScope, DeclSpec::TST_enum, TUK,
1898 : StartLoc, SS, Name, NameLoc, Attr, AS,
1899 : Action::MultiTemplateParamsArg(Actions),
1900 380: Owned, IsDependent);
0: branch 0 not taken
380: branch 1 taken
1901 380: assert(!IsDependent && "didn't expect dependent enum");
1902 :
319: branch 1 taken
61: branch 2 taken
1903 380: if (Tok.is(tok::l_brace))
1904 319: ParseEnumBody(StartLoc, TagDecl);
1905 :
1906 : // FIXME: The DeclSpec should keep the locations of both the keyword and the
1907 : // name (if there is one).
216: branch 1 taken
164: branch 2 taken
1908 380: SourceLocation TSTLoc = NameLoc.isValid()? NameLoc : StartLoc;
1909 380: const char *PrevSpec = 0;
1910 : unsigned DiagID;
0: branch 2 not taken
380: branch 3 taken
1911 380: if (DS.SetTypeSpecType(DeclSpec::TST_enum, TSTLoc, PrevSpec, DiagID,
1912 : TagDecl.getAs<void>(), Owned))
1913 0: Diag(StartLoc, DiagID) << PrevSpec;
1914 : }
1915 :
1916 : /// ParseEnumBody - Parse a {} enclosed enumerator-list.
1917 : /// enumerator-list:
1918 : /// enumerator
1919 : /// enumerator-list ',' enumerator
1920 : /// enumerator:
1921 : /// enumeration-constant
1922 : /// enumeration-constant '=' constant-expression
1923 : /// enumeration-constant:
1924 : /// identifier
1925 : ///
1926 319: void Parser::ParseEnumBody(SourceLocation StartLoc, DeclPtrTy EnumDecl) {
1927 : // Enter the scope of the enum body and start the definition.
1928 319: ParseScope EnumScope(this, Scope::DeclScope);
1929 319: Actions.ActOnTagStartDefinition(CurScope, EnumDecl);
1930 :
1931 319: SourceLocation LBraceLoc = ConsumeBrace();
1932 :
1933 : // C does not allow an empty enumerator-list, C++ does [dcl.enum].
11: branch 1 taken
308: branch 2 taken
3: branch 4 taken
8: branch 5 taken
3: branch 6 taken
316: branch 7 taken
1934 319: if (Tok.is(tok::r_brace) && !getLang().CPlusPlus)
1935 3: Diag(Tok, diag::ext_empty_struct_union_enum) << "enum";
1936 :
1937 319: llvm::SmallVector<DeclPtrTy, 32> EnumConstantDecls;
1938 :
1939 319: DeclPtrTy LastEnumConstDecl;
1940 :
1941 : // Parse the enumerator-list.
939: branch 1 taken
295: branch 2 taken
1234: branch 4 taken
24: branch 5 taken
1942 1553: while (Tok.is(tok::identifier)) {
1943 1234: IdentifierInfo *Ident = Tok.getIdentifierInfo();
1944 1234: SourceLocation IdentLoc = ConsumeToken();
1945 :
1946 1234: SourceLocation EqualLoc;
1947 1234: OwningExprResult AssignedVal(Actions);
948: branch 1 taken
286: branch 2 taken
1948 1234: if (Tok.is(tok::equal)) {
1949 948: EqualLoc = ConsumeToken();
1950 948: AssignedVal = ParseConstantExpression();
2: branch 1 taken
946: branch 2 taken
1951 948: if (AssignedVal.isInvalid())
1952 2: SkipUntil(tok::comma, tok::r_brace, true, true);
1953 : }
1954 :
1955 : // Install the enumerator constant into EnumDecl.
1956 : DeclPtrTy EnumConstDecl = Actions.ActOnEnumConstant(CurScope, EnumDecl,
1957 : LastEnumConstDecl,
1958 : IdentLoc, Ident,
1959 : EqualLoc,
1960 1234: AssignedVal.release());
1961 1234: EnumConstantDecls.push_back(EnumConstDecl);
1962 1234: LastEnumConstDecl = EnumConstDecl;
1963 :
295: branch 1 taken
939: branch 2 taken
1964 1234: if (Tok.isNot(tok::comma))
1965 295: break;
1966 939: SourceLocation CommaLoc = ConsumeToken();
1967 :
13: branch 1 taken
926: branch 2 taken
2: branch 4 taken
11: branch 5 taken
2: branch 7 taken
0: branch 8 not taken
2: branch 9 taken
937: branch 10 taken
1968 939: if (Tok.isNot(tok::identifier) &&
1969 : !(getLang().C99 || getLang().CPlusPlus0x))
1970 : Diag(CommaLoc, diag::ext_enumerator_list_comma)
1971 : << getLang().CPlusPlus
1972 2: << CodeModificationHint::CreateRemoval(CommaLoc);
1973 : }
1974 :
1975 : // Eat the }.
1976 319: SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc);
1977 :
1978 319: AttributeList *Attr = 0;
1979 : // If attributes exist after the identifier list, parse them.
4: branch 1 taken
315: branch 2 taken
1980 319: if (Tok.is(tok::kw___attribute))
1981 4: Attr = ParseGNUAttributes(); // FIXME: where do they do?
1982 :
1983 : Actions.ActOnEnumBody(StartLoc, LBraceLoc, RBraceLoc, EnumDecl,
1984 : EnumConstantDecls.data(), EnumConstantDecls.size(),
1985 319: CurScope, Attr);
1986 :
1987 319: EnumScope.Exit();
1988 319: Actions.ActOnTagFinishDefinition(CurScope, EnumDecl, RBraceLoc);
1989 319: }
1990 :
1991 : /// isTypeSpecifierQualifier - Return true if the current token could be the
1992 : /// start of a type-qualifier-list.
1993 5: bool Parser::isTypeQualifier() const {
5: branch 1 taken
0: branch 2 not taken
1994 5: switch (Tok.getKind()) {
1995 5: default: return false;
1996 : // type-qualifier
1997 : case tok::kw_const:
1998 : case tok::kw_volatile:
1999 : case tok::kw_restrict:
2000 0: return true;
2001 : }
2002 : }
2003 :
2004 : /// isTypeSpecifierQualifier - Return true if the current token could be the
2005 : /// start of a specifier-qualifier-list.
2006 15283: bool Parser::isTypeSpecifierQualifier() {
1875: branch 1 taken
5011: branch 2 taken
0: branch 3 not taken
0: branch 4 not taken
8395: branch 5 taken
2: branch 6 taken
0: branch 7 not taken
2007 15283: switch (Tok.getKind()) {
2008 1875: default: return false;
2009 :
2010 : case tok::identifier: // foo::bar
2: branch 1 taken
5009: branch 2 taken
2011 5011: if (TryAltiVecVectorToken())
2012 2: return true;
2013 : // Fall through.
2014 : case tok::kw_typename: // typename T::type
2015 : // Annotate typenames and C++ scope specifiers. If we get one, just
2016 : // recurse to handle whatever we get.
4196: branch 1 taken
813: branch 2 taken
2017 5009: if (TryAnnotateTypeOrScopeToken())
2018 4196: return isTypeSpecifierQualifier();
2019 : // Otherwise, not a type specifier.
2020 813: return false;
2021 :
2022 : case tok::coloncolon: // ::foo::bar
0: branch 2 not taken
0: branch 3 not taken
0: branch 6 not taken
0: branch 7 not taken
0: branch 8 not taken
0: branch 9 not taken
2023 0: if (NextToken().is(tok::kw_new) || // ::new
2024 : NextToken().is(tok::kw_delete)) // ::delete
2025 0: return false;
2026 :
2027 : // Annotate typenames and C++ scope specifiers. If we get one, just
2028 : // recurse to handle whatever we get.
0: branch 1 not taken
0: branch 2 not taken
2029 0: if (TryAnnotateTypeOrScopeToken())
2030 0: return isTypeSpecifierQualifier();
2031 : // Otherwise, not a type specifier.
2032 0: return false;
2033 :
2034 : // GNU attributes support.
2035 : case tok::kw___attribute:
2036 : // GNU typeof support.
2037 : case tok::kw_typeof:
2038 :
2039 : // type-specifiers
2040 : case tok::kw_short:
2041 : case tok::kw_long:
2042 : case tok::kw_signed:
2043 : case tok::kw_unsigned:
2044 : case tok::kw__Complex:
2045 : case tok::kw__Imaginary:
2046 : case tok::kw_void:
2047 : case tok::kw_char:
2048 : case tok::kw_wchar_t:
2049 : case tok::kw_char16_t:
2050 : case tok::kw_char32_t:
2051 : case tok::kw_int:
2052 : case tok::kw_float:
2053 : case tok::kw_double:
2054 : case tok::kw_bool:
2055 : case tok::kw__Bool:
2056 : case tok::kw__Decimal32:
2057 : case tok::kw__Decimal64:
2058 : case tok::kw__Decimal128:
2059 : case tok::kw___vector:
2060 :
2061 : // struct-or-union-specifier (C99) or class-specifier (C++)
2062 : case tok::kw_class:
2063 : case tok::kw_struct:
2064 : case tok::kw_union:
2065 : // enum-specifier
2066 : case tok::kw_enum:
2067 :
2068 : // type-qualifier
2069 : case tok::kw_const:
2070 : case tok::kw_volatile:
2071 : case tok::kw_restrict:
2072 :
2073 : // typedef-name
2074 : case tok::annot_typename:
2075 8395: return true;
2076 :
2077 : // GNU ObjC bizarre protocol extension: <proto1,proto2> with implicit 'id'.
2078 : case tok::less:
2079 2: return getLang().ObjC1;
2080 :
2081 : case tok::kw___cdecl:
2082 : case tok::kw___stdcall:
2083 : case tok::kw___fastcall:
2084 : case tok::kw___w64:
2085 : case tok::kw___ptr64:
2086 0: return true;
2087 : }
2088 : }
2089 :
2090 : /// isDeclarationSpecifier() - Return true if the current token is part of a
2091 : /// declaration specifier.
2092 18264: bool Parser::isDeclarationSpecifier() {
7239: branch 1 taken
5422: branch 2 taken
0: branch 3 not taken
0: branch 4 not taken
5602: branch 5 taken
1: branch 6 taken
0: branch 7 not taken
2093 18264: switch (Tok.getKind()) {
2094 7239: default: return false;
2095 :
2096 : case tok::identifier: // foo::bar
2097 : // Unfortunate hack to support "Class.factoryMethod" notation.
2536: branch 1 taken
2886: branch 2 taken
189: branch 5 taken
2347: branch 6 taken
189: branch 7 taken
5233: branch 8 taken
2098 5422: if (getLang().ObjC1 && NextToken().is(tok::period))
2099 189: return false;
0: branch 1 not taken
5233: branch 2 taken
2100 5233: if (TryAltiVecVectorToken())
2101 0: return true;
2102 : // Fall through.
2103 :
2104 : case tok::kw_typename: // typename T::type
2105 : // Annotate typenames and C++ scope specifiers. If we get one, just
2106 : // recurse to handle whatever we get.
1484: branch 1 taken
3749: branch 2 taken
2107 5233: if (TryAnnotateTypeOrScopeToken())
2108 1484: return isDeclarationSpecifier();
2109 : // Otherwise, not a declaration specifier.
2110 3749: return false;
2111 : case tok::coloncolon: // ::foo::bar
0: branch 2 not taken
0: branch 3 not taken
0: branch 6 not taken
0: branch 7 not taken
0: branch 8 not taken
0: branch 9 not taken
2112 0: if (NextToken().is(tok::kw_new) || // ::new
2113 : NextToken().is(tok::kw_delete)) // ::delete
2114 0: return false;
2115 :
2116 : // Annotate typenames and C++ scope specifiers. If we get one, just
2117 : // recurse to handle whatever we get.
0: branch 1 not taken
0: branch 2 not taken
2118 0: if (TryAnnotateTypeOrScopeToken())
2119 0: return isDeclarationSpecifier();
2120 : // Otherwise, not a declaration specifier.
2121 0: return false;
2122 :
2123 : // storage-class-specifier
2124 : case tok::kw_typedef:
2125 : case tok::kw_extern:
2126 : case tok::kw___private_extern__:
2127 : case tok::kw_static:
2128 : case tok::kw_auto:
2129 : case tok::kw_register:
2130 : case tok::kw___thread:
2131 :
2132 : // type-specifiers
2133 : case tok::kw_short:
2134 : case tok::kw_long:
2135 : case tok::kw_signed:
2136 : case tok::kw_unsigned:
2137 : case tok::kw__Complex:
2138 : case tok::kw__Imaginary:
2139 : case tok::kw_void:
2140 : case tok::kw_char:
2141 : case tok::kw_wchar_t:
2142 : case tok::kw_char16_t:
2143 : case tok::kw_char32_t:
2144 :
2145 : case tok::kw_int:
2146 : case tok::kw_float:
2147 : case tok::kw_double:
2148 : case tok::kw_bool:
2149 : case tok::kw__Bool:
2150 : case tok::kw__Decimal32:
2151 : case tok::kw__Decimal64:
2152 : case tok::kw__Decimal128:
2153 : case tok::kw___vector:
2154 :
2155 : // struct-or-union-specifier (C99) or class-specifier (C++)
2156 : case tok::kw_class:
2157 : case tok::kw_struct:
2158 : case tok::kw_union:
2159 : // enum-specifier
2160 : case tok::kw_enum:
2161 :
2162 : // type-qualifier
2163 : case tok::kw_const:
2164 : case tok::kw_volatile:
2165 : case tok::kw_restrict:
2166 :
2167 : // function-specifier
2168 : case tok::kw_inline:
2169 : case tok::kw_virtual:
2170 : case tok::kw_explicit:
2171 :
2172 : // typedef-name
2173 : case tok::annot_typename:
2174 :
2175 : // GNU typeof support.
2176 : case tok::kw_typeof:
2177 :
2178 : // GNU attributes.
2179 : case tok::kw___attribute:
2180 5602: return true;
2181 :
2182 : // GNU ObjC bizarre protocol extension: <proto1,proto2> with implicit 'id'.
2183 : case tok::less:
2184 1: return getLang().ObjC1;
2185 :
2186 : case tok::kw___declspec:
2187 : case tok::kw___cdecl:
2188 : case tok::kw___stdcall:
2189 : case tok::kw___fastcall:
2190 : case tok::kw___w64:
2191 : case tok::kw___ptr64:
2192 : case tok::kw___forceinline:
2193 0: return true;
2194 : }
2195 : }
2196 :
2197 799: bool Parser::isConstructorDeclarator() {
2198 799: TentativeParsingAction TPA(*this);
2199 :
2200 : // Parse the C++ scope specifier.
2201 799: CXXScopeSpec SS;
2202 799: ParseOptionalCXXScopeSpecifier(SS, 0, true);
2203 :
2204 : // Parse the constructor name.
19: branch 1 taken
780: branch 2 taken
19: branch 4 taken
0: branch 5 not taken
799: branch 6 taken
0: branch 7 not taken
2205 799: if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id)) {
2206 : // We already know that we have a constructor name; just consume
2207 : // the token.
2208 799: ConsumeToken();
2209 : } else {
2210 0: TPA.Revert();
2211 0: return false;
2212 : }
2213 :
2214 : // Current class name must be followed by a left parentheses.
145: branch 1 taken
654: branch 2 taken
2215 799: if (Tok.isNot(tok::l_paren)) {
2216 145: TPA.Revert();
2217 145: return false;
2218 : }
2219 654: ConsumeParen();
2220 :
2221 : // A right parentheses or ellipsis signals that we have a constructor.
325: branch 1 taken
329: branch 2 taken
1: branch 4 taken
324: branch 5 taken
330: branch 6 taken
324: branch 7 taken
2222 654: if (Tok.is(tok::r_paren) || Tok.is(tok::ellipsis)) {
2223 330: TPA.Revert();
2224 330: return true;
2225 : }
2226 :
2227 : // If we need to, enter the specified scope.
2228 324: DeclaratorScopeObj DeclScopeObj(*this, SS);
21: branch 1 taken
303: branch 2 taken
21: branch 4 taken
0: branch 5 not taken
21: branch 6 taken
303: branch 7 taken
2229 324: if (SS.isSet() && Actions.ShouldEnterDeclaratorScope(CurScope, SS))
2230 21: DeclScopeObj.EnterDeclaratorScope();
2231 :
2232 : // Check whether the next token(s) are part of a declaration
2233 : // specifier, in which case we have the start of a parameter and,
2234 : // therefore, we know that this is a constructor.
2235 324: bool IsConstructor = isDeclarationSpecifier();
2236 324: TPA.Revert();
2237 324: return IsConstructor;
2238 : }
2239 :
2240 : /// ParseTypeQualifierListOpt
2241 : /// type-qualifier-list: [C99 6.7.5]
2242 : /// type-qualifier
2243 : /// [GNU] attributes [ only if AttributesAllowed=true ]
2244 : /// type-qualifier-list type-qualifier
2245 : /// [GNU] type-qualifier-list attributes [ only if AttributesAllowed=true ]
2246 : /// [C++0x] attribute-specifier[opt] is allowed before cv-qualifier-seq
2247 : /// if CXX0XAttributesAllowed = true
2248 : ///
2249 : void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, bool GNUAttributesAllowed,
2250 24649: bool CXX0XAttributesAllowed) {
1612: branch 1 taken
23037: branch 2 taken
3: branch 4 taken
1609: branch 5 taken
3: branch 6 taken
24646: branch 7 taken
2251 24649: if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
2252 3: SourceLocation Loc = Tok.getLocation();
2253 3: CXX0XAttributeList Attr = ParseCXX0XAttributes();
2: branch 0 taken
1: branch 1 taken
2254 3: if (CXX0XAttributesAllowed)
2255 2: DS.AddAttributes(Attr.AttrList);
2256 : else
2257 1: Diag(Loc, diag::err_attributes_not_allowed);
2258 : }
2259 :
2260 1033: while (1) {
2261 25682: bool isInvalid = false;
2262 25682: const char *PrevSpec = 0;
2263 25682: unsigned DiagID = 0;
2264 25682: SourceLocation Loc = Tok.getLocation();
2265 :
319: branch 1 taken
47: branch 2 taken
634: branch 3 taken
5: branch 4 taken
75: branch 5 taken
24602: branch 6 taken
2266 25682: switch (Tok.getKind()) {
2267 : case tok::kw_const:
2268 : isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , Loc, PrevSpec, DiagID,
2269 319: getLang());
2270 319: break;
2271 : case tok::kw_volatile:
2272 : isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID,
2273 47: getLang());
2274 47: break;
2275 : case tok::kw_restrict:
2276 : isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID,
2277 634: getLang());
2278 634: break;
2279 : case tok::kw___w64:
2280 : case tok::kw___ptr64:
2281 : case tok::kw___cdecl:
2282 : case tok::kw___stdcall:
2283 : case tok::kw___fastcall:
5: branch 0 taken
0: branch 1 not taken
2284 5: if (GNUAttributesAllowed) {
2285 5: DS.AddAttributes(ParseMicrosoftTypeAttributes());
2286 5: continue;
2287 : }
2288 0: goto DoneWithTypeQuals;
2289 : case tok::kw___attribute:
28: branch 0 taken
47: branch 1 taken
2290 75: if (GNUAttributesAllowed) {
2291 28: DS.AddAttributes(ParseGNUAttributes());
2292 28: continue; // do *not* consume the next token!
2293 : }
2294 : // otherwise, FALL THROUGH!
2295 : default:
2296 24649: DoneWithTypeQuals:
2297 : // If this is not a type-qualifier token, we're done reading type
2298 : // qualifiers. First verify that DeclSpec's are consistent.
2299 24649: DS.Finish(Diags, PP);
2300 : return;
2301 : }
2302 :
2303 : // If the specifier combination wasn't legal, issue a diagnostic.
0: branch 0 not taken
1000: branch 1 taken
2304 1000: if (isInvalid) {
0: branch 0 not taken
0: branch 1 not taken
2305 0: assert(PrevSpec && "Method did not return previous specifier!");
2306 0: Diag(Tok, DiagID) << PrevSpec;
2307 : }
2308 1000: ConsumeToken();
2309 : }
2310 : }
2311 :
2312 :
2313 : /// ParseDeclarator - Parse and verify a newly-initialized declarator.
2314 : ///
2315 63892: void Parser::ParseDeclarator(Declarator &D) {
2316 : /// This implements the 'declarator' production in the C grammar, then checks
2317 : /// for well-formedness and issues diagnostics.
2318 63892: ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);
2319 63892: }
2320 :
2321 : /// ParseDeclaratorInternal - Parse a C or C++ declarator. The direct-declarator
2322 : /// is parsed by the function passed to it. Pass null, and the direct-declarator
2323 : /// isn't parsed at all, making this function effectively parse the C++
2324 : /// ptr-operator production.
2325 : ///
2326 : /// declarator: [C99 6.7.5] [C++ 8p4, dcl.decl]
2327 : /// [C] pointer[opt] direct-declarator
2328 : /// [C++] direct-declarator
2329 : /// [C++] ptr-operator declarator
2330 : ///
2331 : /// pointer: [C99 6.7.5]
2332 : /// '*' type-qualifier-list[opt]
2333 : /// '*' type-qualifier-list[opt] pointer
2334 : ///
2335 : /// ptr-operator:
2336 : /// '*' cv-qualifier-seq[opt]
2337 : /// '&'
2338 : /// [C++0x] '&&'
2339 : /// [GNU] '&' restrict[opt] attributes[opt]
2340 : /// [GNU?] '&&' restrict[opt] attributes[opt]
2341 : /// '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt]
2342 : void Parser::ParseDeclaratorInternal(Declarator &D,
2343 82058: DirectDeclParseFunction DirectDeclParser) {
808: branch 1 taken
81250: branch 2 taken
2344 82058: if (Diags.hasAllExtensionsSilenced())
2345 808: D.setExtension();
2346 : // C++ member pointers start with a '::' or a nested-name.
2347 : // Member pointers get special handling, since there's no place for the
2348 : // scope spec in the generic path below.
32360: branch 1 taken
49698: branch 2 taken
32359: branch 4 taken
1: branch 5 taken
16532: branch 7 taken
15827: branch 8 taken
657: branch 10 taken
15875: branch 11 taken
16485: branch 12 taken
65573: branch 13 taken
2349 82058: if (getLang().CPlusPlus &&
2350 : (Tok.is(tok::coloncolon) || Tok.is(tok::identifier) ||
2351 : Tok.is(tok::annot_cxxscope))) {
2352 16485: CXXScopeSpec SS;
762: branch 1 taken
15723: branch 2 taken
2353 16485: if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true)) {
470: branch 1 taken
292: branch 2 taken
2354 762: if (Tok.isNot(tok::star)) {
2355 : // The scope spec really belongs to the direct-declarator.
2356 470: D.getCXXScopeSpec() = SS;
470: branch 0 taken
0: branch 1 not taken
2357 470: if (DirectDeclParser)
0: branch 0 not taken
470: branch 1 taken
2358 470: (this->*DirectDeclParser)(D);
2359 470: return;
2360 : }
2361 :
2362 292: SourceLocation Loc = ConsumeToken();
2363 292: D.SetRangeEnd(Loc);
2364 292: DeclSpec DS;
2365 292: ParseTypeQualifierListOpt(DS);
2366 292: D.ExtendWithDeclSpec(DS);
2367 :
2368 : // Recurse to parse whatever is left.
2369 292: ParseDeclaratorInternal(D, DirectDeclParser);
2370 :
2371 : // Sema will have to catch (syntactically invalid) pointers into global
2372 : // scope. It has to catch pointers into namespace scope anyway.
2373 : D.AddTypeInfo(DeclaratorChunk::getMemberPointer(SS,DS.getTypeQualifiers(),
2374 : Loc, DS.TakeAttributes()),
2375 292: /* Don't replace range end. */SourceLocation());
2376 292: return;
2377 : }
2378 : }
2379 :
2380 81296: tok::TokenKind Kind = Tok.getKind();
2381 : // Not a pointer, C++ reference, or block.
66630: branch 0 taken
14666: branch 1 taken
66394: branch 2 taken
236: branch 3 taken
1564: branch 4 taken
64830: branch 5 taken
0: branch 7 not taken
1564: branch 8 taken
38: branch 9 taken
64792: branch 10 taken
0: branch 12 not taken
38: branch 13 taken
64792: branch 14 taken
16504: branch 15 taken
2382 81296: if (Kind != tok::star && Kind != tok::caret &&
2383 : (Kind != tok::amp || !getLang().CPlusPlus) &&
2384 : // We parse rvalue refs in C++03, because otherwise the errors are scary.
2385 : (Kind != tok::ampamp || !getLang().CPlusPlus)) {
64512: branch 0 taken
280: branch 1 taken
2386 64792: if (DirectDeclParser)
0: branch 0 not taken
64512: branch 1 taken
2387 64512: (this->*DirectDeclParser)(D);
2388 64792: return;
2389 : }
2390 :
2391 : // Otherwise, '*' -> pointer, '^' -> block, '&' -> lvalue reference,
2392 : // '&&' -> rvalue reference
2393 16504: SourceLocation Loc = ConsumeToken(); // Eat the *, ^, & or &&.
2394 16504: D.SetRangeEnd(Loc);
2395 :
1838: branch 0 taken
14666: branch 1 taken
236: branch 2 taken
1602: branch 3 taken
2396 31406: if (Kind == tok::star || Kind == tok::caret) {
2397 : // Is a pointer.
2398 14902: DeclSpec DS;
2399 :
2400 14902: ParseTypeQualifierListOpt(DS);
2401 14902: D.ExtendWithDeclSpec(DS);
2402 :
2403 : // Recursively parse the declarator.
2404 14902: ParseDeclaratorInternal(D, DirectDeclParser);
14666: branch 0 taken
236: branch 1 taken
2405 14902: if (Kind == tok::star)
2406 : // Remember that we parsed a pointer type, and remember the type-quals.
2407 : D.AddTypeInfo(DeclaratorChunk::getPointer(DS.getTypeQualifiers(), Loc,
2408 : DS.TakeAttributes()),
2409 14666: SourceLocation());
2410 : else
2411 : // Remember that we parsed a Block type, and remember the type-quals.
2412 : D.AddTypeInfo(DeclaratorChunk::getBlockPointer(DS.getTypeQualifiers(),
2413 : Loc, DS.TakeAttributes()),
2414 236: SourceLocation());
2415 : } else {
2416 : // Is a reference
2417 1602: DeclSpec DS;
2418 :
2419 : // Complain about rvalue references in C++03, but then go on and build
2420 : // the declarator.
38: branch 0 taken
1564: branch 1 taken
1: branch 3 taken
37: branch 4 taken
1: branch 5 taken
1601: branch 6 taken
2421 1602: if (Kind == tok::ampamp && !getLang().CPlusPlus0x)
2422 1: Diag(Loc, diag::err_rvalue_reference);
2423 :
2424 : // C++ 8.3.2p1: cv-qualified references are ill-formed except when the
2425 : // cv-qualifiers are introduced through the use of a typedef or of a
2426 : // template type argument, in which case the cv-qualifiers are ignored.
2427 : //
2428 : // [GNU] Retricted references are allowed.
2429 : // [GNU] Attributes on references are allowed.
2430 : // [C++0x] Attributes on references are not allowed.
2431 1602: ParseTypeQualifierListOpt(DS, true, false);
2432 1602: D.ExtendWithDeclSpec(DS);
2433 :
4: branch 1 taken
1598: branch 2 taken
2434 1602: if (DS.getTypeQualifiers() != DeclSpec::TQ_unspecified) {
3: branch 1 taken
1: branch 2 taken
2435 4: if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
2436 : Diag(DS.getConstSpecLoc(),
2437 3: diag::err_invalid_reference_qualifier_application) << "const";
2: branch 1 taken
2: branch 2 taken
2438 4: if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile)
2439 : Diag(DS.getVolatileSpecLoc(),
2440 2: diag::err_invalid_reference_qualifier_application) << "volatile";
2441 : }
2442 :
2443 : // Recursively parse the declarator.
2444 1602: ParseDeclaratorInternal(D, DirectDeclParser);
2445 :
298: branch 1 taken
1304: branch 2 taken
2446 1602: if (D.getNumTypeObjects() > 0) {
2447 : // C++ [dcl.ref]p4: There shall be no references to references.
2448 298: DeclaratorChunk& InnerChunk = D.getTypeObject(D.getNumTypeObjects() - 1);
3: branch 0 taken
295: branch 1 taken
2449 298: if (InnerChunk.Kind == DeclaratorChunk::Reference) {
2: branch 1 taken
1: branch 2 taken
2450 3: if (const IdentifierInfo *II = D.getIdentifier())
2451 : Diag(InnerChunk.Loc, diag::err_illegal_decl_reference_to_reference)
2452 2: << II;
2453 : else
2454 : Diag(InnerChunk.Loc, diag::err_illegal_decl_reference_to_reference)
2455 1: << "type name";
2456 :
2457 : // Once we've complained about the reference-to-reference, we
2458 : // can go ahead and build the (technically ill-formed)
2459 : // declarator: reference collapsing will take care of it.
2460 : }
2461 : }
2462 :
2463 : // Remember that we parsed a reference type. It doesn't have type-quals.
2464 : D.AddTypeInfo(DeclaratorChunk::getReference(DS.getTypeQualifiers(), Loc,
2465 : DS.TakeAttributes(),
2466 : Kind == tok::amp),
2467 1602: SourceLocation());
2468 : }
2469 : }
2470 :
2471 : /// ParseDirectDeclarator
2472 : /// direct-declarator: [C99 6.7.5]
2473 : /// [C99] identifier
2474 : /// '(' declarator ')'
2475 : /// [GNU] '(' attributes declarator ')'
2476 : /// [C90] direct-declarator '[' constant-expression[opt] ']'
2477 : /// [C99] direct-declarator '[' type-qual-list[opt] assignment-expr[opt] ']'
2478 : /// [C99] direct-declarator '[' 'static' type-qual-list[opt] assign-expr ']'
2479 : /// [C99] direct-declarator '[' type-qual-list 'static' assignment-expr ']'
2480 : /// [C99] direct-declarator '[' type-qual-list[opt] '*' ']'
2481 : /// direct-declarator '(' parameter-type-list ')'
2482 : /// direct-declarator '(' identifier-list[opt] ')'
2483 : /// [GNU] direct-declarator '(' parameter-forward-declarations
2484 : /// parameter-type-list[opt] ')'
2485 : /// [C++] direct-declarator '(' parameter-declaration-clause ')'
2486 : /// cv-qualifier-seq[opt] exception-specification[opt]
2487 : /// [C++] declarator-id
2488 : ///
2489 : /// declarator-id: [C++ 8]
2490 : /// id-expression
2491 : /// '::'[opt] nested-name-specifier[opt] type-name
2492 : ///
2493 : /// id-expression: [C++ 5.1]
2494 : /// unqualified-id
2495 : /// qualified-id
2496 : ///
2497 : /// unqualified-id: [C++ 5.1]
2498 : /// identifier
2499 : /// operator-function-id
2500 : /// conversion-function-id
2501 : /// '~' class-name
2502 : /// template-id
2503 : ///
2504 64877: void Parser::ParseDirectDeclarator(Declarator &D) {
2505 64877: DeclaratorScopeObj DeclScopeObj(*this, D.getCXXScopeSpec());
2506 :
24975: branch 1 taken
39902: branch 2 taken
19640: branch 4 taken
5335: branch 5 taken
19640: branch 6 taken
45237: branch 7 taken
2507 64877: if (getLang().CPlusPlus && D.mayHaveIdentifier()) {
2508 : // ParseDeclaratorInternal might already have parsed the scope.
2509 : bool afterCXXScope = D.getCXXScopeSpec().isSet() ||
2510 : ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), /*ObjectType=*/0,
19170: branch 2 taken
470: branch 3 taken
0: branch 6 not taken
19170: branch 7 taken
2511 19640: true);
470: branch 0 taken
19170: branch 1 taken
2512 19640: if (afterCXXScope) {
466: branch 2 taken
4: branch 3 taken
2513 470: if (Actions.ShouldEnterDeclaratorScope(CurScope, D.getCXXScopeSpec()))
2514 : // Change the declaration context for name lookup, until this function
2515 : // is exited (and the declarator has been parsed).
2516 466: DeclScopeObj.EnterDeclaratorScope();
2517 : }
2518 :
3515: branch 1 taken
16125: branch 2 taken
2959: branch 4 taken
556: branch 5 taken
2884: branch 7 taken
75: branch 8 taken
186: branch 10 taken
2698: branch 11 taken
16942: branch 12 taken
2698: branch 13 taken
2519 19640: if (Tok.is(tok::identifier) || Tok.is(tok::kw_operator) ||
2520 : Tok.is(tok::annot_template_id) || Tok.is(tok::tilde)) {
2521 : // We found something that indicates the start of an unqualified-id.
2522 : // Parse that unqualified-id.
2523 : bool AllowConstructorName
2524 : = ((D.getCXXScopeSpec().isSet() &&
2525 : D.getContext() == Declarator::FileContext) ||
2526 : (!D.getCXXScopeSpec().isSet() &&
2527 : D.getContext() == Declarator::MemberContext)) &&
466: branch 2 taken
16476: branch 3 taken
14: branch 5 taken
452: branch 6 taken
16476: branch 9 taken
14: branch 10 taken
4684: branch 12 taken
11792: branch 13 taken
1095: branch 16 taken
4041: branch 17 taken
2528 16942: !D.getDeclSpec().hasTypeSpecifier();
4: branch 3 taken
16938: branch 4 taken
2529 16942: if (ParseUnqualifiedId(D.getCXXScopeSpec(),
2530 : /*EnteringContext=*/true,
2531 : /*AllowDestructorName=*/true,
2532 : AllowConstructorName,
2533 : /*ObjectType=*/0,
2534 : D.getName())) {
2535 4: D.SetIdentifier(0, Tok.getLocation());
2536 4: D.setInvalidType(true);
2537 : } else {
2538 : // Parsed the unqualified-id; update range information and move along.
0: branch 3 not taken
16938: branch 4 taken
2539 16938: if (D.getSourceRange().getBegin().isInvalid())
2540 0: D.SetRangeBegin(D.getName().getSourceRange().getBegin());
2541 16938: D.SetRangeEnd(D.getName().getSourceRange().getEnd());
2542 : }
2543 16942: goto PastIdentifier;
2544 : }
29212: branch 1 taken
16025: branch 2 taken
29209: branch 4 taken
3: branch 5 taken
29209: branch 6 taken
16028: branch 7 taken
2545 45237: } else if (Tok.is(tok::identifier) && D.mayHaveIdentifier()) {
2546 : assert(!getLang().CPlusPlus &&
29209: branch 1 taken
0: branch 2 not taken
2547 29209: "There's a C++-specific check for tok::identifier above");
29209: branch 1 taken
0: branch 2 not taken
2548 29209: assert(Tok.getIdentifierInfo() && "Not an identifier?");
2549 29209: D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
2550 29209: ConsumeToken();
2551 29209: goto PastIdentifier;
2552 : }
2553 :
1063: branch 1 taken
17663: branch 2 taken
2554 18726: if (Tok.is(tok::l_paren)) {
2555 : // direct-declarator: '(' declarator ')'
2556 : // direct-declarator: '(' attributes declarator ')'
2557 : // Example: 'char (*X)' or 'int (*XX)(void)'
2558 1063: ParseParenDeclarator(D);
2559 :
2560 : // If the declarator was parenthesized, we entered the declarator
2561 : // scope when parsing the parenthesized declarator, then exited
2562 : // the scope already. Re-enter the scope, if we need to.
9: branch 2 taken
1054: branch 3 taken
2563 1063: if (D.getCXXScopeSpec().isSet()) {
9: branch 2 taken
0: branch 3 not taken
2564 9: if (Actions.ShouldEnterDeclaratorScope(CurScope, D.getCXXScopeSpec()))
2565 : // Change the declaration context for name lookup, until this function
2566 : // is exited (and the declarator has been parsed).
2567 9: DeclScopeObj.EnterDeclaratorScope();
2568 : }
17630: branch 1 taken
33: branch 2 taken
2569 17663: } else if (D.mayOmitIdentifier()) {
2570 : // This could be something simple like "int" (in which case the declarator
2571 : // portion is empty), if an abstract-declarator is allowed.
2572 17630: D.SetIdentifier(0, Tok.getLocation());
2573 : } else {
10: branch 1 taken
23: branch 2 taken
2574 33: if (D.getContext() == Declarator::MemberContext)
2575 : Diag(Tok, diag::err_expected_member_name_or_semi)
2576 10: << D.getDeclSpec().getSourceRange();
13: branch 1 taken
10: branch 2 taken
2577 23: else if (getLang().CPlusPlus)
2578 13: Diag(Tok, diag::err_expected_unqualified_id) << getLang().CPlusPlus;
2579 : else
2580 10: Diag(Tok, diag::err_expected_ident_lparen);
2581 33: D.SetIdentifier(0, Tok.getLocation());
2582 33: D.setInvalidType(true);
2583 : }
2584 :
2585 64877: PastIdentifier:
2586 : assert(D.isPastIdentifier() &&
64877: branch 1 taken
0: branch 2 not taken
2587 64877: "Haven't past the location of the identifier yet?");
2588 :
2589 : // Don't parse attributes unless we have an identifier.
45460: branch 1 taken
19417: branch 2 taken
15856: branch 4 taken
29604: branch 5 taken
13: branch 7 taken
15843: branch 8 taken
13: branch 9 taken
64864: branch 10 taken
2590 110337: if (D.getIdentifier() && getLang().CPlusPlus
2591 : && isCXX0XAttributeSpecifier(true)) {
2592 13: SourceLocation AttrEndLoc;
2593 13: CXX0XAttributeList Attr = ParseCXX0XAttributes();
2594 13: D.AddAttributes(Attr.AttrList, AttrEndLoc);
2595 : }
2596 :
2597 16726: while (1) {
14518: branch 1 taken
67085: branch 2 taken
2598 81603: if (Tok.is(tok::l_paren)) {
2599 : // The paren may be part of a C++ direct initializer, eg. "int x(1);".
2600 : // In such a case, check if we actually have a function declarator; if it
2601 : // is not, the declarator has been fully parsed.
7028: branch 1 taken
7490: branch 2 taken
4075: branch 4 taken
2953: branch 5 taken
4075: branch 6 taken
10443: branch 7 taken
2602 14518: if (getLang().CPlusPlus && D.mayBeFollowedByCXXDirectInit()) {
2603 : // When not in file scope, warn for ambiguous function declarators, just
2604 : // in case the author intended it as a variable definition.
2605 4075: bool warnIfAmbiguous = D.getContext() != Declarator::FileContext;
3966: branch 1 taken
109: branch 2 taken
2606 4075: if (!isCXXFunctionDeclarator(warnIfAmbiguous))
2607 109: break;
2608 : }
2609 14409: ParseFunctionDeclarator(ConsumeParen(), D);
64768: branch 1 taken
2317: branch 2 taken
2610 67085: } else if (Tok.is(tok::l_square)) {
2611 2317: ParseBracketDeclarator(D);
2612 : } else {
2613 64768: break;
2614 : }
2615 64877: }
2616 64877: }
2617 :
2618 : /// ParseParenDeclarator - We parsed the declarator D up to a paren. This is
2619 : /// only called before the identifier, so these are most likely just grouping
2620 : /// parens for precedence. If we find that these are actually function
2621 : /// parameter parens in an abstract-declarator, we call ParseFunctionDeclarator.
2622 : ///
2623 : /// direct-declarator:
2624 : /// '(' declarator ')'
2625 : /// [GNU] '(' attributes declarator ')'
2626 : /// direct-declarator '(' parameter-type-list ')'
2627 : /// direct-declarator '(' identifier-list[opt] ')'
2628 : /// [GNU] direct-declarator '(' parameter-forward-declarations
2629 : /// parameter-type-list[opt] ')'
2630 : ///
2631 1122: void Parser::ParseParenDeclarator(Declarator &D) {
2632 1122: SourceLocation StartLoc = ConsumeParen();
1122: branch 1 taken
0: branch 2 not taken
2633 1122: assert(!D.isPastIdentifier() && "Should be called before passing identifier");
2634 :
2635 : // Eat any attributes before we look at whether this is a grouping or function
2636 : // declarator paren. If this is a grouping paren, the attribute applies to
2637 : // the type being built up, for example:
2638 : // int (__attribute__(()) *x)(long y)
2639 : // If this ends up not being a grouping paren, the attribute applies to the
2640 : // first argument, for example:
2641 : // int (__attribute__(()) int x)
2642 : // In either case, we need to eat any attributes to be able to determine what
2643 : // sort of paren this is.
2644 : //
2645 1122: AttributeList *AttrList = 0;
2646 1122: bool RequiresArg = false;
12: branch 1 taken
1110: branch 2 taken
2647 1122: if (Tok.is(tok::kw___attribute)) {
2648 12: AttrList = ParseGNUAttributes();
2649 :
2650 : // We require that the argument list (if this is a non-grouping paren) be
2651 : // present even if the attribute list was empty.
2652 12: RequiresArg = true;
2653 : }
2654 : // Eat any Microsoft extensions.
1121: branch 1 taken
1: branch 2 taken
1120: branch 4 taken
1: branch 5 taken
1120: branch 7 taken
0: branch 8 not taken
1120: branch 10 taken
0: branch 11 not taken
0: branch 13 not taken
1120: branch 14 taken
2: branch 15 taken
1120: branch 16 taken
2655 1122: if (Tok.is(tok::kw___cdecl) || Tok.is(tok::kw___stdcall) ||
2656 : Tok.is(tok::kw___fastcall) || Tok.is(tok::kw___w64) ||
2657 : Tok.is(tok::kw___ptr64)) {
2658 2: AttrList = ParseMicrosoftTypeAttributes(AttrList);
2659 : }
2660 :
2661 : // If we haven't past the identifier yet (or where the identifier would be
2662 : // stored, if this is an abstract declarator), then this is probably just
2663 : // grouping parens. However, if this could be an abstract-declarator, then
2664 : // this could also be the start of function arguments (consider 'void()').
2665 : bool isGrouping;
2666 :
613: branch 1 taken
509: branch 2 taken
2667 1122: if (!D.mayOmitIdentifier()) {
2668 : // If this can't be an abstract-declarator, this *must* be a grouping
2669 : // paren, because we haven't seen the identifier yet.
2670 613: isGrouping = true;
490: branch 1 taken
19: branch 2 taken
265: branch 4 taken
225: branch 5 taken
264: branch 7 taken
1: branch 8 taken
117: branch 10 taken
372: branch 11 taken
137: branch 12 taken
372: branch 13 taken
2671 509: } else if (Tok.is(tok::r_paren) || // 'int()' is a function.
2672 : (getLang().CPlusPlus && Tok.is(tok::ellipsis)) || // C++ int(...)
2673 : isDeclarationSpecifier()) { // 'int(int)' is a function.
2674 : // This handles C99 6.7.5.3p11: in "typedef int X; void foo(X)", X is
2675 : // considered to be a type, not a K&R identifier-list.
2676 137: isGrouping = false;
2677 : } else {
2678 : // Otherwise, this is a grouping paren, e.g. 'int (*X)' or 'int(X)'.
2679 372: isGrouping = true;
2680 : }
2681 :
2682 : // If this is a grouping paren, handle:
2683 : // direct-declarator: '(' declarator ')'
2684 : // direct-declarator: '(' attributes declarator ')'
985: branch 0 taken
137: branch 1 taken
2685 1122: if (isGrouping) {
2686 985: bool hadGroupingParens = D.hasGroupingParens();
2687 985: D.setGroupingParens(true);
12: branch 0 taken
973: branch 1 taken
2688 985: if (AttrList)
2689 12: D.AddAttributes(AttrList, SourceLocation());
2690 :
2691 985: ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);
2692 : // Match the ')'.
2693 985: SourceLocation Loc = MatchRHSPunctuation(tok::r_paren, StartLoc);
2694 :
2695 985: D.setGroupingParens(hadGroupingParens);
2696 985: D.SetRangeEnd(Loc);
2697 985: return;
2698 : }
2699 :
2700 : // Okay, if this wasn't a grouping paren, it must be the start of a function
2701 : // argument list. Recognize that this declarator will never have an
2702 : // identifier (and remember where it would have been), then call into
2703 : // ParseFunctionDeclarator to handle of argument list.
2704 137: D.SetIdentifier(0, Tok.getLocation());
2705 :
2706 137: ParseFunctionDeclarator(StartLoc, D, AttrList, RequiresArg);
2707 : }
2708 :
2709 : /// ParseFunctionDeclarator - We are after the identifier and have parsed the
2710 : /// declarator D up to a paren, which indicates that we are parsing function
2711 : /// arguments.
2712 : ///
2713 : /// If AttrList is non-null, then the caller parsed those arguments immediately
2714 : /// after the open paren - they should be considered to be the first argument of
2715 : /// a parameter. If RequiresArg is true, then the first argument of the
2716 : /// function is required to be present and required to not be an identifier
2717 : /// list.
2718 : ///
2719 : /// This method also handles this portion of the grammar:
2720 : /// parameter-type-list: [C99 6.7.5]
2721 : /// parameter-list
2722 : /// parameter-list ',' '...'
2723 : /// [C++] parameter-list '...'
2724 : ///
2725 : /// parameter-list: [C99 6.7.5]
2726 : /// parameter-declaration
2727 : /// parameter-list ',' parameter-declaration
2728 : ///
2729 : /// parameter-declaration: [C99 6.7.5]
2730 : /// declaration-specifiers declarator
2731 : /// [C++] declaration-specifiers declarator '=' assignment-expression
2732 : /// [GNU] declaration-specifiers declarator attributes
2733 : /// declaration-specifiers abstract-declarator[opt]
2734 : /// [C++] declaration-specifiers abstract-declarator[opt]
2735 : /// '=' assignment-expression
2736 : /// [GNU] declaration-specifiers abstract-declarator[opt] attributes
2737 : ///
2738 : /// For C++, after the parameter-list, it also parses "cv-qualifier-seq[opt]"
2739 : /// and "exception-specification[opt]".
2740 : ///
2741 : void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
2742 : AttributeList *AttrList,
2743 14546: bool RequiresArg) {
2744 : // lparen is already consumed!
14546: branch 1 taken
0: branch 2 not taken
2745 14546: assert(D.isPastIdentifier() && "Should not call before identifier!");
2746 :
2747 : // This parameter list may be empty.
5249: branch 1 taken
9297: branch 2 taken
2748 14546: if (Tok.is(tok::r_paren)) {
0: branch 0 not taken
5249: branch 1 taken
2749 5249: if (RequiresArg) {
2750 0: Diag(Tok, diag::err_argument_required_after_attribute);
0: branch 0 not taken
0: branch 1 not taken
2751 0: delete AttrList;
2752 : }
2753 :
2754 5249: SourceLocation RParenLoc = ConsumeParen(); // Eat the closing ')'.
2755 5249: SourceLocation EndLoc = RParenLoc;
2756 :
2757 : // cv-qualifier-seq[opt].
2758 5249: DeclSpec DS;
2759 5249: bool hasExceptionSpec = false;
2760 5249: SourceLocation ThrowLoc;
2761 5249: bool hasAnyExceptionSpec = false;
2762 5249: llvm::SmallVector<TypeTy*, 2> Exceptions;
2763 5249: llvm::SmallVector<SourceRange, 2> ExceptionRanges;
3208: branch 1 taken
2041: branch 2 taken
2764 5249: if (getLang().CPlusPlus) {
2765 3208: ParseTypeQualifierListOpt(DS, false /*no attributes*/);
0: branch 3 not taken
3208: branch 4 taken
2766 3208: if (!DS.getSourceRange().getEnd().isInvalid())
2767 0: EndLoc = DS.getSourceRange().getEnd();
2768 :
2769 : // Parse exception-specification[opt].
96: branch 1 taken
3112: branch 2 taken
2770 3208: if (Tok.is(tok::kw_throw)) {
2771 96: hasExceptionSpec = true;
2772 96: ThrowLoc = Tok.getLocation();
2773 : ParseExceptionSpecification(EndLoc, Exceptions, ExceptionRanges,
2774 96: hasAnyExceptionSpec);
2775 : assert(Exceptions.size() == ExceptionRanges.size() &&
96: branch 2 taken
0: branch 3 not taken
2776 96: "Produced different number of exception types and ranges.");
2777 : }
2778 : }
2779 :
2780 : // Remember that we parsed a function type, and remember the attributes.
2781 : // int() -> no prototype, no '...'.
2782 : D.AddTypeInfo(DeclaratorChunk::getFunction(/*prototype*/getLang().CPlusPlus,
2783 : /*variadic*/ false,
2784 : SourceLocation(),
2785 : /*arglist*/ 0, 0,
2786 : DS.getTypeQualifiers(),
2787 : hasExceptionSpec, ThrowLoc,
2788 : hasAnyExceptionSpec,
2789 : Exceptions.data(),
2790 : ExceptionRanges.data(),
2791 : Exceptions.size(),
2792 : LParenLoc, RParenLoc, D),
2793 5249: EndLoc);
2794 5249: return;
2795 : }
2796 :
2797 : // Alternatively, this parameter list may be an identifier list form for a
2798 : // K&R-style function: void foo(a,b,c)
5538: branch 1 taken
3759: branch 2 taken
1905: branch 4 taken
3633: branch 5 taken
1904: branch 7 taken
1: branch 8 taken
1904: branch 9 taken
7393: branch 10 taken
2799 9297: if (!getLang().CPlusPlus && Tok.is(tok::identifier)
2800 : && !TryAltiVecVectorToken()) {
57: branch 1 taken
1847: branch 2 taken
2801 1904: if (!TryAnnotateTypeOrScopeToken()) {
2802 : // K&R identifier lists can't have typedefs as identifiers, per
2803 : // C99 6.7.5.3p11.
0: branch 0 not taken
57: branch 1 taken
2804 57: if (RequiresArg) {
2805 0: Diag(Tok, diag::err_argument_required_after_attribute);
0: branch 0 not taken
0: branch 1 not taken
2806 0: delete AttrList;
2807 : }
2808 : // Identifier list. Note that '(' identifier-list ')' is only allowed for
2809 : // normal declarators, not for abstract-declarators.
2810 57: return ParseFunctionDeclaratorIdentifierList(LParenLoc, D);
2811 : }
2812 : }
2813 :
2814 : // Finally, a normal, non-empty parameter type list.
2815 :
2816 : // Build up an array of information about the parsed arguments.
2817 9240: llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
2818 :
2819 : // Enter function-declaration scope, limiting any declarators to the
2820 : // function prototype scope, including parameter declarators.
2821 : ParseScope PrototypeScope(this,
2822 9240: Scope::FunctionPrototypeScope|Scope::DeclScope);
2823 :
2824 9240: bool IsVariadic = false;
2825 9240: SourceLocation EllipsisLoc;
4933: branch 1 taken
8934: branch 2 taken
4933: branch 4 taken
8934: branch 5 taken
2826 13867: while (1) {
306: branch 1 taken
13867: branch 2 taken
2827 14173: if (Tok.is(tok::ellipsis)) {
2828 306: IsVariadic = true;
2829 306: EllipsisLoc = ConsumeToken(); // Consume the ellipsis.
2830 306: break;
2831 : }
2832 :
2833 13867: SourceLocation DSStart = Tok.getLocation();
2834 :
2835 : // Parse the declaration-specifiers.
2836 : // Just use the ParsingDeclaration "scope" of the declarator.
2837 13867: DeclSpec DS;
2838 :
2839 : // If the caller parsed attributes for the first argument, add them now.
0: branch 0 not taken
13867: branch 1 taken
2840 13867: if (AttrList) {
2841 0: DS.AddAttributes(AttrList);
2842 0: AttrList = 0; // Only apply the attributes to the first parameter.
2843 : }
2844 13867: ParseDeclarationSpecifiers(DS);
2845 :
2846 : // Parse the declarator. This is "PrototypeContext", because we must
2847 : // accept either 'declarator' or 'abstract-declarator' here.
2848 13867: Declarator ParmDecl(DS, Declarator::PrototypeContext);
2849 13867: ParseDeclarator(ParmDecl);
2850 :
2851 : // Parse GNU attributes, if present.
3: branch 1 taken
13864: branch 2 taken
2852 13867: if (Tok.is(tok::kw___attribute)) {
2853 3: SourceLocation Loc;
2854 3: AttributeList *AttrList = ParseGNUAttributes(&Loc);
2855 3: ParmDecl.AddAttributes(AttrList, Loc);
2856 : }
2857 :
2858 : // Remember this parsed parameter in ParamInfo.
2859 13867: IdentifierInfo *ParmII = ParmDecl.getIdentifier();
2860 :
2861 : // DefArgToks is used when the parsing of default arguments needs
2862 : // to be delayed.
2863 13867: CachedTokens *DefArgToks = 0;
2864 :
2865 : // If no parameter was specified, verify that *something* was specified,
2866 : // otherwise we have a missing type and identifier.
18: branch 1 taken
13849: branch 2 taken
7: branch 4 taken
11: branch 5 taken
7: branch 7 taken
0: branch 8 not taken
7: branch 9 taken
13860: branch 10 taken
2867 13867: if (DS.isEmpty() && ParmDecl.getIdentifier() == 0 &&
2868 : ParmDecl.getNumTypeObjects() == 0) {
2869 : // Completely missing, emit error.
2870 7: Diag(DSStart, diag::err_missing_param);
2871 : } else {
2872 : // Otherwise, we have something. Add it and let semantic analysis try
2873 : // to grok it and add the result to the ParamInfo we are building.
2874 :
2875 : // Inform the actions module about the parameter declarator, so it gets
2876 : // added to the current scope.
2877 13860: DeclPtrTy Param = Actions.ActOnParamDeclarator(CurScope, ParmDecl);
2878 :
2879 : // Parse the default argument, if any. We parse the default
2880 : // arguments in all dialects; the semantic analysis in
2881 : // ActOnParamDefaultArgument will reject the default argument in
2882 : // C.
169: branch 1 taken
13691: branch 2 taken
2883 13860: if (Tok.is(tok::equal)) {
2884 169: SourceLocation EqualLoc = Tok.getLocation();
2885 :
2886 : // Parse the default argument
82: branch 1 taken
87: branch 2 taken
2887 169: if (D.getContext() == Declarator::MemberContext) {
2888 : // If we're inside a class definition, cache the tokens
2889 : // corresponding to the default argument. We'll actually parse
2890 : // them when we see the end of the class definition.
2891 : // FIXME: Templates will require something similar.
2892 : // FIXME: Can we use a smart pointer for Toks?
2893 82: DefArgToks = new CachedTokens;
2894 :
0: branch 1 not taken
82: branch 2 taken
2895 82: if (!ConsumeAndStoreUntil(tok::comma, tok::r_paren, *DefArgToks,
2896 : tok::semi, false)) {
0: branch 0 not taken
0: branch 1 not taken
2897 0: delete DefArgToks;
2898 0: DefArgToks = 0;
2899 0: Actions.ActOnParamDefaultArgumentError(Param);
2900 : } else
2901 : Actions.ActOnParamUnparsedDefaultArgument(Param, EqualLoc,
2902 82: (*DefArgToks)[1].getLocation());
2903 : } else {
2904 : // Consume the '='.
2905 87: ConsumeToken();
2906 :
2907 87: OwningExprResult DefArgResult(ParseAssignmentExpression());
1: branch 1 taken
86: branch 2 taken
2908 87: if (DefArgResult.isInvalid()) {
2909 1: Actions.ActOnParamDefaultArgumentError(Param);
2910 1: SkipUntil(tok::comma, tok::r_paren, true, true);
2911 : } else {
2912 : // Inform the actions module about the default argument
2913 : Actions.ActOnParamDefaultArgument(Param, EqualLoc,
2914 86: move(DefArgResult));
2915 87: }
2916 : }
2917 : }
2918 :
2919 : ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
2920 : ParmDecl.getIdentifierLoc(), Param,
2921 13860: DefArgToks));
2922 : }
2923 :
2924 : // If the next token is a comma, consume it and keep reading arguments.
8934: branch 1 taken
4933: branch 2 taken
2925 13867: if (Tok.isNot(tok::comma)) {
3: branch 1 taken
8931: branch 2 taken
2926 8934: if (Tok.is(tok::ellipsis)) {
2927 3: IsVariadic = true;
2928 3: EllipsisLoc = ConsumeToken(); // Consume the ellipsis.
2929 :
1: branch 1 taken
2: branch 2 taken
2930 3: if (!getLang().CPlusPlus) {
2931 : // We have ellipsis without a preceding ',', which is ill-formed
2932 : // in C. Complain and provide the fix.
2933 : Diag(EllipsisLoc, diag::err_missing_comma_before_ellipsis)
2934 1: << CodeModificationHint::CreateInsertion(EllipsisLoc, ", ");
2935 : }
2936 : }
2937 :
2938 8934: break;
2939 : }
2940 :
2941 : // Consume the comma.
2942 4933: ConsumeToken();
2943 : }
2944 :
2945 : // Leave prototype scope.
2946 9240: PrototypeScope.Exit();
2947 :
2948 : // If we have the closing ')', eat it.
2949 9240: SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
2950 9240: SourceLocation EndLoc = RParenLoc;
2951 :
2952 9240: DeclSpec DS;
2953 9240: bool hasExceptionSpec = false;
2954 9240: SourceLocation ThrowLoc;
2955 9240: bool hasAnyExceptionSpec = false;
2956 9240: llvm::SmallVector<TypeTy*, 2> Exceptions;
2957 9240: llvm::SmallVector<SourceRange, 2> ExceptionRanges;
2958 :
3759: branch 1 taken
5481: branch 2 taken
2959 9240: if (getLang().CPlusPlus) {
2960 : // Parse cv-qualifier-seq[opt].
2961 3759: ParseTypeQualifierListOpt(DS, false /*no attributes*/);
0: branch 3 not taken
3759: branch 4 taken
2962 3759: if (!DS.getSourceRange().getEnd().isInvalid())
2963 0: EndLoc = DS.getSourceRange().getEnd();
2964 :
2965 : // Parse exception-specification[opt].
232: branch 1 taken
3527: branch 2 taken
2966 3759: if (Tok.is(tok::kw_throw)) {
2967 232: hasExceptionSpec = true;
2968 232: ThrowLoc = Tok.getLocation();
2969 : ParseExceptionSpecification(EndLoc, Exceptions, ExceptionRanges,
2970 232: hasAnyExceptionSpec);
2971 : assert(Exceptions.size() == ExceptionRanges.size() &&
232: branch 2 taken
0: branch 3 not taken
2972 232: "Produced different number of exception types and ranges.");
2973 : }
2974 : }
2975 :
2976 : // Remember that we parsed a function type, and remember the attributes.
2977 : D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/true, IsVariadic,
2978 : EllipsisLoc,
2979 : ParamInfo.data(), ParamInfo.size(),
2980 : DS.getTypeQualifiers(),
2981 : hasExceptionSpec, ThrowLoc,
2982 : hasAnyExceptionSpec,
2983 : Exceptions.data(),
2984 : ExceptionRanges.data(),
2985 : Exceptions.size(),
2986 : LParenLoc, RParenLoc, D),
2987 9240: EndLoc);
2988 : }
2989 :
2990 : /// ParseFunctionDeclaratorIdentifierList - While parsing a function declarator
2991 : /// we found a K&R-style identifier list instead of a type argument list. The
2992 : /// current token is known to be the first identifier in the list.
2993 : ///
2994 : /// identifier-list: [C99 6.7.5]
2995 : /// identifier
2996 : /// identifier-list ',' identifier
2997 : ///
2998 : void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc,
2999 57: Declarator &D) {
3000 : // Build up an array of information about the parsed arguments.
3001 57: llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
3002 57: llvm::SmallSet<const IdentifierInfo*, 16> ParamsSoFar;
3003 :
3004 : // If there was no identifier specified for the declarator, either we are in
3005 : // an abstract-declarator, or we are in a parameter declarator which was found
3006 : // to be abstract. In abstract-declarators, identifier lists are not valid:
3007 : // diagnose this.
0: branch 1 not taken
57: branch 2 taken
3008 57: if (!D.getIdentifier())
3009 0: Diag(Tok, diag::ext_ident_list_in_param);
3010 :
3011 : // Tok is known to be the first identifier in the list. Remember this
3012 : // identifier in ParamInfo.
3013 57: ParamsSoFar.insert(Tok.getIdentifierInfo());
3014 : ParamInfo.push_back(DeclaratorChunk::ParamInfo(Tok.getIdentifierInfo(),
3015 : Tok.getLocation(),
3016 57: DeclPtrTy()));
3017 :
3018 57: ConsumeToken(); // eat the first identifier.
3019 :
22: branch 1 taken
54: branch 2 taken
3020 133: while (Tok.is(tok::comma)) {
3021 : // Eat the comma.
3022 22: ConsumeToken();
3023 :
3024 : // If this isn't an identifier, report the error and skip until ')'.
3: branch 1 taken
19: branch 2 taken
3025 22: if (Tok.isNot(tok::identifier)) {
3026 3: Diag(Tok, diag::err_expected_ident);
3027 3: SkipUntil(tok::r_paren);
3028 3: return;
3029 : }
3030 :
3031 19: IdentifierInfo *ParmII = Tok.getIdentifierInfo();
3032 :
3033 : // Reject 'typedef int y; int test(x, y)', but continue parsing.
1: branch 2 taken
18: branch 3 taken
3034 19: if (Actions.getTypeName(*ParmII, Tok.getLocation(), CurScope))
3035 1: Diag(Tok, diag::err_unexpected_typedef_ident) << ParmII;
3036 :
3037 : // Verify that the argument identifier has not already been mentioned.
2: branch 1 taken
17: branch 2 taken
3038 19: if (!ParamsSoFar.insert(ParmII)) {
3039 2: Diag(Tok, diag::err_param_redefinition) << ParmII;
3040 : } else {
3041 : // Remember this identifier in ParamInfo.
3042 : ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
3043 : Tok.getLocation(),
3044 17: DeclPtrTy()));
3045 : }
3046 :
3047 : // Eat the identifier.
3048 19: ConsumeToken();
3049 : }
3050 :
3051 : // If we have the closing ')', eat it and we're done.
3052 54: SourceLocation RLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
3053 :
3054 : // Remember that we parsed a function type, and remember the attributes. This
3055 : // function type is always a K&R style function type, which is not varargs and
3056 : // has no prototype.
3057 : D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/false, /*varargs*/false,
3058 : SourceLocation(),
3059 : &ParamInfo[0], ParamInfo.size(),
3060 : /*TypeQuals*/0,
3061 : /*exception*/false,
3062 : SourceLocation(), false, 0, 0, 0,
3063 : LParenLoc, RLoc, D),
54: branch 7 taken
3: branch 8 taken
54: branch 10 taken
3: branch 11 taken
3064 54: RLoc);
3065 : }
3066 :
3067 : /// [C90] direct-declarator '[' constant-expression[opt] ']'
3068 : /// [C99] direct-declarator '[' type-qual-list[opt] assignment-expr[opt] ']'
3069 : /// [C99] direct-declarator '[' 'static' type-qual-list[opt] assign-expr ']'
3070 : /// [C99] direct-declarator '[' type-qual-list 'static' assignment-expr ']'
3071 : /// [C99] direct-declarator '[' type-qual-list[opt] '*' ']'
3072 2317: void Parser::ParseBracketDeclarator(Declarator &D) {
3073 2317: SourceLocation StartLoc = ConsumeBracket();
3074 :
3075 : // C array syntax has many features, but by-far the most common is [] and [4].
3076 : // This code does a fast path to handle some of the most obvious cases.
344: branch 1 taken
1973: branch 2 taken
3077 2317: if (Tok.getKind() == tok::r_square) {
3078 344: SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc);
3079 : //FIXME: Use these
3080 344: CXX0XAttributeList Attr;
3: branch 1 taken
341: branch 2 taken
0: branch 4 not taken
3: branch 5 taken
0: branch 6 not taken
344: branch 7 taken
3081 344: if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier(true)) {
3082 0: Attr = ParseCXX0XAttributes();
3083 : }
3084 :
3085 : // Remember that we parsed the empty array type.
3086 344: OwningExprResult NumElements(Actions);
3087 : D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, 0,
3088 : StartLoc, EndLoc),
3089 344: EndLoc);
3090 344: return;
1215: branch 1 taken
758: branch 2 taken
1190: branch 5 taken
25: branch 6 taken
1190: branch 7 taken
783: branch 8 taken
3091 1973: } else if (Tok.getKind() == tok::numeric_constant &&
3092 : GetLookAheadToken(1).is(tok::r_square)) {
3093 : // [4] is very common. Parse the numeric constant expression.
3094 1190: OwningExprResult ExprRes(Actions.ActOnNumericConstant(Tok));
3095 1190: ConsumeToken();
3096 :
3097 1190: SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc);
3098 : //FIXME: Use these
3099 1190: CXX0XAttributeList Attr;
68: branch 1 taken
1122: branch 2 taken
1: branch 4 taken
67: branch 5 taken
1: branch 6 taken
1189: branch 7 taken
3100 1190: if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
3101 1: Attr = ParseCXX0XAttributes();
3102 : }
3103 :
3104 : // If there was an error parsing the assignment-expression, recover.
0: branch 1 not taken
1190: branch 2 taken
3105 1190: if (ExprRes.isInvalid())
3106 0: ExprRes.release(); // Deallocate expr, just use [].
3107 :
3108 : // Remember that we parsed a array type, and remember its features.
3109 : D.AddTypeInfo(DeclaratorChunk::getArray(0, false, 0, ExprRes.release(),
3110 : StartLoc, EndLoc),
3111 1190: EndLoc);
3112 1190: return;
3113 : }
3114 :
3115 : // If valid, this location is the position where we read the 'static' keyword.
3116 783: SourceLocation StaticLoc;
2: branch 1 taken
781: branch 2 taken
3117 783: if (Tok.is(tok::kw_static))
3118 2: StaticLoc = ConsumeToken();
3119 :
3120 : // If there is a type-qualifier-list, read it now.
3121 : // Type qualifiers in an array subscript are a C99 feature.
3122 783: DeclSpec DS;
3123 783: ParseTypeQualifierListOpt(DS, false /*no attributes*/);
3124 :
3125 : // If we haven't already read 'static', check to see if there is one after the
3126 : // type-qualifier-list.
781: branch 1 taken
2: branch 2 taken
0: branch 4 not taken
781: branch 5 taken
0: branch 6 not taken