[cfe-commits] r49251 - in /cfe/trunk: Driver/clang.cpp include/clang/Basic/DiagnosticKinds.def include/clang/Basic/LangOptions.h include/clang/Parse/DeclSpec.h lib/Parse/ParseDecl.cpp lib/Parse/Parser.cpp lib/Sema/SemaType.cpp test/Parser/declarators.c test/Sema/c89.c test/Sema/function.c

Chris Lattner sabre at nondot.org
Fri Apr 4 23:32:51 PDT 2008


Author: lattner
Date: Sat Apr  5 01:32:51 2008
New Revision: 49251

URL: http://llvm.org/viewvc/llvm-project?rev=49251&view=rev
Log:
Fix handling of implicit int, resolving PR2012 and reverting (and
subsuming) my patch for PR1999.

Modified:
    cfe/trunk/Driver/clang.cpp
    cfe/trunk/include/clang/Basic/DiagnosticKinds.def
    cfe/trunk/include/clang/Basic/LangOptions.h
    cfe/trunk/include/clang/Parse/DeclSpec.h
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/test/Parser/declarators.c
    cfe/trunk/test/Sema/c89.c
    cfe/trunk/test/Sema/function.c

Modified: cfe/trunk/Driver/clang.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/clang.cpp?rev=49251&r1=49250&r2=49251&view=diff

==============================================================================
--- cfe/trunk/Driver/clang.cpp (original)
+++ cfe/trunk/Driver/clang.cpp Sat Apr  5 01:32:51 2008
@@ -400,6 +400,10 @@
     break;
   }
   
+  if (LangStd == lang_c89 || LangStd == lang_c94 || LangStd == lang_gnu89)
+    Options.ImplicitInt = 1;
+  else
+    Options.ImplicitInt = 0;
   Options.Trigraphs = 1; // -trigraphs or -ansi
   Options.DollarIdents = 1;  // FIXME: Really a target property.
   Options.PascalStrings = PascalStrings;

Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=49251&r1=49250&r2=49251&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Sat Apr  5 01:32:51 2008
@@ -257,6 +257,11 @@
      "ISO C does not allow an extra ';' outside of a function")
 DIAG(ext_extra_struct_semi, EXTENSION,
      "ISO C does not allow an extra ';' inside a struct or union")
+DIAG(ext_missing_declspec, EXTENSION,
+     "declaration specifier missing, defaulting to 'int'")
+DIAG(ext_missing_type_specifier, EXTENSION,
+     "type specifier missing, defaults to 'int'")
+
 DIAG(ext_duplicate_declspec, EXTENSION,
      "duplicate '%0' declaration specifier")
 DIAG(ext_plain_complex, EXTENSION,
@@ -539,8 +544,6 @@
      "invalid storage class specifier in function declarator")
 DIAG(ext_anon_param_requires_type_specifier, EXTENSION,
      "type specifier required for unnamed parameter, defaults to int")
-DIAG(ext_param_requires_type_specifier, EXTENSION,
-     "type specifier required for parameter '%0', defaults to int")
 DIAG(err_missing_param, ERROR,
      "expected parameter declarator")
 

Modified: cfe/trunk/include/clang/Basic/LangOptions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/LangOptions.h?rev=49251&r1=49250&r2=49251&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/LangOptions.h (original)
+++ cfe/trunk/include/clang/Basic/LangOptions.h Sat Apr  5 01:32:51 2008
@@ -22,8 +22,9 @@
 /// enabled, which controls the dialect of C that is accepted.
 struct LangOptions {
   unsigned Trigraphs         : 1;  // Trigraphs in source files.
-  unsigned BCPLComment       : 1;  // BCPL-style // comments.
+  unsigned BCPLComment       : 1;  // BCPL-style '//' comments.
   unsigned DollarIdents      : 1;  // '$' allowed in identifiers.
+  unsigned ImplicitInt       : 1;  // C89 implicit 'int'.
   unsigned Digraphs          : 1;  // C94, C99 and C++
   unsigned HexFloats         : 1;  // C99 Hexadecimal float constants.
   unsigned C99               : 1;  // C99 Support
@@ -42,15 +43,14 @@
   unsigned LaxVectorConversions : 1;
     
   LangOptions() {
-    Trigraphs = BCPLComment = DollarIdents = Digraphs = HexFloats = 0;
+    Trigraphs = BCPLComment = DollarIdents = ImplicitInt = Digraphs = 0;
+    HexFloats = 0;
     ObjC1 = ObjC2 = 0;
     C99 = Microsoft = CPlusPlus = CPlusPlus0x = NoExtensions = 0;
     CXXOperatorNames = PascalStrings = Boolean = WritableStrings = 0;
     LaxVectorConversions = 0;
   }
   
-  bool isC90() const { return !C99 && !CPlusPlus; }
-  
   /// Emit - Emit this LangOptions object to bitcode.
   void Emit(llvm::Serializer& S) const;
   

Modified: cfe/trunk/include/clang/Parse/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/DeclSpec.h?rev=49251&r1=49250&r2=49251&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Parse/DeclSpec.h Sat Apr  5 01:32:51 2008
@@ -664,7 +664,7 @@
   AttributeList *getAttributes() const { return AttrList; }
   
   void setInvalidType(bool flag) { InvalidType = flag; }
-  bool getInvalidType() { return InvalidType; }
+  bool getInvalidType() const { return InvalidType; }
 };
 
 } // end namespace clang

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=49251&r1=49250&r2=49251&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Sat Apr  5 01:32:51 2008
@@ -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;

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=49251&r1=49250&r2=49251&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Sat Apr  5 01:32:51 2008
@@ -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);

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=49251&r1=49250&r2=49251&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Sat Apr  5 01:32:51 2008
@@ -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()) {

Modified: cfe/trunk/test/Parser/declarators.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/declarators.c?rev=49251&r1=49250&r2=49251&view=diff

==============================================================================
--- cfe/trunk/test/Parser/declarators.c (original)
+++ cfe/trunk/test/Parser/declarators.c Sat Apr  5 01:32:51 2008
@@ -6,7 +6,7 @@
 void f1(int [*]);
 void f2(int [const *]);
 void f3(int [volatile const*]);
-int f4(*XX)(void); /* expected-error {{cannot return}} expected-warning {{type specifier required}} */
+int f4(*XX)(void); /* expected-error {{cannot return}} expected-warning {{type specifier missing, defaults to 'int'}} */
 
 char ((((*X))));
 

Modified: cfe/trunk/test/Sema/c89.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/c89.c?rev=49251&r1=49250&r2=49251&view=diff

==============================================================================
--- cfe/trunk/test/Sema/c89.c (original)
+++ cfe/trunk/test/Sema/c89.c Sat Apr  5 01:32:51 2008
@@ -36,6 +36,14 @@
 
 
 /* Implicit int, always ok */
-foo() {}
+test6() {}
+
+/* PR2012 */
+test7;  /* expected-warning {{declaration specifier missing, defaulting to 'int'}} */
+
+void test8(int, x);  /* expected-warning {{declaration specifier missing, defaulting to 'int'}} */
+
+typedef int sometype;
+int a(sometype, y) {return 0;}  /* expected-warning {{declaration specifier missing, defaulting to 'int'}} */
 
 

Modified: cfe/trunk/test/Sema/function.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/function.c?rev=49251&r1=49250&r2=49251&view=diff

==============================================================================
--- cfe/trunk/test/Sema/function.c (original)
+++ cfe/trunk/test/Sema/function.c Sat Apr  5 01:32:51 2008
@@ -18,7 +18,7 @@
 
 // PR1965
 int t5(b);          // expected-error {{parameter list without types}}
-int t6(int x, g);   // expected-warning {{type specifier required for parameter 'g'}}
+int t6(int x, g);   // expected-warning {{type specifier missing, defaults to 'int'}}
 
 int t7(, );       // expected-error {{expected parameter declarator}} expected-error {{expected parameter declarator}}
 int t8(, int a);  // expected-error {{expected parameter declarator}}





More information about the cfe-commits mailing list