[cfe-commits] r85924 - in /cfe/trunk: include/clang/Parse/Parser.h lib/Parse/ParseDecl.cpp lib/Parse/ParseStmt.cpp lib/Parse/Parser.cpp test/Lexer/block_cmt_end.c test/Sema/decl-invalid.c test/Sema/init.c
John McCall
rjmccall at apple.com
Tue Nov 3 11:26:08 PST 2009
Author: rjmccall
Date: Tue Nov 3 13:26:08 2009
New Revision: 85924
URL: http://llvm.org/viewvc/llvm-project?rev=85924&view=rev
Log:
Reorganize the parsing of decl groups / function definitions so that
declarators are parsed primarily within a single function (at least for
these cases). Remove some excess diagnostics arising during parse failures.
Modified:
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/ParseStmt.cpp
cfe/trunk/lib/Parse/Parser.cpp
cfe/trunk/test/Lexer/block_cmt_end.c
cfe/trunk/test/Sema/decl-invalid.c
cfe/trunk/test/Sema/init.c
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=85924&r1=85923&r2=85924&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Tue Nov 3 13:26:08 2009
@@ -950,11 +950,12 @@
DeclGroupPtrTy ParseDeclaration(unsigned Context, SourceLocation &DeclEnd);
DeclGroupPtrTy ParseSimpleDeclaration(unsigned Context,
- SourceLocation &DeclEnd,
- bool RequireSemi = true);
+ SourceLocation &DeclEnd);
+ DeclGroupPtrTy ParseDeclGroup(DeclSpec &DS, unsigned Context,
+ bool AllowFunctionDefinitions,
+ SourceLocation *DeclEnd = 0);
DeclPtrTy ParseDeclarationAfterDeclarator(Declarator &D,
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo());
- DeclGroupPtrTy ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D);
DeclPtrTy ParseFunctionStatementBody(DeclPtrTy Decl);
DeclPtrTy ParseFunctionTryBlock(DeclPtrTy Decl);
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=85924&r1=85923&r2=85924&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Tue Nov 3 13:26:08 2009
@@ -336,8 +336,7 @@
/// If RequireSemi is false, this does not check for a ';' at the end of the
/// declaration.
Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context,
- SourceLocation &DeclEnd,
- bool RequireSemi) {
+ SourceLocation &DeclEnd) {
// Parse the common declaration-specifiers piece.
DeclSpec DS;
ParseDeclarationSpecifiers(DS);
@@ -350,29 +349,102 @@
return Actions.ConvertDeclToDeclGroup(TheDecl);
}
- Declarator DeclaratorInfo(DS, (Declarator::TheContext)Context);
- ParseDeclarator(DeclaratorInfo);
+ DeclGroupPtrTy DG = ParseDeclGroup(DS, Context, /*FunctionDefs=*/ false,
+ &DeclEnd);
+ return DG;
+}
- DeclGroupPtrTy DG =
- ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
+/// ParseDeclGroup - Having concluded that this is either a function
+/// definition or a group of object declarations, actually parse the
+/// result.
+Parser::DeclGroupPtrTy Parser::ParseDeclGroup(DeclSpec &DS, unsigned Context,
+ bool AllowFunctionDefinitions,
+ SourceLocation *DeclEnd) {
+ // Parse the first declarator.
+ Declarator D(DS, static_cast<Declarator::TheContext>(Context));
+ ParseDeclarator(D);
+
+ // Bail out if the first declarator didn't seem well-formed.
+ if (!D.hasName() && !D.mayOmitIdentifier()) {
+ // Skip until ; or }.
+ SkipUntil(tok::r_brace, true, true);
+ if (Tok.is(tok::semi))
+ ConsumeToken();
+ return DeclGroupPtrTy();
+ }
- DeclEnd = Tok.getLocation();
+ if (AllowFunctionDefinitions && D.isFunctionDeclarator()) {
+ if (isDeclarationAfterDeclarator()) {
+ // Fall though. We have to check this first, though, because
+ // __attribute__ might be the start of a function definition in
+ // (extended) K&R C.
+ } else if (isStartOfFunctionDefinition()) {
+ if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
+ Diag(Tok, diag::err_function_declared_typedef);
- // If the client wants to check what comes after the declaration, just return
- // immediately without checking anything!
- if (!RequireSemi) return DG;
+ // Recover by treating the 'typedef' as spurious.
+ DS.ClearStorageClassSpecs();
+ }
- if (Tok.is(tok::semi)) {
- ConsumeToken();
- return DG;
+ DeclPtrTy TheDecl = ParseFunctionDefinition(D);
+ return Actions.ConvertDeclToDeclGroup(TheDecl);
+ } else {
+ Diag(Tok, diag::err_expected_fn_body);
+ SkipUntil(tok::semi);
+ return DeclGroupPtrTy();
+ }
}
- Diag(Tok, diag::err_expected_semi_declaration);
- // Skip to end of block or statement
- SkipUntil(tok::r_brace, true, true);
- if (Tok.is(tok::semi))
+ llvm::SmallVector<DeclPtrTy, 8> DeclsInGroup;
+ DeclPtrTy FirstDecl = ParseDeclarationAfterDeclarator(D);
+ if (FirstDecl.get())
+ DeclsInGroup.push_back(FirstDecl);
+
+ // If we don't have a comma, it is either the end of the list (a ';') or an
+ // error, bail out.
+ while (Tok.is(tok::comma)) {
+ // Consume the comma.
ConsumeToken();
- return DG;
+
+ // Parse the next declarator.
+ D.clear();
+
+ // Accept attributes in an init-declarator. In the first declarator in a
+ // declaration, these would be part of the declspec. In subsequent
+ // declarators, they become part of the declarator itself, so that they
+ // don't apply to declarators after *this* one. Examples:
+ // short __attribute__((common)) var; -> declspec
+ // short var __attribute__((common)); -> declarator
+ // short x, __attribute__((common)) var; -> declarator
+ if (Tok.is(tok::kw___attribute)) {
+ SourceLocation Loc;
+ AttributeList *AttrList = ParseAttributes(&Loc);
+ D.AddAttributes(AttrList, Loc);
+ }
+
+ ParseDeclarator(D);
+
+ DeclPtrTy ThisDecl = ParseDeclarationAfterDeclarator(D);
+ if (ThisDecl.get())
+ DeclsInGroup.push_back(ThisDecl);
+ }
+
+ if (DeclEnd)
+ *DeclEnd = Tok.getLocation();
+
+ if (Context != Declarator::ForContext &&
+ ExpectAndConsume(tok::semi,
+ Context == Declarator::FileContext
+ ? diag::err_invalid_token_after_toplevel_declarator
+ : diag::err_expected_semi_declaration)) {
+ SkipUntil(tok::r_brace, true, true);
+ if (Tok.is(tok::semi))
+ ConsumeToken();
+ }
+
+ return Actions.FinalizeDeclaratorGroup(CurScope, DS,
+ DeclsInGroup.data(),
+ DeclsInGroup.size());
}
/// \brief Parse 'declaration' after parsing 'declaration-specifiers
@@ -498,63 +570,6 @@
return ThisDecl;
}
-/// ParseInitDeclaratorListAfterFirstDeclarator - Parse 'declaration' after
-/// parsing 'declaration-specifiers declarator'. This method is split out this
-/// way to handle the ambiguity between top-level function-definitions and
-/// declarations.
-///
-/// init-declarator-list: [C99 6.7]
-/// init-declarator
-/// init-declarator-list ',' init-declarator
-///
-/// According to the standard grammar, =default and =delete are function
-/// definitions, but that definitely doesn't fit with the parser here.
-///
-Parser::DeclGroupPtrTy Parser::
-ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
- // Declarators may be grouped together ("int X, *Y, Z();"). Remember the decls
- // that we parse together here.
- llvm::SmallVector<DeclPtrTy, 8> DeclsInGroup;
-
- // At this point, we know that it is not a function definition. Parse the
- // rest of the init-declarator-list.
- while (1) {
- DeclPtrTy ThisDecl = ParseDeclarationAfterDeclarator(D);
- if (ThisDecl.get())
- DeclsInGroup.push_back(ThisDecl);
-
- // If we don't have a comma, it is either the end of the list (a ';') or an
- // error, bail out.
- if (Tok.isNot(tok::comma))
- break;
-
- // Consume the comma.
- ConsumeToken();
-
- // Parse the next declarator.
- D.clear();
-
- // Accept attributes in an init-declarator. In the first declarator in a
- // declaration, these would be part of the declspec. In subsequent
- // declarators, they become part of the declarator itself, so that they
- // don't apply to declarators after *this* one. Examples:
- // short __attribute__((common)) var; -> declspec
- // short var __attribute__((common)); -> declarator
- // short x, __attribute__((common)) var; -> declarator
- if (Tok.is(tok::kw___attribute)) {
- SourceLocation Loc;
- AttributeList *AttrList = ParseAttributes(&Loc);
- D.AddAttributes(AttrList, Loc);
- }
-
- ParseDeclarator(D);
- }
-
- return Actions.FinalizeDeclaratorGroup(CurScope, D.getDeclSpec(),
- DeclsInGroup.data(),
- DeclsInGroup.size());
-}
-
/// ParseSpecifierQualifierList
/// specifier-qualifier-list:
/// type-specifier specifier-qualifier-list[opt]
@@ -2118,7 +2133,6 @@
/// '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt]
void Parser::ParseDeclaratorInternal(Declarator &D,
DirectDeclParseFunction DirectDeclParser) {
-
if (Diags.hasAllExtensionsSilenced())
D.setExtension();
// C++ member pointers start with a '::' or a nested-name.
Modified: cfe/trunk/lib/Parse/ParseStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=85924&r1=85923&r2=85924&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseStmt.cpp (original)
+++ cfe/trunk/lib/Parse/ParseStmt.cpp Tue Nov 3 13:26:08 2009
@@ -938,8 +938,7 @@
Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
- DeclGroupPtrTy DG = ParseSimpleDeclaration(Declarator::ForContext, DeclEnd,
- false);
+ DeclGroupPtrTy DG = ParseSimpleDeclaration(Declarator::ForContext, DeclEnd);
FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
if (Tok.is(tok::semi)) { // for (int x = 4;
Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=85924&r1=85923&r2=85924&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Tue Nov 3 13:26:08 2009
@@ -548,6 +548,7 @@
SkipUntil(tok::semi); // FIXME: better skip?
return DeclGroupPtrTy();
}
+
const char *PrevSpec = 0;
unsigned DiagID;
if (DS.SetTypeSpecType(DeclSpec::TST_unspecified, AtLoc, PrevSpec, DiagID))
@@ -571,54 +572,7 @@
return Actions.ConvertDeclToDeclGroup(TheDecl);
}
- // Parse the first declarator.
- Declarator DeclaratorInfo(DS, Declarator::FileContext);
- ParseDeclarator(DeclaratorInfo);
- // Error parsing the declarator?
- if (!DeclaratorInfo.hasName()) {
- // If so, skip until the semi-colon or a }.
- SkipUntil(tok::r_brace, true, true);
- if (Tok.is(tok::semi))
- ConsumeToken();
- return DeclGroupPtrTy();
- }
-
- // If we have a declaration or declarator list, handle it.
- if (isDeclarationAfterDeclarator()) {
- // Parse the init-declarator-list for a normal declaration.
- DeclGroupPtrTy DG =
- ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
- // Eat the semi colon after the declaration.
- ExpectAndConsume(tok::semi, diag::err_expected_semi_declaration);
- return DG;
- }
-
- if (DeclaratorInfo.isFunctionDeclarator() &&
- isStartOfFunctionDefinition()) {
- if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
- Diag(Tok, diag::err_function_declared_typedef);
-
- if (Tok.is(tok::l_brace)) {
- // This recovery skips the entire function body. It would be nice
- // to simply call ParseFunctionDefinition() below, however Sema
- // assumes the declarator represents a function, not a typedef.
- ConsumeBrace();
- SkipUntil(tok::r_brace, true);
- } else {
- SkipUntil(tok::semi);
- }
- return DeclGroupPtrTy();
- }
- DeclPtrTy TheDecl = ParseFunctionDefinition(DeclaratorInfo);
- return Actions.ConvertDeclToDeclGroup(TheDecl);
- }
-
- if (DeclaratorInfo.isFunctionDeclarator())
- Diag(Tok, diag::err_expected_fn_body);
- else
- Diag(Tok, diag::err_invalid_token_after_toplevel_declarator);
- SkipUntil(tok::semi);
- return DeclGroupPtrTy();
+ return ParseDeclGroup(DS, Declarator::FileContext, true);
}
/// ParseFunctionDefinition - We parsed and verified that the specified
Modified: cfe/trunk/test/Lexer/block_cmt_end.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Lexer/block_cmt_end.c?rev=85924&r1=85923&r2=85924&view=diff
==============================================================================
--- cfe/trunk/test/Lexer/block_cmt_end.c (original)
+++ cfe/trunk/test/Lexer/block_cmt_end.c Tue Nov 3 13:26:08 2009
@@ -17,7 +17,7 @@
/* expected-warning {{escaped newline}} expected-warning {{backslash and newline}} *\
/
-int bar
+int bar /* expected-error {{invalid token after top level declarator}} */
/* xyz
@@ -26,7 +26,7 @@
/* expected-warning {{escaped newline between}} expected-warning {{backslash and newline separated by space}} expected-warning {{trigraph ends block comment}} *??/
/
-foo /* expected-error {{invalid token after top level declarator}} */
+foo
// rdar://6060752 - We should not get warnings about trigraphs in comments:
Modified: cfe/trunk/test/Sema/decl-invalid.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/decl-invalid.c?rev=85924&r1=85923&r2=85924&view=diff
==============================================================================
--- cfe/trunk/test/Sema/decl-invalid.c (original)
+++ cfe/trunk/test/Sema/decl-invalid.c Tue Nov 3 13:26:08 2009
@@ -10,8 +10,7 @@
int r[x()]; // expected-error {{size of array has non-integer type 'void'}}
static y ?; // expected-error{{unknown type name 'y'}} \
- expected-error{{expected identifier or '('}} \
- expected-error{{expected ';' at end of declaration}}
+ expected-error{{expected identifier or '('}}
}
int; // expected-error {{declaration does not declare anything}}
Modified: cfe/trunk/test/Sema/init.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/init.c?rev=85924&r1=85923&r2=85924&view=diff
==============================================================================
--- cfe/trunk/test/Sema/init.c (original)
+++ cfe/trunk/test/Sema/init.c Tue Nov 3 13:26:08 2009
@@ -21,7 +21,7 @@
int test() {
int a[10];
int b[10] = a; // expected-error {{initialization with '{...}' expected}}
-int +; // expected-error {{expected identifier or '('}} expected-error {{expected ';' at end of declaration}}
+int +; // expected-error {{expected identifier or '('}}
}
More information about the cfe-commits
mailing list