Hi majnemer, rnk, nrieck,
This is important for being able to handle these attributes on classes
(PR11170).
http://reviews.llvm.org/D3772
Files:
include/clang/Basic/DiagnosticSemaKinds.td
lib/CodeGen/CodeGenModule.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclAttr.cpp
test/CodeGen/dllexport.cpp
test/CodeGen/dllimport.cpp
test/Sema/dllexport.c
test/Sema/dllimport.c
test/SemaCXX/MicrosoftExtensions.cpp
test/SemaCXX/dllexport.cpp
test/SemaCXX/dllimport.cpp
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -2091,6 +2091,8 @@
InGroup<IgnoredAttributes>;
def err_attribute_dll_redeclaration : Error<
"redeclaration of %q0 cannot add %q1 attribute">;
+def err_attribute_dllimport_function_definition : Error<
+ "dllimport cannot by applied to non-inline function definition">;
def err_attribute_dllimport_data_definition : Error<
"definition of dllimport data">;
def err_attribute_weakref_not_static : Error<
Index: lib/CodeGen/CodeGenModule.cpp
===================================================================
--- lib/CodeGen/CodeGenModule.cpp
+++ lib/CodeGen/CodeGenModule.cpp
@@ -1960,14 +1960,16 @@
if (Linkage == GVA_AvailableExternally)
return llvm::Function::AvailableExternallyLinkage;
- // LinkOnceODRLinkage is insufficient if the symbol is required to exist in
- // the symbol table. Promote the linkage to WeakODRLinkage to preserve the
- // semantics of LinkOnceODRLinkage while providing visibility in the symbol
- // table.
- llvm::GlobalValue::LinkageTypes OnceLinkage =
- llvm::GlobalValue::LinkOnceODRLinkage;
- if (D->hasAttr<DLLExportAttr>() || D->hasAttr<DLLImportAttr>())
- OnceLinkage = llvm::GlobalVariable::WeakODRLinkage;
+ auto DiscardableODRLinkage = llvm::GlobalValue::LinkOnceODRLinkage;
+ auto NonDiscardableODRLinkage = llvm::GlobalValue::WeakODRLinkage;
+
+ if (D->hasAttr<DLLExportAttr>()) {
+ DiscardableODRLinkage = llvm::GlobalVariable::WeakODRLinkage;
+ NonDiscardableODRLinkage = llvm::GlobalVariable::WeakODRLinkage;
+ } else if (D->hasAttr<DLLImportAttr>()) {
+ DiscardableODRLinkage = llvm::GlobalVariable::AvailableExternallyLinkage;
+ NonDiscardableODRLinkage = llvm::GlobalVariable::AvailableExternallyLinkage;
+ }
// Note that Apple's kernel linker doesn't support symbol
// coalescing, so we need to avoid linkonce and weak linkages there.
@@ -1981,28 +1983,28 @@
// merged with other definitions. c) C++ has the ODR, so we know the
// definition is dependable.
if (Linkage == GVA_DiscardableODR)
- return !Context.getLangOpts().AppleKext ? OnceLinkage
+ return !Context.getLangOpts().AppleKext ? DiscardableODRLinkage
: llvm::Function::InternalLinkage;
// An explicit instantiation of a template has weak linkage, since
// explicit instantiations can occur in multiple translation units
// and must all be equivalent. However, we are not allowed to
// throw away these explicit instantiations.
if (Linkage == GVA_StrongODR)
- return !Context.getLangOpts().AppleKext ? llvm::Function::WeakODRLinkage
+ return !Context.getLangOpts().AppleKext ? NonDiscardableODRLinkage
: llvm::Function::ExternalLinkage;
// Destructor variants in the Microsoft C++ ABI are always linkonce_odr thunks
// emitted on an as-needed basis.
if (UseThunkForDtorVariant)
- return OnceLinkage;
+ return llvm::GlobalVariable::LinkOnceODRLinkage;
// If required by the ABI, give definitions of static data members with inline
// initializers at least linkonce_odr linkage.
if (getCXXABI().isInlineInitializedStaticDataMemberLinkOnce() &&
isa<VarDecl>(D) &&
isVarDeclInlineInitializedStaticDataMember(cast<VarDecl>(D)))
- return OnceLinkage;
+ return DiscardableODRLinkage;
// C++ doesn't have tentative definitions and thus cannot have common
// linkage.
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -9770,11 +9770,9 @@
if (DA && (!FD->hasAttr<DLLExportAttr>())) {
// dllimport attribute cannot be directly applied to definition.
// Microsoft accepts dllimport for functions defined within class scope.
- if (!DA->isInherited() &&
- !(LangOpts.MicrosoftExt && FD->getLexicalDeclContext()->isRecord())) {
- Diag(FD->getLocation(),
- diag::err_attribute_can_be_applied_only_to_symbol_declaration)
- << DA;
+
+ if (!DA->isInherited() && !FD->isInlined()) {
+ Diag(FD->getLocation(), diag::err_attribute_dllimport_function_definition);
FD->setInvalidDecl();
return D;
}
Index: lib/Sema/SemaDeclAttr.cpp
===================================================================
--- lib/Sema/SemaDeclAttr.cpp
+++ lib/Sema/SemaDeclAttr.cpp
@@ -3841,13 +3841,6 @@
return;
}
- // Currently, the dllimport attribute is ignored for inlined functions.
- // Warning is emitted.
- if (FD && FD->isInlineSpecified()) {
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
- return;
- }
-
unsigned Index = Attr.getAttributeSpellingListIndex();
DLLImportAttr *NewAttr = S.mergeDLLImportAttr(D, Attr.getRange(), Index);
if (NewAttr)
@@ -3868,14 +3861,6 @@
}
static void handleDLLExportAttr(Sema &S, Decl *D, const AttributeList &Attr) {
- // Currently, the dllexport attribute is ignored for inlined functions, unless
- // the -fkeep-inline-functions flag has been used. Warning is emitted.
- if (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isInlineSpecified()) {
- // FIXME: ... unless the -fkeep-inline-functions flag has been used.
- S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
- return;
- }
-
unsigned Index = Attr.getAttributeSpellingListIndex();
DLLExportAttr *NewAttr = S.mergeDLLExportAttr(D, Attr.getRange(), Index);
if (NewAttr)
Index: test/CodeGen/dllexport.cpp
===================================================================
--- /dev/null
+++ test/CodeGen/dllexport.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple i686-pc-win32 -x c++ -O2 -disable-llvm-optzns -emit-llvm < %s | FileCheck %s
+
+#define DLLEXPORT __declspec(dllexport)
+
+void DLLEXPORT a();
+// CHECK-DAG: declare dllexport void @"\01?a@@YAXXZ"()
+
+inline void DLLEXPORT b() {}
+// CHECK-DAG: define weak_odr dllexport void @"\01?b@@YAXXZ"()
+
+template <typename T> void c() {}
+template void DLLEXPORT c<int>();
+// CHECK-DAG: define weak_odr dllexport void @"\01??$c@H@@YAXXZ"()
+
+struct S {
+ void DLLEXPORT a() {}
+ // CHECK-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?a@S@@QAEXXZ"
+};
+
+void user() {
+ // FIXME: dllexported functions must be emitted even if they're not referenced in this TU.
+ a();
+ b();
+ &S::a;
+}
Index: test/CodeGen/dllimport.cpp
===================================================================
--- /dev/null
+++ test/CodeGen/dllimport.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -triple i686-pc-win32 -x c++ -O2 -disable-llvm-optzns -emit-llvm < %s | FileCheck %s
+
+#define DLLIMPORT __declspec(dllimport)
+
+void DLLIMPORT a();
+// CHECK-DAG: declare dllimport void @"\01?a@@YAXXZ"()
+
+inline void DLLIMPORT b() {}
+// CHECK-DAG: define available_externally dllimport void @"\01?b@@YAXXZ"()
+
+template <typename T> inline void c() {} // FIXME: MSVC accepts this without 'inline' too.
+template void DLLIMPORT c<int>();
+// CHECK-DAG: define available_externally dllimport void @"\01??$c@H@@YAXXZ"()
+
+struct S {
+ void DLLIMPORT a() {}
+ // CHECK-DAG: define available_externally dllimport x86_thiscallcc void @"\01?a@S@@QAEXXZ"
+};
+
+void user(S* s) {
+ a();
+ b();
+ s->a();
+}
Index: test/Sema/dllexport.c
===================================================================
--- test/Sema/dllexport.c
+++ test/Sema/dllexport.c
@@ -69,10 +69,10 @@
__declspec(dllexport) void def() {}
// Export inline function.
-__declspec(dllexport) inline void inlineFunc1() {} // expected-warning{{'dllexport' attribute ignored}}
+__declspec(dllexport) inline void inlineFunc1() {}
extern void inlineFunc1();
-inline void __attribute__((dllexport)) inlineFunc2() {} // expected-warning{{'dllexport' attribute ignored}}
+inline void __attribute__((dllexport)) inlineFunc2() {}
extern void inlineFunc2();
// Redeclarations
Index: test/Sema/dllimport.c
===================================================================
--- test/Sema/dllimport.c
+++ test/Sema/dllimport.c
@@ -97,11 +97,11 @@
void __declspec(dllimport) decl2B();
// Not allowed on function definitions.
-__declspec(dllimport) void def() {} // expected-error{{'dllimport' attribute can be applied only to symbol declaration}}
+__declspec(dllimport) void def() {} // expected-error{{dllimport cannot by applied to non-inline function definition}}
// Import inline function.
-__declspec(dllimport) inline void inlineFunc1() {} // expected-warning{{'dllimport' attribute ignored}}
-inline void __attribute__((dllimport)) inlineFunc2() {} // expected-warning{{'dllimport' attribute ignored}}
+__declspec(dllimport) inline void inlineFunc1() {}
+inline void __attribute__((dllimport)) inlineFunc2() {}
// Redeclarations
__declspec(dllimport) void redecl1();
Index: test/SemaCXX/MicrosoftExtensions.cpp
===================================================================
--- test/SemaCXX/MicrosoftExtensions.cpp
+++ test/SemaCXX/MicrosoftExtensions.cpp
@@ -122,7 +122,7 @@
void f2(void); // expected-note{{previous declaration is here}}
};
-__declspec(dllimport) void AAA::f2(void) { // expected-error{{'dllimport' attribute can be applied only to symbol}}
+__declspec(dllimport) void AAA::f2(void) { // expected-error{{dllimport cannot by applied to non-inline function definition}}
// expected-error@-1{{redeclaration of 'AAA::f2' cannot add 'dllimport' attribute}}
}
Index: test/SemaCXX/dllexport.cpp
===================================================================
--- test/SemaCXX/dllexport.cpp
+++ test/SemaCXX/dllexport.cpp
@@ -92,10 +92,10 @@
extern "C" __declspec(dllexport) void externC() {}
// Export inline function.
-__declspec(dllexport) inline void inlineFunc1() {} // expected-warning{{'dllexport' attribute ignored}}
-inline void __attribute__((dllexport)) inlineFunc2() {} // expected-warning{{'dllexport' attribute ignored}}
+__declspec(dllexport) inline void inlineFunc1() {}
+inline void __attribute__((dllexport)) inlineFunc2() {}
-__declspec(dllexport) inline void inlineDecl(); // expected-warning{{'dllexport' attribute ignored}}
+__declspec(dllexport) inline void inlineDecl();
void inlineDecl() {}
__declspec(dllexport) void inlineDef();
@@ -188,7 +188,7 @@
// Export specialization of an exported function template.
template<> __declspec(dllexport) void exportedFuncTmpl<ExplicitSpec_Exported>();
template<> __declspec(dllexport) void exportedFuncTmpl<ExplicitSpec_Def_Exported>() {}
-template<> __declspec(dllexport) inline void exportedFuncTmpl<ExplicitSpec_InlineDef_Exported>() {} // expected-warning{{'dllexport' attribute ignored}}
+template<> __declspec(dllexport) inline void exportedFuncTmpl<ExplicitSpec_InlineDef_Exported>() {}
// Not exporting specialization of an exported function template without
// explicit dllexport.
@@ -205,7 +205,7 @@
// Export specialization of a non-exported function template.
template<> __declspec(dllexport) void funcTmpl<ExplicitSpec_Exported>();
template<> __declspec(dllexport) void funcTmpl<ExplicitSpec_Def_Exported>() {}
-template<> __declspec(dllexport) inline void funcTmpl<ExplicitSpec_InlineDef_Exported>() {} // expected-warning{{'dllexport' attribute ignored}}
+template<> __declspec(dllexport) inline void funcTmpl<ExplicitSpec_InlineDef_Exported>() {}
Index: test/SemaCXX/dllimport.cpp
===================================================================
--- test/SemaCXX/dllimport.cpp
+++ test/SemaCXX/dllimport.cpp
@@ -116,14 +116,14 @@
void __declspec(dllimport) decl2B();
// Not allowed on function definitions.
-__declspec(dllimport) void def() {} // expected-error{{'dllimport' attribute can be applied only to symbol declaration}}
+__declspec(dllimport) void def() {} // expected-error{{dllimport cannot by applied to non-inline function definition}}
// extern "C"
extern "C" __declspec(dllexport) void externC();
// Import inline function.
-__declspec(dllimport) inline void inlineFunc1() {} // expected-warning{{'dllimport' attribute ignored}}
-inline void __attribute__((dllimport)) inlineFunc2() {} // expected-warning{{'dllimport' attribute ignored}}
+__declspec(dllimport) inline void inlineFunc1() {}
+inline void __attribute__((dllimport)) inlineFunc2() {}
// Redeclarations
__declspec(dllimport) void redecl1();
@@ -209,8 +209,8 @@
// Import specialization of an imported function template. A definition must be
// declared inline.
template<> __declspec(dllimport) void importedFuncTmpl<ExplicitSpec_Imported>();
-template<> __declspec(dllimport) void importedFuncTmpl<ExplicitSpec_Def_Imported>() {} // expected-error{{'dllimport' attribute can be applied only to symbol declaration}}
-template<> __declspec(dllimport) inline void importedFuncTmpl<ExplicitSpec_InlineDef_Imported>() {} // expected-warning{{'dllimport' attribute ignored}}
+template<> __declspec(dllimport) void importedFuncTmpl<ExplicitSpec_Def_Imported>() {} // expected-error{{dllimport cannot by applied to non-inline function definition}}
+template<> __declspec(dllimport) inline void importedFuncTmpl<ExplicitSpec_InlineDef_Imported>() {}
// Not importing specialization of an imported function template without
// explicit dllimport.
@@ -223,5 +223,5 @@
// Import specialization of a non-imported function template. A definition must
// be declared inline.
template<> __declspec(dllimport) void funcTmpl<ExplicitSpec_Imported>();
-template<> __declspec(dllimport) void funcTmpl<ExplicitSpec_Def_Imported>() {} // expected-error{{'dllimport' attribute can be applied only to symbol declaration}}
-template<> __declspec(dllimport) inline void funcTmpl<ExplicitSpec_InlineDef_Imported>() {} // expected-warning{{'dllimport' attribute ignored}}
+template<> __declspec(dllimport) void funcTmpl<ExplicitSpec_Def_Imported>() {} // expected-error{{dllimport cannot by applied to non-inline function definition}}
+template<> __declspec(dllimport) inline void funcTmpl<ExplicitSpec_InlineDef_Imported>() {}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits