r204576 - Treat dllimport globals without explicit storage class as extern

Nico Rieck nico.rieck at gmail.com
Sun Mar 23 14:24:01 PDT 2014


Author: nrieck
Date: Sun Mar 23 16:24:01 2014
New Revision: 204576

URL: http://llvm.org/viewvc/llvm-project?rev=204576&view=rev
Log:
Treat dllimport globals without explicit storage class as extern

dllimport implies a definition which means the 'extern' keyword is optional
when declaring imported variables.

Modified:
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/Sema/dllimport.c
    cfe/trunk/test/SemaCXX/dllimport.cpp

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=204576&r1=204575&r2=204576&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sun Mar 23 16:24:01 2014
@@ -4923,6 +4923,31 @@ static bool shouldConsiderLinkage(const
   llvm_unreachable("Unexpected context");
 }
 
+static bool hasParsedAttr(Scope *S, const AttributeList *AttrList,
+                          AttributeList::Kind Kind) {
+  for (const AttributeList *L = AttrList; L; L = L->getNext())
+    if (L->getKind() == Kind)
+      return true;
+  return false;
+}
+
+static bool hasParsedAttr(Scope *S, const Declarator &PD,
+                          AttributeList::Kind Kind) {
+  // Check decl attributes on the DeclSpec.
+  if (hasParsedAttr(S, PD.getDeclSpec().getAttributes().getList(), Kind))
+    return true;
+
+  // Walk the declarator structure, checking decl attributes that were in a type
+  // position to the decl itself.
+  for (unsigned I = 0, E = PD.getNumTypeObjects(); I != E; ++I) {
+    if (hasParsedAttr(S, PD.getTypeObject(I).getAttrs(), Kind))
+      return true;
+  }
+
+  // Finally, check attributes on the decl itself.
+  return hasParsedAttr(S, PD.getAttributes(), Kind);
+}
+
 /// Adjust the \c DeclContext for a function or variable that might be a
 /// function-local external declaration.
 bool Sema::adjustContextForLocalExternDecl(DeclContext *&DC) {
@@ -4959,6 +4984,12 @@ Sema::ActOnVariableDeclarator(Scope *S,
   VarDecl::StorageClass SC =
     StorageClassSpecToVarDeclStorageClass(D.getDeclSpec());
 
+  // dllimport globals without explicit storage class are treated as extern. We
+  // have to change the storage class this early to get the right DeclContext.
+  if (SC == SC_None && !DC->isRecord() &&
+      hasParsedAttr(S, D, AttributeList::AT_DLLImport))
+    SC = SC_Extern;
+
   DeclContext *OriginalDC = DC;
   bool IsLocalExternDecl = SC == SC_Extern &&
                            adjustContextForLocalExternDecl(DC);
@@ -5326,6 +5357,13 @@ Sema::ActOnVariableDeclarator(Scope *S,
     }
   }
 
+  // Ensure that dllimport globals without explicit storage class are treated as
+  // extern. The storage class is set above using parsed attributes. Now we can
+  // check the VarDecl itself.
+  assert(!NewVD->hasAttr<DLLImportAttr>() ||
+         NewVD->getAttr<DLLImportAttr>()->isInherited() ||
+         NewVD->isStaticDataMember() || NewVD->getStorageClass() != SC_None);
+
   // In auto-retain/release, infer strong retension for variables of
   // retainable type.
   if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewVD))

Modified: cfe/trunk/test/Sema/dllimport.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/dllimport.c?rev=204576&r1=204575&r2=204576&view=diff
==============================================================================
--- cfe/trunk/test/Sema/dllimport.c (original)
+++ cfe/trunk/test/Sema/dllimport.c Sun Mar 23 16:24:01 2014
@@ -22,6 +22,8 @@ __declspec(dllimport) extern int ExternG
 
 // dllimport implies a declaration.
 __declspec(dllimport) int GlobalDecl;
+int **__attribute__((dllimport))* GlobalDeclChunkAttr;
+int GlobalDeclAttr __attribute__((dllimport));
 
 // Not allowed on definitions.
 __declspec(dllimport) extern int ExternGlobalInit = 1; // expected-error{{definition of dllimport data}}
@@ -32,12 +34,37 @@ int __declspec(dllimport) GlobalInit2 =
 __declspec(dllimport) extern int ExternGlobalDeclInit;
 int ExternGlobalDeclInit = 1; // expected-error{{definition of dllimport data}}
 
+__declspec(dllimport) int GlobalDeclInit;
+int GlobalDeclInit = 1; // expected-error{{definition of dllimport data}}
+
+int *__attribute__((dllimport)) GlobalDeclChunkAttrInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+int *GlobalDeclChunkAttrInit = 0; // expected-warning{{'GlobalDeclChunkAttrInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+
+int GlobalDeclAttrInit __attribute__((dllimport)); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+int GlobalDeclAttrInit = 1; // expected-warning{{'GlobalDeclAttrInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+
 // Redeclarations
 __declspec(dllimport) extern int GlobalRedecl1;
 __declspec(dllimport) extern int GlobalRedecl1;
 
+__declspec(dllimport) int GlobalRedecl2a;
+__declspec(dllimport) int GlobalRedecl2a;
+
+int *__attribute__((dllimport)) GlobalRedecl2b;
+int *__attribute__((dllimport)) GlobalRedecl2b;
+
+int GlobalRedecl2c __attribute__((dllimport));
+int GlobalRedecl2c __attribute__((dllimport));
+
 // Import in local scope.
+__declspec(dllimport) float LocalRedecl1; // expected-note{{previous definition is here}}
+__declspec(dllimport) float LocalRedecl2; // expected-note{{previous definition is here}}
+__declspec(dllimport) float LocalRedecl3; // expected-note{{previous definition is here}}
 void functionScope() {
+  __declspec(dllimport) int LocalRedecl1; // expected-error{{redefinition of 'LocalRedecl1' with a different type: 'int' vs 'float'}}
+  int *__attribute__((dllimport)) LocalRedecl2; // expected-error{{redefinition of 'LocalRedecl2' with a different type: 'int *' vs 'float'}}
+  int LocalRedecl3 __attribute__((dllimport)); // expected-error{{redefinition of 'LocalRedecl3' with a different type: 'int' vs 'float'}}
+
   __declspec(dllimport)        int LocalVarDecl;
   __declspec(dllimport)        int LocalVarDef = 1; // expected-error{{definition of dllimport data}}
   __declspec(dllimport) extern int ExternLocalVarDecl;

Modified: cfe/trunk/test/SemaCXX/dllimport.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/dllimport.cpp?rev=204576&r1=204575&r2=204576&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/dllimport.cpp (original)
+++ cfe/trunk/test/SemaCXX/dllimport.cpp Sun Mar 23 16:24:01 2014
@@ -34,6 +34,8 @@ __declspec(dllimport) extern int ExternG
 
 // dllimport implies a declaration.
 __declspec(dllimport) int GlobalDecl;
+int **__attribute__((dllimport))* GlobalDeclChunkAttr;
+int GlobalDeclAttr __attribute__((dllimport));
 
 // Not allowed on definitions.
 __declspec(dllimport) extern int ExternGlobalInit = 1; // expected-error{{definition of dllimport data}}
@@ -44,12 +46,37 @@ int __declspec(dllimport) GlobalInit2 =
 __declspec(dllimport) extern int ExternGlobalDeclInit;
 int ExternGlobalDeclInit = 1; // expected-error{{definition of dllimport data}}
 
+__declspec(dllimport) int GlobalDeclInit;
+int GlobalDeclInit = 1; // expected-error{{definition of dllimport data}}
+
+int *__attribute__((dllimport)) GlobalDeclChunkAttrInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+int *GlobalDeclChunkAttrInit = 0; // expected-warning{{'GlobalDeclChunkAttrInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+
+int GlobalDeclAttrInit __attribute__((dllimport)); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}}
+int GlobalDeclAttrInit = 1; // expected-warning{{'GlobalDeclAttrInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
+
 // Redeclarations
 __declspec(dllimport) extern int GlobalRedecl1;
 __declspec(dllimport) extern int GlobalRedecl1;
 
+__declspec(dllimport) int GlobalRedecl2a;
+__declspec(dllimport) int GlobalRedecl2a;
+
+int *__attribute__((dllimport)) GlobalRedecl2b;
+int *__attribute__((dllimport)) GlobalRedecl2b;
+
+int GlobalRedecl2c __attribute__((dllimport));
+int GlobalRedecl2c __attribute__((dllimport));
+
 // Import in local scope.
+__declspec(dllimport) float LocalRedecl1; // expected-note{{previous definition is here}}
+__declspec(dllimport) float LocalRedecl2; // expected-note{{previous definition is here}}
+__declspec(dllimport) float LocalRedecl3; // expected-note{{previous definition is here}}
 void functionScope() {
+  __declspec(dllimport) int LocalRedecl1; // expected-error{{redefinition of 'LocalRedecl1' with a different type: 'int' vs 'float'}}
+  int *__attribute__((dllimport)) LocalRedecl2; // expected-error{{redefinition of 'LocalRedecl2' with a different type: 'int *' vs 'float'}}
+  int LocalRedecl3 __attribute__((dllimport)); // expected-error{{redefinition of 'LocalRedecl3' with a different type: 'int' vs 'float'}}
+
   __declspec(dllimport)        int LocalVarDecl;
   __declspec(dllimport)        int LocalVarDef = 1; // expected-error{{definition of dllimport data}}
   __declspec(dllimport) extern int ExternLocalVarDecl;





More information about the cfe-commits mailing list