Fix handling of implicit int, resolving PR2012 and reverting (and
subsuming) my patch for PR1999.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@49251 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 7d15e98..9b8ecf8 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -1340,7 +1340,6 @@
         ParmDecl.AddAttributes(ParseAttributes());
       
       // Verify C99 6.7.5.3p2: The only SCS allowed is 'register'.
-      // NOTE: we could trivially allow 'int foo(auto int X)' if we wanted.
       if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified &&
           DS.getStorageClassSpec() != DeclSpec::SCS_register) {
         Diag(DS.getStorageClassSpecLoc(),
@@ -1353,11 +1352,6 @@
         DS.ClearStorageClassSpecs();
       }
       
-      // Inform the actions module about the parameter declarator, so it gets
-      // added to the current scope.
-      Action::TypeResult ParamTy =
-        Actions.ActOnParamDeclaratorType(CurScope, ParmDecl);
-        
       // Remember this parsed parameter in ParamInfo.
       IdentifierInfo *ParmII = ParmDecl.getIdentifier();
       
@@ -1366,28 +1360,28 @@
         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 if (!DS.hasTypeSpecifier() &&
-                 (getLang().C99 || getLang().CPlusPlus)) {
-        // Otherwise, if something was specified but a type specifier wasn't,
-        // (e.g. "x" or "restrict x" or "restrict"), this is a use of implicit
-        // int.  This is valid in C90, but not in C99 or C++.
-        if (ParmII)
-          Diag(ParmDecl.getIdentifierLoc(),
-               diag::ext_param_requires_type_specifier, ParmII->getName());
-        else
-          Diag(DSStart, diag::ext_anon_param_requires_type_specifier);
-      }
+      } 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.
         
-      ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII, 
-        ParmDecl.getIdentifierLoc(), ParamTy.Val, ParmDecl.getInvalidType(),
-        ParmDecl.getDeclSpec().TakeAttributes()));
+        // 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;
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 7609124..cd99fc0 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -467,7 +467,7 @@
   // If this is C90 and the declspecs were completely missing, fudge in an
   // implicit int.  We do this here because this is the only place where
   // declaration-specifiers are completely optional in the grammar.
-  if (getLang().isC90() && !D.getDeclSpec().getParsedSpecifiers() == 0) {
+  if (getLang().ImplicitInt && D.getDeclSpec().getParsedSpecifiers() == 0) {
     const char *PrevSpec;
     D.getDeclSpec().SetTypeSpecType(DeclSpec::TST_int, D.getIdentifierLoc(),
                                     PrevSpec);
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index ca56c56..d46e997 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -27,7 +27,7 @@
   QualType Result;
   
   switch (DS.getTypeSpecType()) {
-  default: return QualType(); // FIXME: Handle unimp cases!
+  default: assert(0 && "Unknown TypeSpecType!");
   case DeclSpec::TST_void:
     Result = Context.VoidTy;
     break;
@@ -42,7 +42,29 @@
       Result = Context.UnsignedCharTy;
     }
     break;
-  case DeclSpec::TST_unspecified:  // Unspecific typespec defaults to int.
+  case DeclSpec::TST_unspecified:
+    // Unspecified typespec defaults to int in C90.  However, the C90 grammar
+    // [C90 6.5] only allows a decl-spec if there was *some* type-specifier,
+    // type-qualifier, or storage-class-specifier.  If not, emit an extwarn.
+    // Note that the one exception to this is function definitions, which are
+    // allowed to be completely missing a declspec.  This is handled in the
+    // parser already though by it pretending to have seen an 'int' in this
+    // case.
+    if (getLangOptions().ImplicitInt) {
+      if ((DS.getParsedSpecifiers() & (DeclSpec::PQ_StorageClassSpecifier |
+                                       DeclSpec::PQ_TypeSpecifier |
+                                       DeclSpec::PQ_TypeQualifier)) == 0)
+        Diag(DS.getSourceRange().getBegin(), diag::ext_missing_declspec);
+    } else {
+      // C99 and C++ require a type specifier.  For example, C99 6.7.2p2 says:
+      // "At least one type specifier shall be given in the declaration
+      // specifiers in each declaration, and in the specifier-qualifier list in
+      // each struct declaration and type name."
+      if (!DS.hasTypeSpecifier())
+        Diag(DS.getSourceRange().getBegin(), diag::ext_missing_type_specifier);
+    }
+      
+    // FALL THROUGH.  
   case DeclSpec::TST_int: {
     if (DS.getTypeSpecSign() != DeclSpec::TSS_unsigned) {
       switch (DS.getTypeSpecWidth()) {