blob: 0f3d4e2f6104d4a2432f00bae8c3ecaf5969cd7f [file] [log] [blame]
Chris Lattnereb8a28f2006-08-10 18:43:39 +00001//===--- Parser.cpp - C Language Family Parser ----------------------------===//
Chris Lattner0bb5f832006-07-31 01:59:18 +00002//
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"
Chris Lattner288e86ff12006-11-11 23:03:42 +000015#include "clang/Parse/DeclSpec.h"
Chris Lattner971c6b62006-08-05 22:46:42 +000016#include "clang/Parse/Scope.h"
Chris Lattner0bb5f832006-07-31 01:59:18 +000017using namespace llvm;
18using namespace clang;
19
Chris Lattner697e5d62006-11-09 06:32:27 +000020Parser::Parser(Preprocessor &pp, Action &actions)
21 : PP(pp), Actions(actions), Diags(PP.getDiagnostics()) {
Chris Lattner8c204872006-10-14 05:19:21 +000022 Tok.setKind(tok::eof);
Chris Lattnere4e38592006-08-14 00:15:05 +000023 CurScope = 0;
Chris Lattnereec40f92006-08-06 21:55:29 +000024
25 ParenCount = BracketCount = BraceCount = 0;
Chris Lattner971c6b62006-08-05 22:46:42 +000026}
27
Chris Lattner685ed1e2006-08-14 00:22:04 +000028/// Out-of-line virtual destructor to provide home for Action class.
29Action::~Action() {}
Chris Lattnere4e38592006-08-14 00:15:05 +000030
Chris Lattner0bb5f832006-07-31 01:59:18 +000031
Chris Lattnerb9093cd2006-08-04 04:39:53 +000032void Parser::Diag(SourceLocation Loc, unsigned DiagID,
Chris Lattner0bb5f832006-07-31 01:59:18 +000033 const std::string &Msg) {
Chris Lattnerb9093cd2006-08-04 04:39:53 +000034 Diags.Report(Loc, DiagID, Msg);
Chris Lattner0bb5f832006-07-31 01:59:18 +000035}
36
Chris Lattner4564bc12006-08-10 23:14:52 +000037/// 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.
Chris Lattner71e23ce2006-11-04 20:18:38 +000042SourceLocation Parser::MatchRHSPunctuation(tok::TokenKind RHSTok,
43 SourceLocation LHSLoc) {
Chris Lattner4564bc12006-08-10 23:14:52 +000044
Chris Lattner71e23ce2006-11-04 20:18:38 +000045 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;
Chris Lattner4564bc12006-08-10 23:14:52 +000056 }
Chris Lattner71e23ce2006-11-04 20:18:38 +000057 Diag(Tok, DID);
58 Diag(LHSLoc, diag::err_matching, LHSName);
59 SkipUntil(RHSTok);
60 return R;
Chris Lattner4564bc12006-08-10 23:14:52 +000061}
62
Chris Lattnerdbb2a462006-08-12 19:26:13 +000063/// ExpectAndConsume - The parser expects that 'ExpectedTok' is next in the
64/// input. If so, it is consumed and false is returned.
65///
66/// If the input is malformed, this emits the specified diagnostic. Next, if
67/// SkipToTok is specified, it calls SkipUntil(SkipToTok). Finally, true is
68/// returned.
69bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID,
Chris Lattner6d7e6342006-08-15 03:41:14 +000070 const char *Msg, tok::TokenKind SkipToTok) {
Chris Lattnerdbb2a462006-08-12 19:26:13 +000071 if (Tok.getKind() == ExpectedTok) {
Chris Lattner15a00da2006-08-15 04:10:31 +000072 ConsumeAnyToken();
Chris Lattnerdbb2a462006-08-12 19:26:13 +000073 return false;
74 }
75
Chris Lattner6d7e6342006-08-15 03:41:14 +000076 Diag(Tok, DiagID, Msg);
Chris Lattnerdbb2a462006-08-12 19:26:13 +000077 if (SkipToTok != tok::unknown)
78 SkipUntil(SkipToTok);
79 return true;
80}
81
Chris Lattner70f32b72006-07-31 05:09:04 +000082//===----------------------------------------------------------------------===//
Chris Lattnereec40f92006-08-06 21:55:29 +000083// Error recovery.
84//===----------------------------------------------------------------------===//
85
86/// SkipUntil - Read tokens until we get to the specified token, then consume
87/// it (unless DontConsume is false). Because we cannot guarantee that the
88/// token will ever occur, this skips to the next token, or to some likely
89/// good stopping point. If StopAtSemi is true, skipping will stop at a ';'
90/// character.
91///
92/// If SkipUntil finds the specified token, it returns true, otherwise it
93/// returns false.
94bool Parser::SkipUntil(tok::TokenKind T, bool StopAtSemi, bool DontConsume) {
Chris Lattner5bd57e02006-08-11 06:40:25 +000095 // We always want this function to skip at least one token if the first token
96 // isn't T and if not at EOF.
97 bool isFirstTokenSkipped = true;
Chris Lattnereec40f92006-08-06 21:55:29 +000098 while (1) {
99 // If we found the token, stop and return true.
100 if (Tok.getKind() == T) {
101 if (DontConsume) {
102 // Noop, don't consume the token.
Chris Lattnereec40f92006-08-06 21:55:29 +0000103 } else {
Chris Lattnerdbb2a462006-08-12 19:26:13 +0000104 ConsumeAnyToken();
Chris Lattnereec40f92006-08-06 21:55:29 +0000105 }
106 return true;
107 }
108
109 switch (Tok.getKind()) {
110 case tok::eof:
111 // Ran out of tokens.
112 return false;
113
114 case tok::l_paren:
115 // Recursively skip properly-nested parens.
116 ConsumeParen();
Chris Lattner5bd57e02006-08-11 06:40:25 +0000117 SkipUntil(tok::r_paren, false);
Chris Lattnereec40f92006-08-06 21:55:29 +0000118 break;
119 case tok::l_square:
120 // Recursively skip properly-nested square brackets.
121 ConsumeBracket();
Chris Lattner5bd57e02006-08-11 06:40:25 +0000122 SkipUntil(tok::r_square, false);
Chris Lattnereec40f92006-08-06 21:55:29 +0000123 break;
124 case tok::l_brace:
125 // Recursively skip properly-nested braces.
126 ConsumeBrace();
Chris Lattner5bd57e02006-08-11 06:40:25 +0000127 SkipUntil(tok::r_brace, false);
Chris Lattnereec40f92006-08-06 21:55:29 +0000128 break;
129
130 // Okay, we found a ']' or '}' or ')', which we think should be balanced.
131 // Since the user wasn't looking for this token (if they were, it would
132 // already be handled), this isn't balanced. If there is a LHS token at a
133 // higher level, we will assume that this matches the unbalanced token
134 // and return it. Otherwise, this is a spurious RHS token, which we skip.
135 case tok::r_paren:
Chris Lattner5bd57e02006-08-11 06:40:25 +0000136 if (ParenCount && !isFirstTokenSkipped)
137 return false; // Matches something.
Chris Lattnereec40f92006-08-06 21:55:29 +0000138 ConsumeParen();
139 break;
140 case tok::r_square:
Chris Lattner5bd57e02006-08-11 06:40:25 +0000141 if (BracketCount && !isFirstTokenSkipped)
142 return false; // Matches something.
Chris Lattnereec40f92006-08-06 21:55:29 +0000143 ConsumeBracket();
144 break;
145 case tok::r_brace:
Chris Lattner5bd57e02006-08-11 06:40:25 +0000146 if (BraceCount && !isFirstTokenSkipped)
147 return false; // Matches something.
Chris Lattnereec40f92006-08-06 21:55:29 +0000148 ConsumeBrace();
149 break;
150
151 case tok::string_literal:
Chris Lattnerd3e98952006-10-06 05:22:26 +0000152 case tok::wide_string_literal:
Chris Lattnereec40f92006-08-06 21:55:29 +0000153 ConsumeStringToken();
154 break;
155 case tok::semi:
156 if (StopAtSemi)
157 return false;
158 // FALL THROUGH.
159 default:
160 // Skip this token.
161 ConsumeToken();
162 break;
163 }
Chris Lattner5bd57e02006-08-11 06:40:25 +0000164 isFirstTokenSkipped = false;
Chris Lattnereec40f92006-08-06 21:55:29 +0000165 }
166}
167
168//===----------------------------------------------------------------------===//
Chris Lattnere4e38592006-08-14 00:15:05 +0000169// Scope manipulation
170//===----------------------------------------------------------------------===//
171
Chris Lattnerb6a0e172006-11-06 00:22:42 +0000172/// ScopeCache - Cache scopes to avoid malloc traffic.
173static SmallVector<Scope*, 16> ScopeCache;
174
Chris Lattnere4e38592006-08-14 00:15:05 +0000175/// EnterScope - Start a new scope.
Chris Lattner33ad2ca2006-11-05 23:47:55 +0000176void Parser::EnterScope(unsigned ScopeFlags) {
Chris Lattnerb6a0e172006-11-06 00:22:42 +0000177 if (!ScopeCache.empty()) {
178 Scope *N = ScopeCache.back();
179 ScopeCache.pop_back();
180 N->Init(CurScope, ScopeFlags);
181 CurScope = N;
182 } else {
183 CurScope = new Scope(CurScope, ScopeFlags);
184 }
Chris Lattnere4e38592006-08-14 00:15:05 +0000185}
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 *Old = CurScope;
195 CurScope = Old->getParent();
Chris Lattnerb6a0e172006-11-06 00:22:42 +0000196
197 if (ScopeCache.size() == 16)
198 delete Old;
199 else
200 ScopeCache.push_back(Old);
Chris Lattnere4e38592006-08-14 00:15:05 +0000201}
202
203
204
205
206//===----------------------------------------------------------------------===//
Chris Lattner70f32b72006-07-31 05:09:04 +0000207// C99 6.9: External Definitions.
208//===----------------------------------------------------------------------===//
Chris Lattner0bb5f832006-07-31 01:59:18 +0000209
Chris Lattnerb6a0e172006-11-06 00:22:42 +0000210Parser::~Parser() {
211 // If we still have scopes active, delete the scope tree.
212 delete CurScope;
213
214 // Free the scope cache.
215 while (!ScopeCache.empty()) {
216 delete ScopeCache.back();
217 ScopeCache.pop_back();
218 }
219}
220
Chris Lattner38ba3362006-08-17 07:04:37 +0000221/// Initialize - Warm up the parser.
222///
223void Parser::Initialize() {
Chris Lattnere4e38592006-08-14 00:15:05 +0000224 // Prime the lexer look-ahead.
225 ConsumeToken();
226
227 // Create the global scope, install it as the current scope.
228 assert(CurScope == 0 && "A scope is already active?");
Chris Lattner33ad2ca2006-11-05 23:47:55 +0000229 EnterScope(0);
Chris Lattner38ba3362006-08-17 07:04:37 +0000230
Chris Lattner6d7e6342006-08-15 03:41:14 +0000231
232 // Install builtin types.
233 // TODO: Move this someplace more useful.
234 {
235 //__builtin_va_list
236 DeclSpec DS;
237 DS.StorageClassSpec = DeclSpec::SCS_typedef;
238
239 // TODO: add a 'TST_builtin' type?
240 DS.TypeSpecType = DeclSpec::TST_typedef;
Chris Lattner38ba3362006-08-17 07:04:37 +0000241
Chris Lattner6d7e6342006-08-15 03:41:14 +0000242 Declarator D(DS, Declarator::FileContext);
243 D.SetIdentifier(PP.getIdentifierInfo("__builtin_va_list"),SourceLocation());
Chris Lattner2dacc3f2006-10-16 00:33:54 +0000244 Actions.ParseDeclarator(CurScope, D, 0, 0);
Chris Lattner6d7e6342006-08-15 03:41:14 +0000245 }
246
Chris Lattner0bb5f832006-07-31 01:59:18 +0000247 if (Tok.getKind() == tok::eof) // Empty source file is an extension.
Chris Lattnerbd638922006-11-10 05:19:25 +0000248 Diag(Tok, diag::ext_empty_source_file);
Chris Lattner38ba3362006-08-17 07:04:37 +0000249}
250
251/// ParseTopLevelDecl - Parse one top-level declaration, return whatever the
252/// action tells us to. This returns true if the EOF was encountered.
253bool Parser::ParseTopLevelDecl(DeclTy*& Result) {
254 Result = 0;
255 if (Tok.getKind() == tok::eof) return true;
Chris Lattner0bb5f832006-07-31 01:59:18 +0000256
Chris Lattner2dacc3f2006-10-16 00:33:54 +0000257 Result = ParseExternalDeclaration();
Chris Lattner38ba3362006-08-17 07:04:37 +0000258 return false;
259}
260
261/// Finalize - Shut down the parser.
262///
263void Parser::Finalize() {
Chris Lattnere4e38592006-08-14 00:15:05 +0000264 ExitScope();
265 assert(CurScope == 0 && "Scope imbalance!");
Chris Lattner0bb5f832006-07-31 01:59:18 +0000266}
267
Chris Lattner38ba3362006-08-17 07:04:37 +0000268/// ParseTranslationUnit:
269/// translation-unit: [C99 6.9]
270/// external-declaration
271/// translation-unit external-declaration
272void Parser::ParseTranslationUnit() {
273 Initialize();
274
275 DeclTy *Res;
276 while (!ParseTopLevelDecl(Res))
277 /*parse them all*/;
278
279 Finalize();
280}
281
Chris Lattner0bb5f832006-07-31 01:59:18 +0000282/// ParseExternalDeclaration:
Chris Lattner70f32b72006-07-31 05:09:04 +0000283/// external-declaration: [C99 6.9]
Chris Lattner0bb5f832006-07-31 01:59:18 +0000284/// function-definition [TODO]
285/// declaration [TODO]
286/// [EXT] ';'
Chris Lattner6d7e6342006-08-15 03:41:14 +0000287/// [GNU] asm-definition
Chris Lattner0bb5f832006-07-31 01:59:18 +0000288/// [GNU] __extension__ external-declaration [TODO]
Chris Lattner40f16b52006-11-05 02:05:37 +0000289/// [OBJC] objc-class-definition
290/// [OBJC] objc-class-declaration
291/// [OBJC] objc-alias-declaration
292/// [OBJC] objc-protocol-definition
293/// [OBJC] objc-method-definition
294/// [OBJC] @end
Chris Lattner0bb5f832006-07-31 01:59:18 +0000295///
Chris Lattner6d7e6342006-08-15 03:41:14 +0000296/// [GNU] asm-definition:
297/// simple-asm-expr ';'
298///
Chris Lattner2dacc3f2006-10-16 00:33:54 +0000299Parser::DeclTy *Parser::ParseExternalDeclaration() {
Chris Lattner0bb5f832006-07-31 01:59:18 +0000300 switch (Tok.getKind()) {
301 case tok::semi:
Chris Lattnerbd638922006-11-10 05:19:25 +0000302 Diag(Tok, diag::ext_top_level_semi);
Chris Lattner0bb5f832006-07-31 01:59:18 +0000303 ConsumeToken();
Chris Lattner2dacc3f2006-10-16 00:33:54 +0000304 // TODO: Invoke action for top-level semicolon.
305 return 0;
Chris Lattner6d7e6342006-08-15 03:41:14 +0000306 case tok::kw_asm:
307 ParseSimpleAsm();
308 ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
309 "top-level asm block");
Chris Lattner2dacc3f2006-10-16 00:33:54 +0000310 // TODO: Invoke action for top-level asm.
311 return 0;
Steve Naroffb419d3a2006-10-27 23:18:49 +0000312 case tok::at:
Chris Lattnerb26b6652006-11-08 06:10:32 +0000313 ParseObjCAtDirectives();
Steve Naroffb419d3a2006-10-27 23:18:49 +0000314 return 0;
315 case tok::minus:
Chris Lattnerb26b6652006-11-08 06:10:32 +0000316 ParseObjCInstanceMethodDeclaration();
Chris Lattneraacc5af2006-11-03 07:21:07 +0000317 return 0;
Steve Naroffb419d3a2006-10-27 23:18:49 +0000318 case tok::plus:
Chris Lattnerb26b6652006-11-08 06:10:32 +0000319 ParseObjCClassMethodDeclaration();
Steve Naroffb419d3a2006-10-27 23:18:49 +0000320 return 0;
Chris Lattner0bb5f832006-07-31 01:59:18 +0000321 default:
322 // We can't tell whether this is a function-definition or declaration yet.
Chris Lattner2dacc3f2006-10-16 00:33:54 +0000323 return ParseDeclarationOrFunctionDefinition();
Chris Lattner0bb5f832006-07-31 01:59:18 +0000324 }
325}
326
327/// ParseDeclarationOrFunctionDefinition - Parse either a function-definition or
Chris Lattner70f32b72006-07-31 05:09:04 +0000328/// a declaration. We can't tell which we have until we read up to the
329/// compound-statement in function-definition.
Chris Lattner0bb5f832006-07-31 01:59:18 +0000330///
Chris Lattner70f32b72006-07-31 05:09:04 +0000331/// function-definition: [C99 6.9.1]
332/// declaration-specifiers[opt] declarator declaration-list[opt]
333/// compound-statement [TODO]
334/// declaration: [C99 6.7]
Chris Lattner0bb5f832006-07-31 01:59:18 +0000335/// declaration-specifiers init-declarator-list[opt] ';' [TODO]
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000336/// [!C99] init-declarator-list ';' [TODO]
Chris Lattner70f32b72006-07-31 05:09:04 +0000337/// [OMP] threadprivate-directive [TODO]
338///
Chris Lattner2dacc3f2006-10-16 00:33:54 +0000339Parser::DeclTy *Parser::ParseDeclarationOrFunctionDefinition() {
Chris Lattner70f32b72006-07-31 05:09:04 +0000340 // Parse the common declaration-specifiers piece.
Chris Lattnerb9093cd2006-08-04 04:39:53 +0000341 DeclSpec DS;
342 ParseDeclarationSpecifiers(DS);
Chris Lattnerd2864882006-08-05 08:09:44 +0000343
344 // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
Chris Lattner53361ac2006-08-10 05:19:57 +0000345 // declaration-specifiers init-declarator-list[opt] ';'
Chris Lattner0e894622006-08-13 19:58:17 +0000346 if (Tok.getKind() == tok::semi) {
347 // TODO: emit error on 'int;' or 'const enum foo;'.
348 // if (!DS.isMissingDeclaratorOk()) Diag(...);
349
350 ConsumeToken();
Chris Lattner2dacc3f2006-10-16 00:33:54 +0000351 // TODO: Return type definition.
352 return 0;
Chris Lattner0e894622006-08-13 19:58:17 +0000353 }
Chris Lattner70f32b72006-07-31 05:09:04 +0000354
Chris Lattnerfff824f2006-08-07 06:31:38 +0000355 // Parse the first declarator.
356 Declarator DeclaratorInfo(DS, Declarator::FileContext);
357 ParseDeclarator(DeclaratorInfo);
358 // Error parsing the declarator?
359 if (DeclaratorInfo.getIdentifier() == 0) {
360 // If so, skip until the semi-colon or a }.
361 SkipUntil(tok::r_brace, true);
362 if (Tok.getKind() == tok::semi)
363 ConsumeToken();
Chris Lattner2dacc3f2006-10-16 00:33:54 +0000364 return 0;
Chris Lattnerfff824f2006-08-07 06:31:38 +0000365 }
Chris Lattner70f32b72006-07-31 05:09:04 +0000366
Chris Lattnerfff824f2006-08-07 06:31:38 +0000367 // If the declarator is the start of a function definition, handle it.
368 if (Tok.getKind() == tok::equal || // int X()= -> not a function def
369 Tok.getKind() == tok::comma || // int X(), -> not a function def
Chris Lattner2dacc3f2006-10-16 00:33:54 +0000370 Tok.getKind() == tok::semi || // int X(); -> not a function def
Chris Lattnerfff824f2006-08-07 06:31:38 +0000371 Tok.getKind() == tok::kw_asm || // int X() __asm__ -> not a fn def
372 Tok.getKind() == tok::kw___attribute) {// int X() __attr__ -> not a fn def
373 // FALL THROUGH.
Chris Lattnera11999d2006-10-15 22:34:45 +0000374 } else if (DeclaratorInfo.isFunctionDeclarator() &&
Chris Lattnerfff824f2006-08-07 06:31:38 +0000375 (Tok.getKind() == tok::l_brace || // int X() {}
376 isDeclarationSpecifier())) { // int X(f) int f; {}
Chris Lattner2dacc3f2006-10-16 00:33:54 +0000377 return ParseFunctionDefinition(DeclaratorInfo);
Chris Lattnerfff824f2006-08-07 06:31:38 +0000378 } else {
Chris Lattnera11999d2006-10-15 22:34:45 +0000379 if (DeclaratorInfo.isFunctionDeclarator())
Chris Lattnerfff824f2006-08-07 06:31:38 +0000380 Diag(Tok, diag::err_expected_fn_body);
381 else
382 Diag(Tok, diag::err_expected_after_declarator);
Chris Lattnere4e38592006-08-14 00:15:05 +0000383 SkipUntil(tok::semi);
Chris Lattner2dacc3f2006-10-16 00:33:54 +0000384 return 0;
Chris Lattnerfff824f2006-08-07 06:31:38 +0000385 }
Chris Lattnerd9c3c592006-08-05 06:26:47 +0000386
Chris Lattner53361ac2006-08-10 05:19:57 +0000387 // Parse the init-declarator-list for a normal declaration.
Chris Lattner2dacc3f2006-10-16 00:33:54 +0000388 return ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
Chris Lattner70f32b72006-07-31 05:09:04 +0000389}
390
Chris Lattnerfff824f2006-08-07 06:31:38 +0000391/// ParseFunctionDefinition - We parsed and verified that the specified
392/// Declarator is well formed. If this is a K&R-style function, read the
393/// parameters declaration-list, then start the compound-statement.
394///
395/// declaration-specifiers[opt] declarator declaration-list[opt]
396/// compound-statement [TODO]
397///
Chris Lattner2dacc3f2006-10-16 00:33:54 +0000398Parser::DeclTy *Parser::ParseFunctionDefinition(Declarator &D) {
Chris Lattnerfff824f2006-08-07 06:31:38 +0000399 const DeclaratorTypeInfo &FnTypeInfo = D.getTypeObject(0);
400 assert(FnTypeInfo.Kind == DeclaratorTypeInfo::Function &&
401 "This isn't a function declarator!");
Chris Lattner7014fb82006-11-05 07:36:23 +0000402
403 // FIXME: Enter a scope for the arguments.
Chris Lattner33ad2ca2006-11-05 23:47:55 +0000404 //EnterScope(Scope::FnScope);
Chris Lattner7014fb82006-11-05 07:36:23 +0000405
406
Chris Lattnerfff824f2006-08-07 06:31:38 +0000407
408 // If this declaration was formed with a K&R-style identifier list for the
409 // arguments, parse declarations for all of the args next.
410 // int foo(a,b) int a; float b; {}
411 if (!FnTypeInfo.Fun.hasPrototype && !FnTypeInfo.Fun.isEmpty) {
412 // Read all the argument declarations.
Chris Lattner53361ac2006-08-10 05:19:57 +0000413 while (isDeclarationSpecifier())
414 ParseDeclaration(Declarator::KNRTypeListContext);
Chris Lattnerfff824f2006-08-07 06:31:38 +0000415
416 // Note, check that we got them all.
417 } else {
418 //if (isDeclarationSpecifier())
419 // Diag('k&r declspecs with prototype?');
420
Chris Lattner8693a512006-08-13 21:54:02 +0000421 // TODO: Install the arguments into the current scope.
Chris Lattnerfff824f2006-08-07 06:31:38 +0000422 }
423
Chris Lattner0ccd51e2006-08-09 05:47:47 +0000424 // We should have an opening brace now.
425 if (Tok.getKind() != tok::l_brace) {
426 Diag(Tok, diag::err_expected_fn_body);
427
428 // Skip over garbage, until we get to '{'. Don't eat the '{'.
429 SkipUntil(tok::l_brace, true, true);
430
431 // If we didn't find the '{', bail out.
432 if (Tok.getKind() != tok::l_brace)
Chris Lattner2dacc3f2006-10-16 00:33:54 +0000433 return 0;
Chris Lattner0ccd51e2006-08-09 05:47:47 +0000434 }
Chris Lattnerfff824f2006-08-07 06:31:38 +0000435
Chris Lattner30f910e2006-10-16 05:52:41 +0000436 // Parse the function body as a compound stmt.
437 StmtResult FnBody = ParseCompoundStatement();
438 if (FnBody.isInvalid) return 0;
Chris Lattner2dacc3f2006-10-16 00:33:54 +0000439
Chris Lattner7014fb82006-11-05 07:36:23 +0000440 // FIXME: Leave the argument scope.
441 // ExitScope();
442
Chris Lattner2dacc3f2006-10-16 00:33:54 +0000443 // TODO: Pass argument information.
Chris Lattner30f910e2006-10-16 05:52:41 +0000444 return Actions.ParseFunctionDefinition(CurScope, D, FnBody.Val);
Chris Lattnerfff824f2006-08-07 06:31:38 +0000445}
446
Chris Lattner0116c472006-08-15 06:03:28 +0000447/// ParseAsmStringLiteral - This is just a normal string-literal, but is not
448/// allowed to be a wide string, and is not subject to character translation.
449///
450/// [GNU] asm-string-literal:
451/// string-literal
452///
453void Parser::ParseAsmStringLiteral() {
Chris Lattnerd3e98952006-10-06 05:22:26 +0000454 if (!isTokenStringLiteral()) {
Chris Lattner0116c472006-08-15 06:03:28 +0000455 Diag(Tok, diag::err_expected_string_literal);
456 return;
457 }
458
459 ExprResult Res = ParseStringLiteralExpression();
460 if (Res.isInvalid) return;
461
462 // TODO: Diagnose: wide string literal in 'asm'
463}
464
Chris Lattner6d7e6342006-08-15 03:41:14 +0000465/// ParseSimpleAsm
466///
467/// [GNU] simple-asm-expr:
468/// 'asm' '(' asm-string-literal ')'
Chris Lattner6d7e6342006-08-15 03:41:14 +0000469///
470void Parser::ParseSimpleAsm() {
471 assert(Tok.getKind() == tok::kw_asm && "Not an asm!");
472 ConsumeToken();
473
474 if (Tok.getKind() != tok::l_paren) {
475 Diag(Tok, diag::err_expected_lparen_after, "asm");
476 return;
477 }
478
Chris Lattner04132372006-10-16 06:12:55 +0000479 SourceLocation Loc = ConsumeParen();
Chris Lattner6d7e6342006-08-15 03:41:14 +0000480
Chris Lattner0116c472006-08-15 06:03:28 +0000481 ParseAsmStringLiteral();
Chris Lattner6d7e6342006-08-15 03:41:14 +0000482
Chris Lattner04f80192006-08-15 04:55:54 +0000483 MatchRHSPunctuation(tok::r_paren, Loc);
Chris Lattner6d7e6342006-08-15 03:41:14 +0000484}
Steve Naroffb419d3a2006-10-27 23:18:49 +0000485