blob: 21ef54da0ff0701861f4c81817f5d8682f79ada9 [file] [log] [blame]
Chris Lattner4b009652007-07-25 00:24:17 +00001//===--- Parser.cpp - C Language Family Parser ----------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the Parser interfaces.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Parse/Parser.h"
15#include "clang/Parse/DeclSpec.h"
16#include "clang/Parse/Scope.h"
17using namespace clang;
18
19Parser::Parser(Preprocessor &pp, Action &actions)
20 : PP(pp), Actions(actions), Diags(PP.getDiagnostics()) {
21 Tok.setKind(tok::eof);
22 CurScope = 0;
23 NumCachedScopes = 0;
24 ParenCount = BracketCount = BraceCount = 0;
Steve Naroff81f1bba2007-09-06 21:24:23 +000025 ObjcImpDecl = 0;
Chris Lattner4b009652007-07-25 00:24:17 +000026}
27
28/// Out-of-line virtual destructor to provide home for Action class.
29Action::~Action() {}
30
31
32void Parser::Diag(SourceLocation Loc, unsigned DiagID,
33 const std::string &Msg) {
34 Diags.Report(Loc, DiagID, &Msg, 1);
35}
36
37/// MatchRHSPunctuation - For punctuation with a LHS and RHS (e.g. '['/']'),
38/// this helper function matches and consumes the specified RHS token if
39/// present. If not present, it emits the specified diagnostic indicating
40/// that the parser failed to match the RHS of the token at LHSLoc. LHSName
41/// should be the name of the unmatched LHS token.
42SourceLocation Parser::MatchRHSPunctuation(tok::TokenKind RHSTok,
43 SourceLocation LHSLoc) {
44
45 if (Tok.getKind() == RHSTok)
46 return ConsumeAnyToken();
47
48 SourceLocation R = Tok.getLocation();
49 const char *LHSName = "unknown";
50 diag::kind DID = diag::err_parse_error;
51 switch (RHSTok) {
52 default: break;
53 case tok::r_paren : LHSName = "("; DID = diag::err_expected_rparen; break;
54 case tok::r_brace : LHSName = "{"; DID = diag::err_expected_rbrace; break;
55 case tok::r_square: LHSName = "["; DID = diag::err_expected_rsquare; break;
56 case tok::greater: LHSName = "<"; DID = diag::err_expected_greater; break;
57 }
58 Diag(Tok, DID);
59 Diag(LHSLoc, diag::err_matching, LHSName);
60 SkipUntil(RHSTok);
61 return R;
62}
63
64/// ExpectAndConsume - The parser expects that 'ExpectedTok' is next in the
65/// input. If so, it is consumed and false is returned.
66///
67/// If the input is malformed, this emits the specified diagnostic. Next, if
68/// SkipToTok is specified, it calls SkipUntil(SkipToTok). Finally, true is
69/// returned.
70bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID,
71 const char *Msg, tok::TokenKind SkipToTok) {
72 if (Tok.getKind() == ExpectedTok) {
73 ConsumeAnyToken();
74 return false;
75 }
76
77 Diag(Tok, DiagID, Msg);
78 if (SkipToTok != tok::unknown)
79 SkipUntil(SkipToTok);
80 return true;
81}
82
83//===----------------------------------------------------------------------===//
84// Error recovery.
85//===----------------------------------------------------------------------===//
86
87/// SkipUntil - Read tokens until we get to the specified token, then consume
88/// it (unless DontConsume is true). Because we cannot guarantee that the
89/// token will ever occur, this skips to the next token, or to some likely
90/// good stopping point. If StopAtSemi is true, skipping will stop at a ';'
91/// character.
92///
93/// If SkipUntil finds the specified token, it returns true, otherwise it
94/// returns false.
95bool Parser::SkipUntil(const tok::TokenKind *Toks, unsigned NumToks,
96 bool StopAtSemi, bool DontConsume) {
97 // We always want this function to skip at least one token if the first token
98 // isn't T and if not at EOF.
99 bool isFirstTokenSkipped = true;
100 while (1) {
101 // If we found one of the tokens, stop and return true.
102 for (unsigned i = 0; i != NumToks; ++i) {
103 if (Tok.getKind() == Toks[i]) {
104 if (DontConsume) {
105 // Noop, don't consume the token.
106 } else {
107 ConsumeAnyToken();
108 }
109 return true;
110 }
111 }
112
113 switch (Tok.getKind()) {
114 case tok::eof:
115 // Ran out of tokens.
116 return false;
117
118 case tok::l_paren:
119 // Recursively skip properly-nested parens.
120 ConsumeParen();
121 SkipUntil(tok::r_paren, false);
122 break;
123 case tok::l_square:
124 // Recursively skip properly-nested square brackets.
125 ConsumeBracket();
126 SkipUntil(tok::r_square, false);
127 break;
128 case tok::l_brace:
129 // Recursively skip properly-nested braces.
130 ConsumeBrace();
131 SkipUntil(tok::r_brace, false);
132 break;
133
134 // Okay, we found a ']' or '}' or ')', which we think should be balanced.
135 // Since the user wasn't looking for this token (if they were, it would
136 // already be handled), this isn't balanced. If there is a LHS token at a
137 // higher level, we will assume that this matches the unbalanced token
138 // and return it. Otherwise, this is a spurious RHS token, which we skip.
139 case tok::r_paren:
140 if (ParenCount && !isFirstTokenSkipped)
141 return false; // Matches something.
142 ConsumeParen();
143 break;
144 case tok::r_square:
145 if (BracketCount && !isFirstTokenSkipped)
146 return false; // Matches something.
147 ConsumeBracket();
148 break;
149 case tok::r_brace:
150 if (BraceCount && !isFirstTokenSkipped)
151 return false; // Matches something.
152 ConsumeBrace();
153 break;
154
155 case tok::string_literal:
156 case tok::wide_string_literal:
157 ConsumeStringToken();
158 break;
159 case tok::semi:
160 if (StopAtSemi)
161 return false;
162 // FALL THROUGH.
163 default:
164 // Skip this token.
165 ConsumeToken();
166 break;
167 }
168 isFirstTokenSkipped = false;
169 }
170}
171
172//===----------------------------------------------------------------------===//
173// Scope manipulation
174//===----------------------------------------------------------------------===//
175
176/// EnterScope - Start a new scope.
177void Parser::EnterScope(unsigned ScopeFlags) {
178 if (NumCachedScopes) {
179 Scope *N = ScopeCache[--NumCachedScopes];
180 N->Init(CurScope, ScopeFlags);
181 CurScope = N;
182 } else {
183 CurScope = new Scope(CurScope, ScopeFlags);
184 }
185}
186
187/// ExitScope - Pop a scope off the scope stack.
188void Parser::ExitScope() {
189 assert(CurScope && "Scope imbalance!");
190
191 // Inform the actions module that this scope is going away.
192 Actions.PopScope(Tok.getLocation(), CurScope);
193
194 Scope *OldScope = CurScope;
195 CurScope = OldScope->getParent();
196
197 if (NumCachedScopes == ScopeCacheSize)
198 delete OldScope;
199 else
200 ScopeCache[NumCachedScopes++] = OldScope;
201}
202
203
204
205
206//===----------------------------------------------------------------------===//
207// C99 6.9: External Definitions.
208//===----------------------------------------------------------------------===//
209
210Parser::~Parser() {
211 // If we still have scopes active, delete the scope tree.
212 delete CurScope;
213
214 // Free the scope cache.
215 for (unsigned i = 0, e = NumCachedScopes; i != e; ++i)
216 delete ScopeCache[i];
217}
218
219/// Initialize - Warm up the parser.
220///
221void Parser::Initialize() {
222 // Prime the lexer look-ahead.
223 ConsumeToken();
224
Chris Lattnera7549902007-08-26 06:24:45 +0000225 // Create the translation unit scope. Install it as the current scope.
Chris Lattner4b009652007-07-25 00:24:17 +0000226 assert(CurScope == 0 && "A scope is already active?");
Chris Lattnera7549902007-08-26 06:24:45 +0000227 EnterScope(Scope::DeclScope);
228
Chris Lattner4b009652007-07-25 00:24:17 +0000229 // Install builtin types.
230 // TODO: Move this someplace more useful.
231 {
232 const char *Dummy;
233
234 //__builtin_va_list
235 DeclSpec DS;
236 bool Error = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, SourceLocation(),
237 Dummy);
238
239 // TODO: add a 'TST_builtin' type?
240 Error |= DS.SetTypeSpecType(DeclSpec::TST_int, SourceLocation(), Dummy);
241 assert(!Error && "Error setting up __builtin_va_list!");
242
243 Declarator D(DS, Declarator::FileContext);
244 D.SetIdentifier(PP.getIdentifierInfo("__builtin_va_list"),SourceLocation());
Steve Naroff6a0e2092007-09-12 14:07:44 +0000245 Actions.ParseDeclarator(CurScope, D, 0);
Chris Lattner4b009652007-07-25 00:24:17 +0000246 }
247
Chris Lattner7bdc85d2007-08-25 05:47:03 +0000248 if (Tok.getKind() == tok::eof &&
249 !getLang().CPlusPlus) // Empty source file is an extension in C
Chris Lattner4b009652007-07-25 00:24:17 +0000250 Diag(Tok, diag::ext_empty_source_file);
Chris Lattner32352462007-08-29 22:54:08 +0000251
252 // Initialization for Objective-C context sensitive keywords recognition.
253 // Referenced in Parser::isObjCTypeQualifier.
254 if (getLang().ObjC1) {
255 ObjcTypeQuals[objc_in] = &PP.getIdentifierTable().get("in");
256 ObjcTypeQuals[objc_out] = &PP.getIdentifierTable().get("out");
257 ObjcTypeQuals[objc_inout] = &PP.getIdentifierTable().get("inout");
258 ObjcTypeQuals[objc_oneway] = &PP.getIdentifierTable().get("oneway");
259 ObjcTypeQuals[objc_bycopy] = &PP.getIdentifierTable().get("bycopy");
260 ObjcTypeQuals[objc_byref] = &PP.getIdentifierTable().get("byref");
261 }
Fariborz Jahanian6668b8c2007-08-31 16:11:31 +0000262 if (getLang().ObjC2) {
263 ObjcPropertyAttrs[objc_readonly] = &PP.getIdentifierTable().get("readonly");
264 ObjcPropertyAttrs[objc_getter] = &PP.getIdentifierTable().get("getter");
265 ObjcPropertyAttrs[objc_setter] = &PP.getIdentifierTable().get("setter");
266 ObjcPropertyAttrs[objc_assign] = &PP.getIdentifierTable().get("assign");
267 ObjcPropertyAttrs[objc_readwrite] =
268 &PP.getIdentifierTable().get("readwrite");
269 ObjcPropertyAttrs[objc_retain] = &PP.getIdentifierTable().get("retain");
270 ObjcPropertyAttrs[objc_copy] = &PP.getIdentifierTable().get("copy");
271 ObjcPropertyAttrs[objc_nonatomic] =
272 &PP.getIdentifierTable().get("nonatomic");
273 }
Chris Lattner4b009652007-07-25 00:24:17 +0000274}
275
276/// ParseTopLevelDecl - Parse one top-level declaration, return whatever the
277/// action tells us to. This returns true if the EOF was encountered.
278bool Parser::ParseTopLevelDecl(DeclTy*& Result) {
279 Result = 0;
280 if (Tok.getKind() == tok::eof) return true;
281
282 Result = ParseExternalDeclaration();
283 return false;
284}
285
286/// Finalize - Shut down the parser.
287///
288void Parser::Finalize() {
289 ExitScope();
290 assert(CurScope == 0 && "Scope imbalance!");
291}
292
293/// ParseTranslationUnit:
294/// translation-unit: [C99 6.9]
295/// external-declaration
296/// translation-unit external-declaration
297void Parser::ParseTranslationUnit() {
298 Initialize();
299
300 DeclTy *Res;
301 while (!ParseTopLevelDecl(Res))
302 /*parse them all*/;
303
304 Finalize();
305}
306
307/// ParseExternalDeclaration:
308/// external-declaration: [C99 6.9]
Chris Lattner06f4e752007-08-10 20:57:02 +0000309/// function-definition
310/// declaration
Chris Lattner4b009652007-07-25 00:24:17 +0000311/// [EXT] ';'
312/// [GNU] asm-definition
Chris Lattner06f4e752007-08-10 20:57:02 +0000313/// [GNU] __extension__ external-declaration
Chris Lattner4b009652007-07-25 00:24:17 +0000314/// [OBJC] objc-class-definition
315/// [OBJC] objc-class-declaration
316/// [OBJC] objc-alias-declaration
317/// [OBJC] objc-protocol-definition
318/// [OBJC] objc-method-definition
319/// [OBJC] @end
320///
321/// [GNU] asm-definition:
322/// simple-asm-expr ';'
323///
324Parser::DeclTy *Parser::ParseExternalDeclaration() {
325 switch (Tok.getKind()) {
326 case tok::semi:
327 Diag(Tok, diag::ext_top_level_semi);
328 ConsumeToken();
329 // TODO: Invoke action for top-level semicolon.
330 return 0;
Chris Lattner06f4e752007-08-10 20:57:02 +0000331 case tok::kw___extension__: {
332 ConsumeToken();
333 // FIXME: Disable extension warnings.
334 DeclTy *RV = ParseExternalDeclaration();
335 // FIXME: Restore extension warnings.
336 return RV;
337 }
Chris Lattner4b009652007-07-25 00:24:17 +0000338 case tok::kw_asm:
339 ParseSimpleAsm();
340 ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
341 "top-level asm block");
342 // TODO: Invoke action for top-level asm.
343 return 0;
344 case tok::at:
345 // @ is not a legal token unless objc is enabled, no need to check.
Steve Narofffaed3bf2007-09-10 20:51:04 +0000346 return ParseObjCAtDirectives();
Chris Lattner4b009652007-07-25 00:24:17 +0000347 case tok::minus:
348 if (getLang().ObjC1) {
Steve Naroff72f17fb2007-08-22 22:17:26 +0000349 ParseObjCInstanceMethodDefinition();
Chris Lattner4b009652007-07-25 00:24:17 +0000350 } else {
351 Diag(Tok, diag::err_expected_external_declaration);
352 ConsumeToken();
353 }
354 return 0;
355 case tok::plus:
356 if (getLang().ObjC1) {
Steve Naroff72f17fb2007-08-22 22:17:26 +0000357 ParseObjCClassMethodDefinition();
Chris Lattner4b009652007-07-25 00:24:17 +0000358 } else {
359 Diag(Tok, diag::err_expected_external_declaration);
360 ConsumeToken();
361 }
362 return 0;
Chris Lattnerf7b2e552007-08-25 06:57:03 +0000363 case tok::kw_namespace:
Chris Lattner4b009652007-07-25 00:24:17 +0000364 case tok::kw_typedef:
Chris Lattner9c135722007-08-25 18:15:16 +0000365 // A function definition cannot start with a these keywords.
Chris Lattner4b009652007-07-25 00:24:17 +0000366 return ParseDeclaration(Declarator::FileContext);
367 default:
368 // We can't tell whether this is a function-definition or declaration yet.
369 return ParseDeclarationOrFunctionDefinition();
370 }
371}
372
373/// ParseDeclarationOrFunctionDefinition - Parse either a function-definition or
374/// a declaration. We can't tell which we have until we read up to the
375/// compound-statement in function-definition.
376///
377/// function-definition: [C99 6.9.1]
378/// declaration-specifiers[opt] declarator declaration-list[opt]
Chris Lattneraac973e2007-08-22 06:06:56 +0000379/// compound-statement
Chris Lattner4b009652007-07-25 00:24:17 +0000380/// declaration: [C99 6.7]
Chris Lattneraac973e2007-08-22 06:06:56 +0000381/// declaration-specifiers init-declarator-list[opt] ';'
382/// [!C99] init-declarator-list ';' [TODO: warn in c99 mode]
Chris Lattner4b009652007-07-25 00:24:17 +0000383/// [OMP] threadprivate-directive [TODO]
384///
385Parser::DeclTy *Parser::ParseDeclarationOrFunctionDefinition() {
386 // Parse the common declaration-specifiers piece.
387 DeclSpec DS;
388 ParseDeclarationSpecifiers(DS);
389
390 // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
391 // declaration-specifiers init-declarator-list[opt] ';'
392 if (Tok.getKind() == tok::semi) {
393 ConsumeToken();
394 return Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
395 }
396
Steve Naroffa7f62782007-08-23 19:56:30 +0000397 // ObjC2 allows prefix attributes on class interfaces.
398 if (getLang().ObjC2 && Tok.getKind() == tok::at) {
Steve Narofffb367882007-08-20 21:31:48 +0000399 SourceLocation AtLoc = ConsumeToken(); // the "@"
400 if (Tok.getIdentifierInfo()->getObjCKeywordID() == tok::objc_interface)
401 return ParseObjCAtInterfaceDeclaration(AtLoc, DS.getAttributes());
402 }
403
Chris Lattner4b009652007-07-25 00:24:17 +0000404 // Parse the first declarator.
405 Declarator DeclaratorInfo(DS, Declarator::FileContext);
406 ParseDeclarator(DeclaratorInfo);
407 // Error parsing the declarator?
408 if (DeclaratorInfo.getIdentifier() == 0) {
409 // If so, skip until the semi-colon or a }.
410 SkipUntil(tok::r_brace, true);
411 if (Tok.getKind() == tok::semi)
412 ConsumeToken();
413 return 0;
414 }
415
416 // If the declarator is the start of a function definition, handle it.
417 if (Tok.getKind() == tok::equal || // int X()= -> not a function def
418 Tok.getKind() == tok::comma || // int X(), -> not a function def
419 Tok.getKind() == tok::semi || // int X(); -> not a function def
420 Tok.getKind() == tok::kw_asm || // int X() __asm__ -> not a fn def
421 Tok.getKind() == tok::kw___attribute) {// int X() __attr__ -> not a fn def
422 // FALL THROUGH.
423 } else if (DeclaratorInfo.isFunctionDeclarator() &&
424 (Tok.getKind() == tok::l_brace || // int X() {}
425 isDeclarationSpecifier())) { // int X(f) int f; {}
426 return ParseFunctionDefinition(DeclaratorInfo);
427 } else {
428 if (DeclaratorInfo.isFunctionDeclarator())
429 Diag(Tok, diag::err_expected_fn_body);
430 else
431 Diag(Tok, diag::err_expected_after_declarator);
432 SkipUntil(tok::semi);
433 return 0;
434 }
435
436 // Parse the init-declarator-list for a normal declaration.
437 return ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
438}
439
440/// ParseFunctionDefinition - We parsed and verified that the specified
441/// Declarator is well formed. If this is a K&R-style function, read the
442/// parameters declaration-list, then start the compound-statement.
443///
444/// declaration-specifiers[opt] declarator declaration-list[opt]
445/// compound-statement [TODO]
446///
447Parser::DeclTy *Parser::ParseFunctionDefinition(Declarator &D) {
448 const DeclaratorChunk &FnTypeInfo = D.getTypeObject(0);
449 assert(FnTypeInfo.Kind == DeclaratorChunk::Function &&
450 "This isn't a function declarator!");
451 const DeclaratorChunk::FunctionTypeInfo &FTI = FnTypeInfo.Fun;
452
453 // If this declaration was formed with a K&R-style identifier list for the
454 // arguments, parse declarations for all of the args next.
455 // int foo(a,b) int a; float b; {}
456 if (!FTI.hasPrototype && FTI.NumArgs != 0)
457 ParseKNRParamDeclarations(D);
458
459 // Enter a scope for the function body.
Chris Lattnera7549902007-08-26 06:24:45 +0000460 EnterScope(Scope::FnScope|Scope::DeclScope);
Chris Lattner4b009652007-07-25 00:24:17 +0000461
462 // Tell the actions module that we have entered a function definition with the
463 // specified Declarator for the function.
464 DeclTy *Res = Actions.ParseStartOfFunctionDef(CurScope, D);
465
466
467 // We should have an opening brace now.
468 if (Tok.getKind() != tok::l_brace) {
469 Diag(Tok, diag::err_expected_fn_body);
470
471 // Skip over garbage, until we get to '{'. Don't eat the '{'.
472 SkipUntil(tok::l_brace, true, true);
473
474 // If we didn't find the '{', bail out.
475 if (Tok.getKind() != tok::l_brace) {
476 ExitScope();
477 return 0;
478 }
479 }
480
481 // Do not enter a scope for the brace, as the arguments are in the same scope
482 // (the function body) as the body itself. Instead, just read the statement
483 // list and put it into a CompoundStmt for safe keeping.
484 StmtResult FnBody = ParseCompoundStatementBody();
485 if (FnBody.isInvalid) {
486 ExitScope();
487 return 0;
488 }
489
490 // Leave the function body scope.
491 ExitScope();
492
493 // TODO: Pass argument information.
494 return Actions.ParseFunctionDefBody(Res, FnBody.Val);
495}
496
497/// ParseKNRParamDeclarations - Parse 'declaration-list[opt]' which provides
498/// types for a function with a K&R-style identifier list for arguments.
499void Parser::ParseKNRParamDeclarations(Declarator &D) {
500 // We know that the top-level of this declarator is a function.
501 DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun;
502
503 // Read all the argument declarations.
504 while (isDeclarationSpecifier()) {
505 SourceLocation DSStart = Tok.getLocation();
506
507 // Parse the common declaration-specifiers piece.
508 DeclSpec DS;
509 ParseDeclarationSpecifiers(DS);
510
511 // C99 6.9.1p6: 'each declaration in the declaration list shall have at
512 // least one declarator'.
513 // NOTE: GCC just makes this an ext-warn. It's not clear what it does with
514 // the declarations though. It's trivial to ignore them, really hard to do
515 // anything else with them.
516 if (Tok.getKind() == tok::semi) {
517 Diag(DSStart, diag::err_declaration_does_not_declare_param);
518 ConsumeToken();
519 continue;
520 }
521
522 // C99 6.9.1p6: Declarations shall contain no storage-class specifiers other
523 // than register.
524 if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified &&
525 DS.getStorageClassSpec() != DeclSpec::SCS_register) {
526 Diag(DS.getStorageClassSpecLoc(),
527 diag::err_invalid_storage_class_in_func_decl);
528 DS.ClearStorageClassSpecs();
529 }
530 if (DS.isThreadSpecified()) {
531 Diag(DS.getThreadSpecLoc(),
532 diag::err_invalid_storage_class_in_func_decl);
533 DS.ClearStorageClassSpecs();
534 }
535
536 // Parse the first declarator attached to this declspec.
537 Declarator ParmDeclarator(DS, Declarator::KNRTypeListContext);
538 ParseDeclarator(ParmDeclarator);
539
540 // Handle the full declarator list.
541 while (1) {
542 DeclTy *AttrList;
543 // If attributes are present, parse them.
544 if (Tok.getKind() == tok::kw___attribute)
545 // FIXME: attach attributes too.
546 AttrList = ParseAttributes();
547
548 // Ask the actions module to compute the type for this declarator.
549 Action::TypeResult TR =
550 Actions.ParseParamDeclaratorType(CurScope, ParmDeclarator);
Steve Narofffaed3bf2007-09-10 20:51:04 +0000551
Chris Lattner4b009652007-07-25 00:24:17 +0000552 if (!TR.isInvalid &&
553 // A missing identifier has already been diagnosed.
554 ParmDeclarator.getIdentifier()) {
555
556 // Scan the argument list looking for the correct param to apply this
557 // type.
558 for (unsigned i = 0; ; ++i) {
559 // C99 6.9.1p6: those declarators shall declare only identifiers from
560 // the identifier list.
561 if (i == FTI.NumArgs) {
562 Diag(ParmDeclarator.getIdentifierLoc(), diag::err_no_matching_param,
563 ParmDeclarator.getIdentifier()->getName());
564 break;
565 }
566
567 if (FTI.ArgInfo[i].Ident == ParmDeclarator.getIdentifier()) {
568 // Reject redefinitions of parameters.
569 if (FTI.ArgInfo[i].TypeInfo) {
570 Diag(ParmDeclarator.getIdentifierLoc(),
571 diag::err_param_redefinition,
572 ParmDeclarator.getIdentifier()->getName());
573 } else {
574 FTI.ArgInfo[i].TypeInfo = TR.Val;
575 }
576 break;
577 }
578 }
579 }
580
581 // If we don't have a comma, it is either the end of the list (a ';') or
582 // an error, bail out.
583 if (Tok.getKind() != tok::comma)
584 break;
585
586 // Consume the comma.
587 ConsumeToken();
588
589 // Parse the next declarator.
590 ParmDeclarator.clear();
591 ParseDeclarator(ParmDeclarator);
592 }
593
594 if (Tok.getKind() == tok::semi) {
595 ConsumeToken();
596 } else {
597 Diag(Tok, diag::err_parse_error);
598 // Skip to end of block or statement
599 SkipUntil(tok::semi, true);
600 if (Tok.getKind() == tok::semi)
601 ConsumeToken();
602 }
603 }
604
605 // The actions module must verify that all arguments were declared.
606}
607
608
609/// ParseAsmStringLiteral - This is just a normal string-literal, but is not
610/// allowed to be a wide string, and is not subject to character translation.
611///
612/// [GNU] asm-string-literal:
613/// string-literal
614///
615void Parser::ParseAsmStringLiteral() {
616 if (!isTokenStringLiteral()) {
617 Diag(Tok, diag::err_expected_string_literal);
618 return;
619 }
620
621 ExprResult Res = ParseStringLiteralExpression();
622 if (Res.isInvalid) return;
623
624 // TODO: Diagnose: wide string literal in 'asm'
625}
626
627/// ParseSimpleAsm
628///
629/// [GNU] simple-asm-expr:
630/// 'asm' '(' asm-string-literal ')'
631///
632void Parser::ParseSimpleAsm() {
633 assert(Tok.getKind() == tok::kw_asm && "Not an asm!");
634 ConsumeToken();
635
636 if (Tok.getKind() != tok::l_paren) {
637 Diag(Tok, diag::err_expected_lparen_after, "asm");
638 return;
639 }
640
641 SourceLocation Loc = ConsumeParen();
642
643 ParseAsmStringLiteral();
644
645 MatchRHSPunctuation(tok::r_paren, Loc);
646}
647