now that identifier list parsing is split out, simplify handling of
normal typed argument lists.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@49272 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 0cf97d2..3ea0d9f 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -447,7 +447,8 @@
       isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_extern, Loc, PrevSpec);
       break;
     case tok::kw___private_extern__:
-      isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_private_extern, Loc, PrevSpec);
+      isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_private_extern, Loc,
+                                         PrevSpec);
       break;
     case tok::kw_static:
       if (DS.isThreadSpecified())
@@ -1241,18 +1242,16 @@
   
   // Okay, this is the parameter list of a function definition, or it is an
   // identifier list of a K&R-style function.
-  bool IsVariadic;
-  bool HasPrototype;
-  bool ErrorEmitted = false;
-
-  // Build up an array of information about the parsed arguments.
-  llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
-  llvm::SmallSet<const IdentifierInfo*, 16> ParamsSoFar;
   
   if (Tok.is(tok::r_paren)) {
+    // Remember that we parsed a function type, and remember the attributes.
     // int() -> no prototype, no '...'.
-    IsVariadic   = false;
-    HasPrototype = false;
+    D.AddTypeInfo(DeclaratorChunk::getFunction(/*prototype*/ false,
+                                               /*variadic*/ false,
+                                               /*arglist*/ 0, 0, LParenLoc));
+    
+    ConsumeParen();  // Eat the closing ')'.
+    return;
   } else if (Tok.is(tok::identifier) &&
              // K&R identifier lists can't have typedefs as identifiers, per
              // C99 6.7.5.3p11.
@@ -1260,120 +1259,112 @@
     // Identifier list.  Note that '(' identifier-list ')' is only allowed for
     // normal declarators, not for abstract-declarators.
     return ParseFunctionDeclaratorIdentifierList(LParenLoc, D);
-  } else {
-    // Finally, a normal, non-empty parameter type list.
-    
-    // Enter function-declaration scope, limiting any declarators for struct
-    // tags to the function prototype scope.
-    // FIXME: is this needed?
-    EnterScope(Scope::DeclScope);
-    
-    IsVariadic = false;
-    while (1) {
-      if (Tok.is(tok::ellipsis)) {
-        IsVariadic = true;
-
-        // Check to see if this is "void(...)" which is not allowed.
-        if (ParamInfo.empty()) {
-          // Otherwise, parse parameter type list.  If it starts with an
-          // ellipsis,  diagnose the malformed function.
-          Diag(Tok, diag::err_ellipsis_first_arg);
-          IsVariadic = false;       // Treat this like 'void()'.
-        }
-
-        // Consume the ellipsis.
-        ConsumeToken();
-        break;
-      }
+  }
+  
+  // Finally, a normal, non-empty parameter type list.
+  
+  // Build up an array of information about the parsed arguments.
+  llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
+  llvm::SmallSet<const IdentifierInfo*, 16> ParamsSoFar;
+  
+  // Enter function-declaration scope, limiting any declarators for struct
+  // tags to the function prototype scope.
+  // FIXME: is this needed?
+  EnterScope(Scope::DeclScope);
+  
+  bool IsVariadic = false;
+  while (1) {
+    if (Tok.is(tok::ellipsis)) {
+      IsVariadic = true;
       
-      SourceLocation DSStart = Tok.getLocation();
-      
-      // Parse the declaration-specifiers.
-      DeclSpec DS;
-      ParseDeclarationSpecifiers(DS);
-
-      // Parse the declarator.  This is "PrototypeContext", because we must
-      // accept either 'declarator' or 'abstract-declarator' here.
-      Declarator ParmDecl(DS, Declarator::PrototypeContext);
-      ParseDeclarator(ParmDecl);
-
-      // Parse GNU attributes, if present.
-      if (Tok.is(tok::kw___attribute))
-        ParmDecl.AddAttributes(ParseAttributes());
-      
-      // Verify C99 6.7.5.3p2: The only SCS allowed is 'register'.
-      if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified &&
-          DS.getStorageClassSpec() != DeclSpec::SCS_register) {
-        Diag(DS.getStorageClassSpecLoc(),
-             diag::err_invalid_storage_class_in_func_decl);
-        DS.ClearStorageClassSpecs();
-      }
-      if (DS.isThreadSpecified()) {
-        Diag(DS.getThreadSpecLoc(),
-             diag::err_invalid_storage_class_in_func_decl);
-        DS.ClearStorageClassSpecs();
-      }
-      
-      // Remember this parsed parameter in ParamInfo.
-      IdentifierInfo *ParmII = ParmDecl.getIdentifier();
-      
-      // Verify that the argument identifier has not already been mentioned.
-      if (ParmII && !ParamsSoFar.insert(ParmII)) {
-        Diag(ParmDecl.getIdentifierLoc(), diag::err_param_redefinition,
-             ParmII->getName());
-        ParmII = 0;
-        ParmDecl.setInvalidType(true);
+      // Check to see if this is "void(...)" which is not allowed.
+      if (ParamInfo.empty()) {
+        // Otherwise, parse parameter type list.  If it starts with an
+        // ellipsis,  diagnose the malformed function.
+        Diag(Tok, diag::err_ellipsis_first_arg);
+        IsVariadic = false;       // Treat this like 'void()'.
       }
 
-      // If no parameter was specified, verify that *something* was specified,
-      // otherwise we have a missing type and identifier.
-      if (DS.getParsedSpecifiers() == DeclSpec::PQ_None && 
-          ParmDecl.getIdentifier() == 0 && ParmDecl.getNumTypeObjects() == 0) {
-        // Completely missing, emit error.
-        Diag(DSStart, diag::err_missing_param);
-      } else {
-        // Otherwise, we have something.  Add it and let semantic analysis try
-        // to grok it and add the result to the ParamInfo we are building.
-        
-        // Inform the actions module about the parameter declarator, so it gets
-        // added to the current scope.
-        Action::TypeResult ParamTy =
-          Actions.ActOnParamDeclaratorType(CurScope, ParmDecl);
-        
-        ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII, 
-            ParmDecl.getIdentifierLoc(), ParamTy.Val, ParmDecl.getInvalidType(),
-            ParmDecl.getDeclSpec().TakeAttributes()));
-      }
-
-      // If the next token is a comma, consume it and keep reading arguments.
-      if (Tok.isNot(tok::comma)) break;
-      
-      // Consume the comma.
-      ConsumeToken();
+      ConsumeToken();     // Consume the ellipsis.
+      break;
     }
     
