From 23c4b1883b13dc17484b7214091b73f3ba29096e Mon Sep 17 00:00:00 2001
From: Chris Lattner <sabre@nondot.org>
Date: Sun, 29 Mar 2009 17:18:04 +0000
Subject: [PATCH] hoist checks for ; and in out of
 ParseInitDeclaratorListAfterFirstDeclarator into ParseSimpleDeclaration, and
 improve a diagnostic.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68009 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/Basic/DiagnosticParseKinds.td |  2 +
 lib/Parse/ParseDecl.cpp                     | 56 ++++++++++-----------
 lib/Parse/Parser.cpp                        | 11 ++--
 test/Parser/typeof.c                        |  4 +-
 test/Sema/init.c                            |  2 +-
 5 files changed, 41 insertions(+), 34 deletions(-)

diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td
index 7b264d34613..ad996b7eeb5 100644
--- a/include/clang/Basic/DiagnosticParseKinds.td
+++ b/include/clang/Basic/DiagnosticParseKinds.td
@@ -78,6 +78,8 @@ def err_expected_rparen : Error<"expected ')'">;
 def err_expected_rsquare : Error<"expected ']'">;
 def err_expected_rbrace : Error<"expected '}'">;
 def err_expected_greater : Error<"expected '>'">;
+def err_expected_semi_declation : Error<
+  "expected ';' at end of declaration">;
 def err_expected_semi_decl_list : Error<
   "expected ';' at end of declaration list">;
 def ext_expected_semi_decl_list : Extension<
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 1f8522f094c..5de4dd4a7c6 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -273,7 +273,30 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context) {
   Declarator DeclaratorInfo(DS, (Declarator::TheContext)Context);
   ParseDeclarator(DeclaratorInfo);
   
-  return ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
+  DeclGroupPtrTy DG =
+    ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
+  
+  if (Tok.is(tok::semi)) {
+    ConsumeToken();
+    // for(is key; in keys) is error.
+    if (Context == Declarator::ForContext && isTokIdentifier_in())
+      Diag(Tok, diag::err_parse_error);
+    
+    return DG;
+  }
+  
+  // If this is an ObjC2 for-each loop, this is a successful declarator
+  // parse.  The syntax for these looks like:
+  // 'for' '(' declaration 'in' expr ')' statement
+  if (Context == Declarator::ForContext && isTokIdentifier_in())
+    return DG;
+  
+  Diag(Tok, diag::err_expected_semi_declation);
+  // Skip to end of block or statement
+  SkipUntil(tok::r_brace, true, true);
+  if (Tok.is(tok::semi))
+    ConsumeToken();
+  return DG;
 }
 
 
@@ -315,7 +338,7 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
       SourceLocation Loc;
       OwningExprResult AsmLabel(ParseSimpleAsm(&Loc));
       if (AsmLabel.isInvalid()) {
-        SkipUntil(tok::semi);
+        SkipUntil(tok::semi, true, true);
         return DeclGroupPtrTy();
       }
 
@@ -343,7 +366,7 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
       } else {
         OwningExprResult Init(ParseInitializer());
         if (Init.isInvalid()) {
-          SkipUntil(tok::semi);
+          SkipUntil(tok::semi, true, true);
           return DeclGroupPtrTy();
         }
         Actions.AddInitializerToDecl(ThisDecl, move(Init));
@@ -400,31 +423,8 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
     ParseDeclarator(D);
   }
   
