From e6c692bd0cad57be6fb30d645e8a9bb1e2d67c6f Mon Sep 17 00:00:00 2001 From: Nico Rieck Date: Sun, 23 Mar 2014 21:24:01 +0000 Subject: [PATCH] Treat dllimport globals without explicit storage class as extern dllimport implies a definition which means the 'extern' keyword is optional when declaring imported variables. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@204576 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDecl.cpp | 38 ++++++++++++++++++++++++++++++++++++++ test/Sema/dllimport.c | 27 +++++++++++++++++++++++++++ test/SemaCXX/dllimport.cpp | 27 +++++++++++++++++++++++++++ 3 files changed, 92 insertions(+) diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 2e8392fb85..e4511c925f 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -4923,6 +4923,31 @@ static bool shouldConsiderLinkage(const FunctionDecl *FD) { 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, Declarator &D, DeclContext *DC, 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, Declarator &D, DeclContext *DC, } } + // 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() || + NewVD->getAttr()->isInherited() || + NewVD->isStaticDataMember() || NewVD->getStorageClass() != SC_None); + // In auto-retain/release, infer strong retension for variables of // retainable type. if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewVD)) diff --git a/test/Sema/dllimport.c b/test/Sema/dllimport.c index 615f8f77b4..c1b615d7b7 100644 --- a/test/Sema/dllimport.c +++ b/test/Sema/dllimport.c @@ -22,6 +22,8 @@ __declspec(dllimport) extern int ExternGlobalDecl; // 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 = 1; // expected-error{{definition of dlli __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; diff --git a/test/SemaCXX/dllimport.cpp b/test/SemaCXX/dllimport.cpp index 4a3ee202ad..82a2aa0cd8 100644 --- a/test/SemaCXX/dllimport.cpp +++ b/test/SemaCXX/dllimport.cpp @@ -34,6 +34,8 @@ __declspec(dllimport) extern int ExternGlobalDecl; // 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 = 1; // expected-error{{definition of dlli __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; -- 2.40.0