[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