On 21.03.2014 01:19, Richard Smith wrote:
> * goes on the right.
> [...]
> 'i' and 'e' should be capitalized.
That's what I get for copy & paste without looking closely... ;)
> You don't have any tests for the attribute being in the declarator chunks,
> rather than in the decl specifiers. Please add such tests.
Done, treating all three attribute placements the same, similar to other
attributes. I noticed that Clang and GCC handle such attributes
differently, i.e. GCC rejects something like
int *__attribute__((visibility("hidden"))) v;
> Move the getAttr into the assert, so we trivially remove the whole thing in
> an NDEBUG build.
Done.
-Nico
>From 92d177d17acb4f8c378e652573872479e9fcd385 Mon Sep 17 00:00:00 2001
From: Nico Rieck <[email protected]>
Date: Mon, 20 Jan 2014 19:28:12 +0100
Subject: [PATCH] dll-sema-global-dllimport-extern
Treat dllimport globals without explicit storage class as extern
dllimport implies a definition which means the 'extern' keyword is optional
when declaring imported variables.
---
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 2e8392f..e4511c9 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<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))
diff --git a/test/Sema/dllimport.c b/test/Sema/dllimport.c
index 615f8f7..c1b615d 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 4a3ee20..82a2aa0 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;
--
1.9.0.msysgit.0
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits