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@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; +} 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@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(); + 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@-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>() {} _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
