This patch implements semantic handling of inline functions declared dllimport or dllexport.
Both attributes are allowed on function definitions if they are declared inline. Explicit specializations and instantiation definitions do not have to be specified as inline (this is how MSVC behaves).
>From 5dadb53d73a193eabe4ba9649661fe76e30ae728 Mon Sep 17 00:00:00 2001 From: Nico Rieck <[email protected]> Date: Mon, 31 Mar 2014 20:45:49 +0200 Subject: [PATCH] Sema: Allow dll attributes on inline functions dllimport and dllexport are allowed on function definitions if they are declared inline. Explicit specializations and instantiation definitions are treated as inline. --- include/clang/Basic/DiagnosticSemaKinds.td | 2 + lib/Sema/SemaDecl.cpp | 30 ++++++------ lib/Sema/SemaDeclAttr.cpp | 15 ------ test/Rewriter/missing-dllimport.c | 16 ++----- test/Sema/dllexport.c | 7 ++- test/Sema/dllimport.c | 9 ++-- test/SemaCXX/MicrosoftExtensions.cpp | 2 +- test/SemaCXX/dllexport.cpp | 30 ++++++++++-- test/SemaCXX/dllimport.cpp | 75 ++++++++++++++++++++++++------ 9 files changed, 121 insertions(+), 65 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 37f277d..e197b22 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2079,6 +2079,8 @@ def err_attribute_dll_not_extern : Error< def warn_attribute_invalid_on_definition : Warning< "'%0' attribute cannot be specified on a definition">, InGroup<IgnoredAttributes>; +def err_attribute_invalid_on_definition : Error< + "%q0 attribute cannot be specified on a definition">; def err_attribute_dll_redeclaration : Error< "redeclaration of %q0 cannot add %q1 attribute">; def err_attribute_dllimport_data_definition : Error< diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 9d7f13c..6a0fbd3 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -4898,9 +4898,9 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl, // A redeclaration is not allowed to drop a dllimport attribute, the only // exception being inline function definitions. - // FIXME: Handle inline functions. // NB: MSVC converts such a declaration to dllexport. - if (OldImportAttr && !HasNewAttr) { + FunctionDecl *NewFD = dyn_cast<FunctionDecl>(NewDecl); + if (OldImportAttr && !HasNewAttr && !(NewFD && NewFD->isInlined())) { S.Diag(NewDecl->getLocation(), diag::warn_redeclaration_without_attribute_prev_attribute_ignored) << NewDecl << OldImportAttr; @@ -9744,20 +9744,24 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { 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; + if (const DLLImportAttr *DA = FD->getAttr<DLLImportAttr>()) { + // dllimport attribute cannot be directly applied to non-inline function + // definitions. MSVC treats explicit specializations and instantiation + // definitions as inline. + FunctionDecl::TemplatedKind TK = FD->getTemplatedKind(); + bool IsTemplate = TK == FunctionDecl::TK_FunctionTemplate || + TK == FunctionDecl::TK_FunctionTemplateSpecialization; + bool IsExplicit = + FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization || + FD->getTemplateSpecializationKind() ==TSK_ExplicitInstantiationDefinition; + + bool TreatAsInline = IsTemplate && IsExplicit; + if (!DA->isInherited() && !FD->isInlined() && !TreatAsInline) { + Diag(FD->getLocation(), diag::err_attribute_invalid_on_definition) << DA; FD->setInvalidDecl(); - return D; } } + // We want to attach documentation to original Decl (which might be // a function template). ActOnDocumentableDecl(D); diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index f4d16af..111bbb3 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -3775,13 +3775,6 @@ static void handleDLLImportAttr(Sema &S, Decl *D, const AttributeList &Attr) { 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) @@ -3802,14 +3795,6 @@ DLLExportAttr *Sema::mergeDLLExportAttr(Decl *D, SourceRange Range, } 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) diff --git a/test/Rewriter/missing-dllimport.c b/test/Rewriter/missing-dllimport.c index 1e4689f..b75d9c9 100644 --- a/test/Rewriter/missing-dllimport.c +++ b/test/Rewriter/missing-dllimport.c @@ -1,19 +1,9 @@ -// RUN: not %clang_cc1 -triple i686-pc-win32 -fms-extensions -fsyntax-only %s 2>&1 | FileCheck -check-prefix=CHECK-NEG %s -// RUN: not %clang_cc1 -triple i686-pc-win32 -fsyntax-only %s 2>&1 | FileCheck -check-prefix=CHECK-POS %s +// RUN: %clang_cc1 -triple i686-pc-win32 -fms-extensions -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple i686-pc-win32 -fsyntax-only -verify %s // Do not report that 'foo()' is redeclared without dllimport attribute with -fms-extensions // specified. Addresses <rdar://problem/7653912>. +// expected-no-diagnostics __declspec(dllimport) int __cdecl foo(void); inline int __cdecl foo() { return 0; } - -// This function is added just to trigger a diagnostic. This way we can test how many -// diagnostics we expect. -void bar() { return 1; } - -// CHECK-NEG: error: void function 'bar' should not return a value -// CHECK-NEG: 1 error generated -// CHECK-POS: warning: 'foo' redeclared without 'dllimport' attribute: previous 'dllimport' ignored -// CHECK-POS: error: void function 'bar' should not return a value -// CHECK-POS: 1 warning and 1 error generated - diff --git a/test/Sema/dllexport.c b/test/Sema/dllexport.c index 8a71e5d..c6d04dc 100644 --- a/test/Sema/dllexport.c +++ b/test/Sema/dllexport.c @@ -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 @@ -88,6 +88,9 @@ __declspec(dllexport) void redecl3(); void redecl4(); // expected-note{{previous declaration is here}} __declspec(dllexport) void redecl4(); // expected-error{{redeclaration of 'redecl4' cannot add 'dllexport' attribute}} + void redecl5(); // expected-note{{previous declaration is here}} +__declspec(dllexport) inline void redecl5() {} // expected-error{{redeclaration of 'redecl5' cannot add 'dllexport' attribute}} + // External linkage is required. __declspec(dllexport) static int staticFunc(); // expected-error{{'staticFunc' must have external linkage when declared 'dllexport'}} diff --git a/test/Sema/dllimport.c b/test/Sema/dllimport.c index a498294..5f080e0 100644 --- a/test/Sema/dllimport.c +++ b/test/Sema/dllimport.c @@ -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' attribute cannot be specified on a 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(); @@ -118,5 +118,8 @@ __declspec(dllimport) void redecl3(); // expected-note{{previous declaration is void redecl4(); // expected-note{{previous declaration is here}} __declspec(dllimport) void redecl4(); // expected-error{{redeclaration of 'redecl4' cannot add 'dllimport' attribute}} + void redecl5(); // expected-note{{previous declaration is here}} +__declspec(dllimport) inline void redecl5() {} // expected-error{{redeclaration of 'redecl5' cannot add 'dllimport' attribute}} + // External linkage is required. __declspec(dllimport) static int staticFunc(); // expected-error{{'staticFunc' must have external linkage when declared 'dllimport'}} diff --git a/test/SemaCXX/MicrosoftExtensions.cpp b/test/SemaCXX/MicrosoftExtensions.cpp index 0f6ebbb..58280a1 100644 --- a/test/SemaCXX/MicrosoftExtensions.cpp +++ b/test/SemaCXX/MicrosoftExtensions.cpp @@ -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' attribute cannot be specified on a definition}} // expected-error@-1{{redeclaration of 'AAA::f2' cannot add 'dllimport' attribute}} } diff --git a/test/SemaCXX/dllexport.cpp b/test/SemaCXX/dllexport.cpp index 0f4cb5c..07154db 100644 --- a/test/SemaCXX/dllexport.cpp +++ b/test/SemaCXX/dllexport.cpp @@ -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(); @@ -111,15 +111,20 @@ __declspec(dllexport) void redecl2(); void redecl3(); // expected-note{{previous declaration is here}} __declspec(dllexport) void redecl3(); // expected-error{{redeclaration of 'redecl3' cannot add 'dllexport' attribute}} + void redecl4(); // expected-note{{previous declaration is here}} +__declspec(dllexport) inline void redecl4() {} // expected-error{{redeclaration of 'redecl4' cannot add 'dllexport' attribute}} + // Friend functions struct FuncFriend { friend __declspec(dllexport) void friend1(); friend __declspec(dllexport) void friend2(); friend void friend3(); // expected-note{{previous declaration is here}} + friend void friend4(); // expected-note{{previous declaration is here}} }; __declspec(dllexport) void friend1() {} void friend2() {} __declspec(dllexport) void friend3() {} // expected-error{{redeclaration of 'friend3' cannot add 'dllexport' attribute}} +__declspec(dllexport) inline void friend4() {} // expected-error{{redeclaration of 'friend4' cannot add 'dllexport' attribute}} // Implicit declarations can be redeclared with dllexport. __declspec(dllexport) void* operator new(__SIZE_TYPE__ n); @@ -143,6 +148,16 @@ template<typename T> void __declspec(dllexport) funcTmplDecl2(); // Export function template definition. template<typename T> __declspec(dllexport) void funcTmplDef() {} +// Export inline function template. +template<typename T> __declspec(dllexport) inline void inlineFuncTmpl1() {} +template<typename T> inline void __attribute__((dllexport)) inlineFuncTmpl2() {} + +template<typename T> __declspec(dllexport) inline void inlineFuncTmplDecl(); +template<typename T> void inlineFuncTmplDecl() {} + +template<typename T> __declspec(dllexport) void inlineFuncTmplDef(); +template<typename T> inline void inlineFuncTmplDef() {} + // Redeclarations template<typename T> __declspec(dllexport) void funcTmplRedecl1(); template<typename T> __declspec(dllexport) void funcTmplRedecl1() {} @@ -153,15 +168,20 @@ template<typename T> void funcTmplRedecl2() {} template<typename T> void funcTmplRedecl3(); // expected-note{{previous declaration is here}} template<typename T> __declspec(dllexport) void funcTmplRedecl3(); // expected-error{{redeclaration of 'funcTmplRedecl3' cannot add 'dllexport' attribute}} +template<typename T> void funcTmplRedecl4(); // expected-note{{previous declaration is here}} +template<typename T> __declspec(dllexport) inline void funcTmplRedecl4() {} // expected-error{{redeclaration of 'funcTmplRedecl4' cannot add 'dllexport' attribute}} + // Function template friends struct FuncTmplFriend { template<typename T> friend __declspec(dllexport) void funcTmplFriend1(); template<typename T> friend __declspec(dllexport) void funcTmplFriend2(); template<typename T> friend void funcTmplFriend3(); // expected-note{{previous declaration is here}} + template<typename T> friend void funcTmplFriend4(); // expected-note{{previous declaration is here}} }; template<typename T> __declspec(dllexport) void funcTmplFriend1() {} template<typename T> void funcTmplFriend2() {} template<typename T> __declspec(dllexport) void funcTmplFriend3() {} // expected-error{{redeclaration of 'funcTmplFriend3' cannot add 'dllexport' attribute}} +template<typename T> __declspec(dllexport) inline void funcTmplFriend4() {} // expected-error{{redeclaration of 'funcTmplFriend4' cannot add 'dllexport' attribute}} // External linkage is required. template<typename T> __declspec(dllexport) static int staticFuncTmpl(); // expected-error{{'staticFuncTmpl' must have external linkage when declared 'dllexport'}} @@ -188,7 +208,7 @@ template void exportedFuncTmpl<ExplicitInst_Exported>(); // 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 +225,7 @@ template __declspec(dllexport) void funcTmpl<ExplicitInst_Exported>(); // 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>() {} diff --git a/test/SemaCXX/dllimport.cpp b/test/SemaCXX/dllimport.cpp index a96f18b..2105a26 100644 --- a/test/SemaCXX/dllimport.cpp +++ b/test/SemaCXX/dllimport.cpp @@ -116,14 +116,20 @@ 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' attribute cannot be specified on a 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() {} + +__declspec(dllimport) inline void inlineDecl(); + void inlineDecl() {} + +__declspec(dllimport) void inlineDef(); + inline void inlineDef() {} // Redeclarations __declspec(dllimport) void redecl1(); @@ -140,17 +146,22 @@ __declspec(dllimport) void redecl3(); // expected-note{{previous declaration is void redecl4(); // expected-note{{previous declaration is here}} __declspec(dllimport) void redecl4(); // expected-error{{redeclaration of 'redecl4' cannot add 'dllimport' attribute}} + void redecl5(); // expected-note{{previous declaration is here}} +__declspec(dllimport) inline void redecl5() {} // expected-error{{redeclaration of 'redecl5' cannot add 'dllimport' attribute}} + // Friend functions struct FuncFriend { friend __declspec(dllimport) void friend1(); friend __declspec(dllimport) void friend2(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} friend __declspec(dllimport) void friend3(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} friend void friend4(); // expected-note{{previous declaration is here}} + friend void friend5(); // expected-note{{previous declaration is here}} }; __declspec(dllimport) void friend1(); void friend2(); // expected-warning{{'friend2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} void friend3() {} // expected-warning{{'friend3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} __declspec(dllimport) void friend4(); // expected-error{{redeclaration of 'friend4' cannot add 'dllimport' attribute}} +__declspec(dllimport) inline void friend5() {} // expected-error{{redeclaration of 'friend5' cannot add 'dllimport' attribute}} // Implicit declarations can be redeclared with dllimport. __declspec(dllimport) void* operator new(__SIZE_TYPE__ n); @@ -171,6 +182,19 @@ namespace ns { __declspec(dllimport) void externalFunc(); } template<typename T> __declspec(dllimport) void funcTmplDecl1(); template<typename T> void __declspec(dllimport) funcTmplDecl2(); +// Import function template definition. +template<typename T> __declspec(dllimport) void funcTmplDef() {} // expected-error{{'dllimport' attribute cannot be specified on a definition}} + +// Import inline function template. +template<typename T> __declspec(dllimport) inline void inlineFuncTmpl1() {} +template<typename T> inline void __attribute__((dllimport)) inlineFuncTmpl2() {} + +template<typename T> __declspec(dllimport) inline void inlineFuncTmplDecl(); +template<typename T> void inlineFuncTmplDecl() {} + +template<typename T> __declspec(dllimport) void inlineFuncTmplDef(); +template<typename T> inline void inlineFuncTmplDef() {} + // Redeclarations template<typename T> __declspec(dllimport) void funcTmplRedecl1(); template<typename T> __declspec(dllimport) void funcTmplRedecl1(); @@ -184,17 +208,22 @@ template<typename T> void funcTmplRedecl3() {} // expected template<typename T> void funcTmplRedecl4(); // expected-note{{previous declaration is here}} template<typename T> __declspec(dllimport) void funcTmplRedecl4(); // expected-error{{redeclaration of 'funcTmplRedecl4' cannot add 'dllimport' attribute}} +template<typename T> void funcTmplRedecl5(); // expected-note{{previous declaration is here}} +template<typename T> __declspec(dllimport) inline void funcTmplRedecl5() {} // expected-error{{redeclaration of 'funcTmplRedecl5' cannot add 'dllimport' attribute}} + // Function template friends struct FuncTmplFriend { template<typename T> friend __declspec(dllimport) void funcTmplFriend1(); template<typename T> friend __declspec(dllimport) void funcTmplFriend2(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} template<typename T> friend __declspec(dllimport) void funcTmplFriend3(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} template<typename T> friend void funcTmplFriend4(); // expected-note{{previous declaration is here}} + template<typename T> friend __declspec(dllimport) inline void funcTmplFriend5(); }; template<typename T> __declspec(dllimport) void funcTmplFriend1(); template<typename T> void funcTmplFriend2(); // expected-warning{{'funcTmplFriend2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} template<typename T> void funcTmplFriend3() {} // expected-warning{{'funcTmplFriend3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} template<typename T> __declspec(dllimport) void funcTmplFriend4(); // expected-error{{redeclaration of 'funcTmplFriend4' cannot add 'dllimport' attribute}} +template<typename T> inline void funcTmplFriend5() {} // External linkage is required. template<typename T> __declspec(dllimport) static int staticFuncTmpl(); // expected-error{{'staticFuncTmpl' must have external linkage when declared 'dllimport'}} @@ -204,13 +233,29 @@ namespace ns { template<typename T> __declspec(dllimport) void externalFuncTmpl( template<typename T> void funcTmpl() {} -template<typename T> __declspec(dllimport) void importedFuncTmpl(); - -// Import specialization of an imported function template. A definition must be -// declared inline. +template<typename T> inline void inlineFuncTmpl() {} +template<typename T> __declspec(dllimport) void importedFuncTmplDecl(); +template<typename T> __declspec(dllimport) inline void importedFuncTmpl() {} + +// Import implicit instantiation of an imported function template. +void useFunTmplDecl() { importedFuncTmplDecl<ImplicitInst_Imported>(); } +void useFunTmplDef() { importedFuncTmpl<ImplicitInst_Imported>(); } + +// Import explicit instantiation declaration of an imported function template. +extern template void importedFuncTmpl<ExplicitDecl_Imported>(); + +// Import explicit instantiation definition of an imported function template. +// NB: MSVC fails this instantiation without explicit dllimport which is most +// likely a bug because an implicit instantiation is accepted. +template void importedFuncTmpl<ExplicitInst_Imported>(); + +// Import specialization of an imported function template. +template<> __declspec(dllimport) void importedFuncTmplDecl<ExplicitSpec_Imported>(); +template<> __declspec(dllimport) void importedFuncTmplDecl<ExplicitSpec_Def_Imported>() {} +template<> __declspec(dllimport) inline void importedFuncTmplDecl<ExplicitSpec_InlineDef_Imported>() {} 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>() {} +template<> __declspec(dllimport) inline void importedFuncTmpl<ExplicitSpec_InlineDef_Imported>() {} // Not importing specialization of an imported function template without // explicit dllimport. @@ -219,9 +264,13 @@ template<> void importedFuncTmpl<ExplicitSpec_NotImported>() {} // Import explicit instantiation declaration of a non-imported function template. extern template __declspec(dllimport) void funcTmpl<ExplicitDecl_Imported>(); +extern template __declspec(dllimport) void inlineFuncTmpl<ExplicitDecl_Imported>(); + +// Import explicit instantiation definition of a non-imported function template. +template __declspec(dllimport) void funcTmpl<ExplicitInst_Imported>(); +template __declspec(dllimport) void inlineFuncTmpl<ExplicitInst_Imported>(); -// Import specialization of a non-imported function template. A definition must -// be declared inline. +// Import specialization of a non-imported function template. 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>() {} +template<> __declspec(dllimport) inline void funcTmpl<ExplicitSpec_InlineDef_Imported>() {} -- 1.9.0.msysgit.0
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
