r208925 - Allow dllimport/dllexport on inline functions and adjust the linkage.
Hans Wennborg
hans at hanshq.net
Thu May 15 15:07:49 PDT 2014
Author: hans
Date: Thu May 15 17:07:49 2014
New Revision: 208925
URL: http://llvm.org/viewvc/llvm-project?rev=208925&view=rev
Log:
Allow dllimport/dllexport on inline functions and adjust the linkage.
This is a step towards handling these attributes on classes (PR11170).
Differential Revision: http://reviews.llvm.org/D3772
Added:
cfe/trunk/test/CodeGen/dllexport.c
cfe/trunk/test/CodeGenCXX/dllexport.cpp
cfe/trunk/test/CodeGenCXX/dllimport.cpp
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/AST/Decl.cpp
cfe/trunk/lib/CodeGen/CodeGenModule.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclAttr.cpp
cfe/trunk/test/Sema/dllexport.c
cfe/trunk/test/Sema/dllimport.c
cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp
cfe/trunk/test/SemaCXX/dllexport.cpp
cfe/trunk/test/SemaCXX/dllimport.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=208925&r1=208924&r2=208925&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu May 15 17:07:49 2014
@@ -2091,6 +2091,8 @@ def warn_attribute_invalid_on_definition
InGroup<IgnoredAttributes>;
def err_attribute_dll_redeclaration : Error<
"redeclaration of %q0 cannot add %q1 attribute">;
+def err_attribute_dllimport_function_definition : Error<
+ "dllimport cannot be applied to non-inline function definition">;
def err_attribute_dllimport_data_definition : Error<
"definition of dllimport data">;
def err_attribute_weakref_not_static : Error<
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=208925&r1=208924&r2=208925&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Thu May 15 17:07:49 2014
@@ -7742,7 +7742,8 @@ QualType ASTContext::GetBuiltinType(unsi
return getFunctionType(ResType, ArgTypes, EPI);
}
-GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) const {
+static GVALinkage basicGVALinkageForFunction(const ASTContext &Context,
+ const FunctionDecl *FD) {
if (!FD->isExternallyVisible())
return GVA_Internal;
@@ -7773,8 +7774,11 @@ GVALinkage ASTContext::GetGVALinkageForF
if (!FD->isInlined())
return External;
- if ((!getLangOpts().CPlusPlus && !getLangOpts().MSVCCompat) ||
+ if ((!Context.getLangOpts().CPlusPlus && !Context.getLangOpts().MSVCCompat &&
+ !FD->hasAttr<DLLExportAttr>()) ||
FD->hasAttr<GNUInlineAttr>()) {
+ // FIXME: This doesn't match gcc's behavior for dllexport inline functions.
+
// GNU or C99 inline semantics. Determine whether this symbol should be
// externally visible.
if (FD->isInlineDefinitionExternallyVisible())
@@ -7793,7 +7797,26 @@ GVALinkage ASTContext::GetGVALinkageForF
return GVA_DiscardableODR;
}
-GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) {
+static GVALinkage adjustGVALinkageForDLLAttribute(GVALinkage L, const Decl *D) {
+ // See http://msdn.microsoft.com/en-us/library/xa0d9ste.aspx
+ // dllexport/dllimport on inline functions.
+ if (D->hasAttr<DLLImportAttr>()) {
+ if (L == GVA_DiscardableODR || L == GVA_StrongODR)
+ return GVA_AvailableExternally;
+ } else if (D->hasAttr<DLLExportAttr>()) {
+ if (L == GVA_DiscardableODR)
+ return GVA_StrongODR;
+ }
+ return L;
+}
+
+GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) const {
+ return adjustGVALinkageForDLLAttribute(basicGVALinkageForFunction(*this, FD),
+ FD);
+}
+
+static GVALinkage basicGVALinkageForVariable(const ASTContext &Context,
+ const VarDecl *VD) {
if (!VD->isExternallyVisible())
return GVA_Internal;
@@ -7807,7 +7830,7 @@ GVALinkage ASTContext::GetGVALinkageForV
// enclosing function.
if (LexicalContext)
StaticLocalLinkage =
- GetGVALinkageForFunction(cast<FunctionDecl>(LexicalContext));
+ Context.GetGVALinkageForFunction(cast<FunctionDecl>(LexicalContext));
// GVA_StrongODR function linkage is stronger than what we need,
// downgrade to GVA_DiscardableODR.
@@ -7821,7 +7844,7 @@ GVALinkage ASTContext::GetGVALinkageForV
// Itanium-specified entry point, which has the normal linkage of the
// variable.
if (VD->getTLSKind() == VarDecl::TLS_Dynamic &&
- getTargetInfo().getTriple().isMacOSX())
+ Context.getTargetInfo().getTriple().isMacOSX())
return GVA_Internal;
switch (VD->getTemplateSpecializationKind()) {
@@ -7842,6 +7865,11 @@ GVALinkage ASTContext::GetGVALinkageForV
llvm_unreachable("Invalid Linkage!");
}
+GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) {
+ return adjustGVALinkageForDLLAttribute(basicGVALinkageForVariable(*this, VD),
+ VD);
+}
+
bool ASTContext::DeclMustBeEmitted(const Decl *D) {
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
if (!VD->isFileVarDecl())
Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=208925&r1=208924&r2=208925&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Thu May 15 17:07:49 2014
@@ -2572,7 +2572,7 @@ bool FunctionDecl::isMSExternInline() co
assert(isInlined() && "expected to get called on an inlined function!");
const ASTContext &Context = getASTContext();
- if (!Context.getLangOpts().MSVCCompat)
+ if (!Context.getLangOpts().MSVCCompat && !hasAttr<DLLExportAttr>())
return false;
for (const FunctionDecl *FD = this; FD; FD = FD->getPreviousDecl())
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=208925&r1=208924&r2=208925&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Thu May 15 17:07:49 2014
@@ -1960,15 +1960,6 @@ llvm::GlobalValue::LinkageTypes CodeGenM
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;
-
// Note that Apple's kernel linker doesn't support symbol
// coalescing, so we need to avoid linkonce and weak linkages there.
// Normally, this means we just map to internal, but for explicit
@@ -1981,7 +1972,7 @@ llvm::GlobalValue::LinkageTypes CodeGenM
// 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 ? llvm::Function::LinkOnceODRLinkage
: llvm::Function::InternalLinkage;
// An explicit instantiation of a template has weak linkage, since
@@ -1995,14 +1986,14 @@ llvm::GlobalValue::LinkageTypes CodeGenM
// Destructor variants in the Microsoft C++ ABI are always linkonce_odr thunks
// emitted on an as-needed basis.
if (UseThunkForDtorVariant)
- return OnceLinkage;
+ return llvm::GlobalValue::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 llvm::GlobalValue::LinkOnceODRLinkage;
// C++ doesn't have tentative definitions and thus cannot have common
// linkage.
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=208925&r1=208924&r2=208925&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu May 15 17:07:49 2014
@@ -9764,20 +9764,12 @@ Decl *Sema::ActOnStartOfFunctionDef(Scop
if (const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>())
ResolveExceptionSpec(D->getLocation(), FPT);
- // Checking attributes of current function definition
- // dllimport attribute.
- DLLImportAttr *DA = FD->getAttr<DLLImportAttr>();
- 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;
- FD->setInvalidDecl();
- return D;
- }
+ // dllimport cannot be applied to non-inline function definitions.
+ if (FD->hasAttr<DLLImportAttr>() && !FD->isInlined()) {
+ assert(!FD->hasAttr<DLLExportAttr>());
+ Diag(FD->getLocation(), diag::err_attribute_dllimport_function_definition);
+ FD->setInvalidDecl();
+ return D;
}
// We want to attach documentation to original Decl (which might be
// a function template).
Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=208925&r1=208924&r2=208925&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Thu May 15 17:07:49 2014
@@ -3841,13 +3841,6 @@ static void handleDLLImportAttr(Sema &S,
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 @@ DLLExportAttr *Sema::mergeDLLExportAttr(
}
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)
Added: cfe/trunk/test/CodeGen/dllexport.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/dllexport.c?rev=208925&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/dllexport.c (added)
+++ cfe/trunk/test/CodeGen/dllexport.c Thu May 15 17:07:49 2014
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -triple i686-pc-win32 -std=c99 -O2 -disable-llvm-optzns -emit-llvm < %s | FileCheck %s
+
+#define DLLEXPORT __declspec(dllexport)
+
+inline void DLLEXPORT f() {}
+extern void DLLEXPORT f();
+
+// CHECK: define weak_odr dllexport void @f()
Added: cfe/trunk/test/CodeGenCXX/dllexport.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/dllexport.cpp?rev=208925&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/dllexport.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/dllexport.cpp Thu May 15 17:07:49 2014
@@ -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 at H@@YAXXZ"()
+
+struct S {
+ void DLLEXPORT a() {}
+ // CHECK-DAG: define weak_odr dllexport x86_thiscallcc void @"\01?a at S@@QAEXXZ"
+};
+
+void user() {
+ // FIXME: dllexported functions must be emitted even if they're not referenced in this TU.
+ a();
+ b();
+ &S::a;
+}
Added: cfe/trunk/test/CodeGenCXX/dllimport.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/dllimport.cpp?rev=208925&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/dllimport.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/dllimport.cpp Thu May 15 17:07:49 2014
@@ -0,0 +1,25 @@
+// 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 at H@@YAXXZ"()
+
+struct S {
+ void DLLIMPORT a() {}
+ // CHECK-DAG: define available_externally dllimport x86_thiscallcc void @"\01?a at S@@QAEXXZ"
+};
+
+void user(S* s) {
+ a();
+ b();
+ c<int>();
+ s->a();
+}
Modified: cfe/trunk/test/Sema/dllexport.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/dllexport.c?rev=208925&r1=208924&r2=208925&view=diff
==============================================================================
--- cfe/trunk/test/Sema/dllexport.c (original)
+++ cfe/trunk/test/Sema/dllexport.c Thu May 15 17:07:49 2014
@@ -69,10 +69,10 @@ void __declspec(dllexport) decl2B()
__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
Modified: cfe/trunk/test/Sema/dllimport.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/dllimport.c?rev=208925&r1=208924&r2=208925&view=diff
==============================================================================
--- cfe/trunk/test/Sema/dllimport.c (original)
+++ cfe/trunk/test/Sema/dllimport.c Thu May 15 17:07:49 2014
@@ -97,11 +97,11 @@ void __attribute__((dllimport)) decl2A()
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 be 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();
Modified: cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp?rev=208925&r1=208924&r2=208925&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp (original)
+++ cfe/trunk/test/SemaCXX/MicrosoftExtensions.cpp Thu May 15 17:07:49 2014
@@ -122,7 +122,7 @@ __declspec(dllimport) void f(void) { }
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 be applied to non-inline function definition}}
// expected-error at -1{{redeclaration of 'AAA::f2' cannot add 'dllimport' attribute}}
}
Modified: cfe/trunk/test/SemaCXX/dllexport.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/dllexport.cpp?rev=208925&r1=208924&r2=208925&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/dllexport.cpp (original)
+++ cfe/trunk/test/SemaCXX/dllexport.cpp Thu May 15 17:07:49 2014
@@ -92,10 +92,10 @@ __declspec(dllexport) void def() {}
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 @@ template void exportedFuncTmpl<ExplicitI
// 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 @@ template __declspec(dllexport) void func
// 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>() {}
Modified: cfe/trunk/test/SemaCXX/dllimport.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/dllimport.cpp?rev=208925&r1=208924&r2=208925&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/dllimport.cpp (original)
+++ cfe/trunk/test/SemaCXX/dllimport.cpp Thu May 15 17:07:49 2014
@@ -116,14 +116,14 @@ void __attribute__((dllimport)) decl2A()
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 be 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 @@ template<typename T> __declspec(dllimpor
// 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 be 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 @@ extern template __declspec(dllimport) vo
// 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 be applied to non-inline function definition}}
+template<> __declspec(dllimport) inline void funcTmpl<ExplicitSpec_InlineDef_Imported>() {}
More information about the cfe-commits
mailing list