Refactor init-declarator-list parsing code to allow for-statements to have
initializers in them. llvm-svn: 38847
This commit is contained in:
parent
9075bd7727
commit
53361ac130
|
@ -20,6 +20,60 @@ using namespace clang;
|
|||
// C99 6.7: Declarations.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// ParseDeclaration - Parse a full 'declaration', which consists of
|
||||
/// declaration-specifiers, some number of declarators, and a semicolon.
|
||||
/// 'Context' should be a Declarator::TheContext value.
|
||||
void Parser::ParseDeclaration(unsigned Context) {
|
||||
// Parse the common declaration-specifiers piece.
|
||||
DeclSpec DS;
|
||||
ParseDeclarationSpecifiers(DS);
|
||||
|
||||
Declarator DeclaratorInfo(DS, (Declarator::TheContext)Context);
|
||||
ParseDeclarator(DeclaratorInfo);
|
||||
|
||||
ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
|
||||
}
|
||||
|
||||
void Parser::ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
|
||||
// At this point, we know that it is not a function definition. Parse the
|
||||
// rest of the init-declarator-list.
|
||||
while (1) {
|
||||
// must be: decl-spec[opt] declarator init-declarator-list
|
||||
// Parse declarator '=' initializer.
|
||||
if (Tok.getKind() == tok::equal) {
|
||||
ConsumeToken();
|
||||
// FIXME: THIS IS WRONG!!
|
||||
ParseExpression();
|
||||
}
|
||||
|
||||
|
||||
// TODO: install declarator.
|
||||
|
||||
// If we don't have a comma, it is either the end of the list (a ';') or an
|
||||
// error, bail out.
|
||||
if (Tok.getKind() != tok::comma)
|
||||
break;
|
||||
|
||||
// Consume the comma.
|
||||
ConsumeToken();
|
||||
|
||||
// Parse the next declarator.
|
||||
D.clear();
|
||||
ParseDeclarator(D);
|
||||
}
|
||||
|
||||
if (Tok.getKind() == tok::semi) {
|
||||
ConsumeToken();
|
||||
} else {
|
||||
Diag(Tok, diag::err_parse_error);
|
||||
// Skip to end of block or statement
|
||||
SkipUntil(tok::r_brace, true);
|
||||
if (Tok.getKind() == tok::semi)
|
||||
ConsumeToken();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// ParseDeclarationSpecifiers
|
||||
/// declaration-specifiers: [C99 6.7]
|
||||
/// storage-class-specifier declaration-specifiers [opt]
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include "clang/Parse/Parser.h"
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Parse/Declarations.h"
|
||||
using namespace llvm;
|
||||
using namespace clang;
|
||||
|
||||
|
@ -262,13 +263,13 @@ void Parser::ParseForStatement() {
|
|||
|
||||
// Parse the first part of the for specifier.
|
||||
if (Tok.getKind() == tok::semi) { // for (;
|
||||
// no first part.
|
||||
// no first part, eat the ';'.
|
||||
ConsumeToken();
|
||||
} else if (isDeclarationSpecifier()) { // for (int X = 4;
|
||||
// FIXME: Parse declaration.
|
||||
assert(0);
|
||||
// Parse declaration, which eats the ';'.
|
||||
ParseDeclaration(Declarator::ForContext);
|
||||
} else {
|
||||
ParseExpression();
|
||||
}
|
||||
|
||||
if (Tok.getKind() == tok::semi) {
|
||||
ConsumeToken();
|
||||
|
@ -277,6 +278,7 @@ void Parser::ParseForStatement() {
|
|||
Diag(ForLoc, diag::err_matching);
|
||||
SkipUntil(tok::semi);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the second part of the for specifier.
|
||||
if (Tok.getKind() == tok::semi) { // for (...;;
|
||||
|
|
|
@ -191,6 +191,7 @@ void Parser::ParseDeclarationOrFunctionDefinition() {
|
|||
ParseDeclarationSpecifiers(DS);
|
||||
|
||||
// C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
|
||||
// declaration-specifiers init-declarator-list[opt] ';'
|
||||
if (Tok.getKind() == tok::semi)
|
||||
assert(0 && "Unimp!");
|
||||
|
||||
|
@ -230,39 +231,8 @@ void Parser::ParseDeclarationOrFunctionDefinition() {
|
|||
return;
|
||||
}
|
||||
|
||||
// At this point, we know that it is not a function definition. Parse the
|
||||
// rest of the init-declarator-list.
|
||||
while (1) {
|
||||
// must be: decl-spec[opt] declarator init-declarator-list
|
||||
// Parse declarator '=' initializer.
|
||||
if (Tok.getKind() == tok::equal)
|
||||
assert(0 && "cannot handle initializer yet!");
|
||||
|
||||
|
||||
// TODO: install declarator.
|
||||
|
||||
// If we don't have a comma, it is either the end of the list (a ';') or an
|
||||
// error, bail out.
|
||||
if (Tok.getKind() != tok::comma)
|
||||
break;
|
||||
|
||||
// Consume the comma.
|
||||
ConsumeToken();
|
||||
|
||||
// Parse the next declarator.
|
||||
DeclaratorInfo.clear();
|
||||
ParseDeclarator(DeclaratorInfo);
|
||||
}
|
||||
|
||||
if (Tok.getKind() == tok::semi) {
|
||||
ConsumeToken();
|
||||
} else {
|
||||
Diag(Tok, diag::err_parse_error);
|
||||
// Skip to end of block or statement
|
||||
SkipUntil(tok::r_brace, true);
|
||||
if (Tok.getKind() == tok::semi)
|
||||
ConsumeToken();
|
||||
}
|
||||
// Parse the init-declarator-list for a normal declaration.
|
||||
ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
|
||||
}
|
||||
|
||||
/// ParseFunctionDefinition - We parsed and verified that the specified
|
||||
|
@ -282,33 +252,8 @@ void Parser::ParseFunctionDefinition(Declarator &D) {
|
|||
// int foo(a,b) int a; float b; {}
|
||||
if (!FnTypeInfo.Fun.hasPrototype && !FnTypeInfo.Fun.isEmpty) {
|
||||
// Read all the argument declarations.
|
||||
while (isDeclarationSpecifier()) {
|
||||
// Parse the common declaration-specifiers piece.
|
||||
DeclSpec DS;
|
||||
ParseDeclarationSpecifiers(DS);
|
||||
|
||||
Declarator DeclaratorInfo(DS, Declarator::FileContext);
|
||||
ParseDeclarator(DeclaratorInfo);
|
||||
|
||||
while (Tok.getKind() == tok::comma) {
|
||||
// Consume the comma.
|
||||
ConsumeToken();
|
||||
|
||||
// Parse the next declarator.
|
||||
DeclaratorInfo.clear();
|
||||
ParseDeclarator(DeclaratorInfo);
|
||||
}
|
||||
|
||||
if (Tok.getKind() == tok::semi) {
|
||||
ConsumeToken();
|
||||
} else {
|
||||
Diag(Tok, diag::err_expected_semi_knr_fn_body);
|
||||
// Skip to end of block or statement
|
||||
SkipUntil(tok::l_brace, true);
|
||||
if (Tok.getKind() == tok::semi)
|
||||
ConsumeToken();
|
||||
}
|
||||
}
|
||||
while (isDeclarationSpecifier())
|
||||
ParseDeclaration(Declarator::KNRTypeListContext);
|
||||
|
||||
// Note, check that we got them all.
|
||||
} else {
|
||||
|
|
|
@ -266,8 +266,8 @@ DIAG(err_expected_rparen, ERROR,
|
|||
"expected ')'")
|
||||
DIAG(err_expected_rbrace, ERROR,
|
||||
"expected '}' to end compound statement ('{}' block)")
|
||||
DIAG(err_expected_semi_knr_fn_body, ERROR,
|
||||
"expected ';' at end of K&R-style function argument declaration list")
|
||||
DIAG(err_expected_semi_decl_list, ERROR,
|
||||
"expected ';' at end of declaration list")
|
||||
DIAG(err_expected_fn_body, ERROR,
|
||||
"expected function body after function declarator")
|
||||
DIAG(err_expected_after_declarator, ERROR,
|
||||
|
|
|
@ -169,6 +169,9 @@ private:
|
|||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// C99 6.7: Declarations.
|
||||
|
||||
void ParseDeclaration(unsigned Context);
|
||||
void ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D);
|
||||
void ParseDeclarationSpecifiers(DeclSpec &DS);
|
||||
bool isDeclarationSpecifier() const;
|
||||
|
||||
|
|
|
@ -15,4 +15,5 @@ int test2() {
|
|||
for (;;)
|
||||
for (9;0;2)
|
||||
;
|
||||
for (int X = 0; 0; 0);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue