[cfe-commits] r109865 - in /cfe/trunk: include/clang/Parse/DeclSpec.h lib/Parse/DeclSpec.cpp lib/Parse/ParseDeclCXX.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp test/SemaCXX/linkage-spec.cpp

Abramo Bagnara abramo.bagnara at gmail.com
Fri Jul 30 09:47:02 PDT 2010


Author: abramo
Date: Fri Jul 30 11:47:02 2010
New Revision: 109865

URL: http://llvm.org/viewvc/llvm-project?rev=109865&view=rev
Log:
Fixed typedef inside extern "C".

Modified:
    cfe/trunk/include/clang/Parse/DeclSpec.h
    cfe/trunk/lib/Parse/DeclSpec.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/SemaCXX/linkage-spec.cpp

Modified: cfe/trunk/include/clang/Parse/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/DeclSpec.h?rev=109865&r1=109864&r2=109865&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Parse/DeclSpec.h Fri Jul 30 11:47:02 2010
@@ -162,6 +162,7 @@
   // storage-class-specifier
   /*SCS*/unsigned StorageClassSpec : 3;
   bool SCS_thread_specified : 1;
+  bool SCS_extern_in_linkage_spec : 1;
 
   // type-specifier
   /*TSW*/unsigned TypeSpecWidth : 2;
@@ -221,9 +222,7 @@
 
   WrittenBuiltinSpecs writtenBS;
   void SaveWrittenBuiltinSpecs();
-  void SaveStorageSpecifierAsWritten() {
-    StorageClassSpecAsWritten = StorageClassSpec;
-  }
+  void SaveStorageSpecifierAsWritten();
 
   DeclSpec(const DeclSpec&);       // DO NOT IMPLEMENT
   void operator=(const DeclSpec&); // DO NOT IMPLEMENT
@@ -232,6 +231,7 @@
   DeclSpec()
     : StorageClassSpec(SCS_unspecified),
       SCS_thread_specified(false),
+      SCS_extern_in_linkage_spec(false),
       TypeSpecWidth(TSW_unspecified),
       TypeSpecComplex(TSC_unspecified),
       TypeSpecSign(TSS_unspecified),
@@ -262,6 +262,10 @@
   // storage-class-specifier
   SCS getStorageClassSpec() const { return (SCS)StorageClassSpec; }
   bool isThreadSpecified() const { return SCS_thread_specified; }
+  bool isExternInLinkageSpec() const { return SCS_extern_in_linkage_spec; }
+  void setExternInLinkageSpec(bool Value) {
+    SCS_extern_in_linkage_spec = Value;
+  }
 
   SourceLocation getStorageClassSpecLoc() const { return StorageClassSpecLoc; }
   SourceLocation getThreadSpecLoc() const { return SCS_threadLoc; }
@@ -269,6 +273,7 @@
   void ClearStorageClassSpecs() {
     StorageClassSpec     = DeclSpec::SCS_unspecified;
     SCS_thread_specified = false;
+    SCS_extern_in_linkage_spec = false;
     StorageClassSpecLoc  = SourceLocation();
     SCS_threadLoc        = SourceLocation();
   }

Modified: cfe/trunk/lib/Parse/DeclSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/DeclSpec.cpp?rev=109865&r1=109864&r2=109865&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/DeclSpec.cpp (original)
+++ cfe/trunk/lib/Parse/DeclSpec.cpp Fri Jul 30 11:47:02 2010
@@ -219,8 +219,15 @@
 bool DeclSpec::SetStorageClassSpec(SCS S, SourceLocation Loc,
                                    const char *&PrevSpec,
                                    unsigned &DiagID) {
-  if (StorageClassSpec != SCS_unspecified)
-    return BadSpecifier(S, (SCS)StorageClassSpec, PrevSpec, DiagID);
+  if (StorageClassSpec != SCS_unspecified) {
+    // Changing storage class is allowed only if the previous one
+    // was the 'extern' that is part of a linkage specification and
+    // the new storage class is 'typedef'.
+    if (!(SCS_extern_in_linkage_spec &&
+          StorageClassSpec == SCS_extern &&
+          S == SCS_typedef))
+      return BadSpecifier(S, (SCS)StorageClassSpec, PrevSpec, DiagID);
+  }
   StorageClassSpec = S;
   StorageClassSpecLoc = Loc;
   assert((unsigned)S == StorageClassSpec && "SCS constants overflow bitfield");
@@ -240,7 +247,6 @@
   return false;
 }
 
-
 /// These methods set the specified attribute of the DeclSpec, but return true
 /// and ignore the request if invalid (e.g. "extern" then "auto" is
 /// specified).
@@ -430,6 +436,15 @@
   }
 }
 
+void DeclSpec::SaveStorageSpecifierAsWritten() {
+  if (SCS_extern_in_linkage_spec && StorageClassSpec == SCS_extern)
+    // If 'extern' is part of a linkage specification,
+    // then it is not a storage class "as written".
+    StorageClassSpecAsWritten = SCS_unspecified;
+  else
+    StorageClassSpecAsWritten = StorageClassSpec;
+}
+
 /// Finish - This does final analysis of the declspec, rejecting things like
 /// "_Imaginary" (lacking an FP type).  This returns a diagnostic to issue or
 /// diag::NUM_DIAGNOSTICS if there is no error.  After calling this method,

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=109865&r1=109864&r2=109865&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Fri Jul 30 11:47:02 2010
@@ -196,6 +196,7 @@
   }
 
   if (Tok.isNot(tok::l_brace)) {
+    DS.setExternInLinkageSpec(true);
     ParseDeclarationOrFunctionDefinition(DS, Attr.AttrList);
     return Actions.ActOnFinishLinkageSpecification(getCurScope(), LinkageSpec,
                                                    SourceLocation());

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=109865&r1=109864&r2=109865&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Jul 30 11:47:02 2010
@@ -1667,21 +1667,11 @@
 /// StorageClassSpecToVarDeclStorageClass - Maps a DeclSpec::SCS to
 /// a VarDecl::StorageClass. Any error reporting is up to the caller:
 /// illegal input values are mapped to VarDecl::None.
-/// If the input declaration context is a linkage specification
-/// with no braces, then Extern is mapped to None.
 static VarDecl::StorageClass
-StorageClassSpecToVarDeclStorageClass(DeclSpec::SCS StorageClassSpec,
-                                      DeclContext *DC) {
+StorageClassSpecToVarDeclStorageClass(DeclSpec::SCS StorageClassSpec) {
   switch (StorageClassSpec) {
   case DeclSpec::SCS_unspecified:    return VarDecl::None;
-  case DeclSpec::SCS_extern:
-    // If the current context is a C++ linkage specification
-    // having no braces, then the keyword "extern" is properly part
-    // of the linkage specification itself, rather than being
-    // the written storage class specifier.
-    return (DC && isa<LinkageSpecDecl>(DC) &&
-            !cast<LinkageSpecDecl>(DC)->hasBraces())
-      ? VarDecl::None : VarDecl::Extern;
+  case DeclSpec::SCS_extern:         return VarDecl::Extern;
   case DeclSpec::SCS_static:         return VarDecl::Static;
   case DeclSpec::SCS_auto:           return VarDecl::Auto;
   case DeclSpec::SCS_register:       return VarDecl::Register;
@@ -1696,21 +1686,11 @@
 /// StorageClassSpecToFunctionDeclStorageClass - Maps a DeclSpec::SCS to
 /// a FunctionDecl::StorageClass. Any error reporting is up to the caller:
 /// illegal input values are mapped to FunctionDecl::None.
-/// If the input declaration context is a linkage specification
-/// with no braces, then Extern is mapped to None.
 static FunctionDecl::StorageClass
-StorageClassSpecToFunctionDeclStorageClass(DeclSpec::SCS StorageClassSpec,
-                                           DeclContext *DC) {
+StorageClassSpecToFunctionDeclStorageClass(DeclSpec::SCS StorageClassSpec) {
   switch (StorageClassSpec) {
   case DeclSpec::SCS_unspecified:    return FunctionDecl::None;
-  case DeclSpec::SCS_extern:
-    // If the current context is a C++ linkage specification
-    // having no braces, then the keyword "extern" is properly part
-    // of the linkage specification itself, rather than being
-    // the written storage class specifier.
-    return (DC && isa<LinkageSpecDecl>(DC) &&
-            !cast<LinkageSpecDecl>(DC)->hasBraces())
-      ? FunctionDecl::None : FunctionDecl::Extern;
+  case DeclSpec::SCS_extern:         return FunctionDecl::Extern;
   case DeclSpec::SCS_static:         return FunctionDecl::Static;
   case DeclSpec::SCS_private_extern: return FunctionDecl::PrivateExtern;
     // Illegal SCSs map to None: error reporting is up to the caller.
@@ -1851,7 +1831,7 @@
     DeclSpec::SCS SCSpec = DS.getStorageClassSpec();
     assert(SCSpec != DeclSpec::SCS_typedef &&
            "Parser allowed 'typedef' as storage class VarDecl.");
-    VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(SCSpec, 0);
+    VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(SCSpec);
     if (SCSpec == DeclSpec::SCS_mutable) {
       // mutable can only appear on non-static class members, so it's always
       // an error here
@@ -1861,7 +1841,7 @@
     }
     SCSpec = DS.getStorageClassSpecAsWritten();
     VarDecl::StorageClass SCAsWritten
-      = StorageClassSpecToVarDeclStorageClass(SCSpec, 0);
+      = StorageClassSpecToVarDeclStorageClass(SCSpec);
 
     Anon = VarDecl::Create(Context, Owner, Record->getLocation(),
                            /*IdentifierInfo=*/0,
@@ -2521,7 +2501,7 @@
   DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec();
   assert(SCSpec != DeclSpec::SCS_typedef &&
          "Parser allowed 'typedef' as storage class VarDecl.");
-  VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(SCSpec, 0);
+  VarDecl::StorageClass SC = StorageClassSpecToVarDeclStorageClass(SCSpec);
   if (SCSpec == DeclSpec::SCS_mutable) {
     // mutable can only appear on non-static class members, so it's always
     // an error here
@@ -2531,7 +2511,7 @@
   }
   SCSpec = D.getDeclSpec().getStorageClassSpecAsWritten();
   VarDecl::StorageClass SCAsWritten
-    = StorageClassSpecToVarDeclStorageClass(SCSpec, DC);
+    = StorageClassSpecToVarDeclStorageClass(SCSpec);
 
   IdentifierInfo *II = Name.getAsIdentifierInfo();
   if (!II) {
@@ -3016,7 +2996,7 @@
 
   DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpecAsWritten();
   FunctionDecl::StorageClass SCAsWritten
-    = StorageClassSpecToFunctionDeclStorageClass(SCSpec, DC);
+    = StorageClassSpecToFunctionDeclStorageClass(SCSpec);
 
   // Check that the return type is not an abstract class type.
   // For record types, this is done by the AbstractClassUsageDiagnoser once

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=109865&r1=109864&r2=109865&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Jul 30 11:47:02 2010
@@ -5909,7 +5909,7 @@
   return DeclPtrTy::make(D);
 }
 
-/// ActOnFinishLinkageSpecification - Completely the definition of
+/// ActOnFinishLinkageSpecification - Complete the definition of
 /// the C++ linkage specification LinkageSpec. If RBraceLoc is
 /// valid, it's the position of the closing '}' brace in a linkage
 /// specification that uses braces.

Modified: cfe/trunk/test/SemaCXX/linkage-spec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/linkage-spec.cpp?rev=109865&r1=109864&r2=109865&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/linkage-spec.cpp (original)
+++ cfe/trunk/test/SemaCXX/linkage-spec.cpp Fri Jul 30 11:47:02 2010
@@ -54,3 +54,6 @@
         return f2((char *)0);
     }
 }
+
+// PR6991
+extern "C" typedef int (*PutcFunc_t)(int);





More information about the cfe-commits mailing list