-    HasPrototype = true;
+    SourceLocation DSStart = Tok.getLocation();
     
-    // Leave prototype scope.
-    ExitScope();
+    // Parse the declaration-specifiers.
+    DeclSpec DS;
+    ParseDeclarationSpecifiers(DS);
+
+    // Parse the declarator.  This is "PrototypeContext", because we must
+    // accept either 'declarator' or 'abstract-declarator' here.
+    Declarator ParmDecl(DS, Declarator::PrototypeContext);
+    ParseDeclarator(ParmDecl);
+
+    // Parse GNU attributes, if present.
+    if (Tok.is(tok::kw___attribute))
+      ParmDecl.AddAttributes(ParseAttributes());
+    
+    // Verify C99 6.7.5.3p2: The only SCS allowed is 'register'.
+    if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified &&
+        DS.getStorageClassSpec() != DeclSpec::SCS_register) {
+      Diag(DS.getStorageClassSpecLoc(),
+           diag::err_invalid_storage_class_in_func_decl);
+      DS.ClearStorageClassSpecs();
+    }
+    if (DS.isThreadSpecified()) {
+      Diag(DS.getThreadSpecLoc(),
+           diag::err_invalid_storage_class_in_func_decl);
+      DS.ClearStorageClassSpecs();
+    }
+    
+    // Remember this parsed parameter in ParamInfo.
+    IdentifierInfo *ParmII = ParmDecl.getIdentifier();
+    
+    // Verify that the argument identifier has not already been mentioned.
+    if (ParmII && !ParamsSoFar.insert(ParmII)) {
+      Diag(ParmDecl.getIdentifierLoc(), diag::err_param_redefinition,
+           ParmII->getName());
+      ParmII = 0;
+      ParmDecl.setInvalidType(true);
+    }
+
+    // If no parameter was specified, verify that *something* was specified,
+    // otherwise we have a missing type and identifier.
+    if (DS.getParsedSpecifiers() == DeclSpec::PQ_None && 
+        ParmDecl.getIdentifier() == 0 && ParmDecl.getNumTypeObjects() == 0) {
+      // Completely missing, emit error.
+      Diag(DSStart, diag::err_missing_param);
+    } else {
+      // Otherwise, we have something.  Add it and let semantic analysis try
+      // to grok it and add the result to the ParamInfo we are building.
+      
+      // Inform the actions module about the parameter declarator, so it gets
+      // added to the current scope.
+      Action::TypeResult ParamTy =
+        Actions.ActOnParamDeclaratorType(CurScope, ParmDecl);
+      
+      ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII, 
+          ParmDecl.getIdentifierLoc(), ParamTy.Val, ParmDecl.getInvalidType(),
+          ParmDecl.getDeclSpec().TakeAttributes()));
+    }
+
+    // If the next token is a comma, consume it and keep reading arguments.
+    if (Tok.isNot(tok::comma)) break;
+    
+    // Consume the comma.
+    ConsumeToken();
   }
   
+  // Leave prototype scope.
+  ExitScope();
+  
   // Remember that we parsed a function type, and remember the attributes.
-  if (!ErrorEmitted)
-    D.AddTypeInfo(DeclaratorChunk::getFunction(HasPrototype, IsVariadic,
-                                               &ParamInfo[0], ParamInfo.size(),
-                                               LParenLoc));
+  D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/true, IsVariadic,
+                                             &ParamInfo[0], ParamInfo.size(),
+                                             LParenLoc));
   
   // If we have the closing ')', eat it and we're done.
-  if (Tok.is(tok::r_paren)) {
-    ConsumeParen();
-  } else {
-    // If an error happened earlier parsing something else in the proto, don't
-    // issue another error.
-    if (!ErrorEmitted)
-      Diag(Tok, diag::err_expected_rparen);
-    SkipUntil(tok::r_paren);
-  }
+  MatchRHSPunctuation(tok::r_paren, LParenLoc);
 }