-  if (Tok.is(tok::semi)) {
-    ConsumeToken();
-    // for(is key; in keys) is error.
-    if (D.getContext() == Declarator::ForContext && isTokIdentifier_in()) {
-      Diag(Tok, diag::err_parse_error);
-      return DeclGroupPtrTy();
-    }
-    
-    return Actions.FinalizeDeclaratorGroup(CurScope, &DeclsInGroup[0],
-                                           DeclsInGroup.size());
-  }
-  
-  // If this is an ObjC2 for-each loop, this is a successful declarator
-  // parse.  The syntax for these looks like:
-  // 'for' '(' declaration 'in' expr ')' statement
-  if (D.getContext() == Declarator::ForContext && isTokIdentifier_in())
-    return Actions.FinalizeDeclaratorGroup(CurScope, &DeclsInGroup[0],
-                                           DeclsInGroup.size());
-
-  Diag(Tok, diag::err_parse_error);
-  // Skip to end of block or statement
-  SkipUntil(tok::r_brace, true, true);
-  if (Tok.is(tok::semi))
-    ConsumeToken();
-  return DeclGroupPtrTy();
+  return Actions.FinalizeDeclaratorGroup(CurScope, &DeclsInGroup[0],
+                                         DeclsInGroup.size());
 }
 
 /// ParseSpecifierQualifierList
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 56f922d4005..b34c241fd1b 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -517,9 +517,13 @@ Parser::ParseDeclarationOrFunctionDefinition(
       Tok.is(tok::kw_asm) ||          // int X() __asm__ -> not a function def
       Tok.is(tok::kw___attribute) ||  // int X() __attr__ -> not a function def
       (getLang().CPlusPlus &&
-       Tok.is(tok::l_paren)) ) {      // int X(0) -> not a function def [C++]
+       Tok.is(tok::l_paren))) {       // int X(0) -> not a function def [C++]
     // Parse the init-declarator-list for a normal declaration.
-    return ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
+    DeclGroupPtrTy DG =
+      ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
+    // Eat the semi colon after the declaration.
+    ExpectAndConsume(tok::semi, diag::err_expected_semi_declation);
+    return DG;
   }
   
   
@@ -564,7 +568,8 @@ Parser::ParseDeclarationOrFunctionDefinition(
 /// [C90] function-definition: [C99 6.7.1] - implicit int result
 /// [C90]   decl-specs[opt] declarator declaration-list[opt] compound-statement
 /// [C++] function-definition: [C++ 8.4]
-///         decl-specifier-seq[opt] declarator ctor-initializer[opt] function-body
+///         decl-specifier-seq[opt] declarator ctor-initializer[opt]
+///         function-body
 /// [C++] function-definition: [C++ 8.4]
 ///         decl-specifier-seq[opt] declarator function-try-block [TODO]
 ///
diff --git a/test/Parser/typeof.c b/test/Parser/typeof.c
index 8cb16c36f2a..76e8d479fcf 100644
--- a/test/Parser/typeof.c
+++ b/test/Parser/typeof.c
@@ -9,8 +9,8 @@ static void test() {
   short typeof (int) aShortInt; // expected-error{{'short typeof' is invalid}} 
   int int ttt; // expected-error{{cannot combine with previous 'int' declaration specifier}}
   typeof(TInt) anInt; 
-  short TInt eee; // expected-error{{parse error}}
-  void ary[7] fff; // expected-error{{array has incomplete element type 'void'}} expected-error{{parse error}}
+  short TInt eee; // expected-error{{expected ';' at end of declaration}}
+  void ary[7] fff; // expected-error{{array has incomplete element type 'void'}} expected-error{{expected ';' at end of declaration}}
   typeof(void ary[7]) anIntError; // expected-error{{expected ')'}} expected-note {{to match this '('}}  expected-warning {{type specifier missing, defaults to 'int'}}
   typeof(const int) aci; 
   const typeof (*pi) aConstInt; 
diff --git a/test/Sema/init.c b/test/Sema/init.c
index 9430f312ad6..cbf75e1bb1c 100644
--- a/test/Sema/init.c
+++ b/test/Sema/init.c
@@ -20,7 +20,7 @@ int *h = &x;
 int test() {
 int a[10];
 int b[10] = a; // expected-error {{initialization with '{...}' expected}}
-int +; // expected-error {{expected identifier or '('}} expected-error {{parse error}}
+int +; // expected-error {{expected identifier or '('}} expected-error {{expected ';' at end of declaration}}
 }
 
 
-- 
GitLab