Index: include/clang/AST/DeclBase.h =================================================================== --- include/clang/AST/DeclBase.h +++ include/clang/AST/DeclBase.h @@ -52,6 +52,7 @@ class RecordDecl; class Stmt; class StoredDeclsMap; +class TemplateDecl; class TranslationUnitDecl; class UsingDirectiveDecl; } @@ -905,6 +906,10 @@ DeclKind == FunctionTemplate; } + /// \brief If this is a declaration that describes some template, this + /// method returns that template declaration. + TemplateDecl *getDescribedTemplate() const; + /// \brief Returns the function itself, or the templated function if this is a /// function template. FunctionDecl *getAsFunction() LLVM_READONLY; Index: include/clang/AST/PrettyPrinter.h =================================================================== --- include/clang/AST/PrettyPrinter.h +++ include/clang/AST/PrettyPrinter.h @@ -42,6 +42,7 @@ ConstantArraySizeAsWritten(false), AnonymousTagLocations(true), SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false), SuppressTemplateArgsInCXXConstructors(false), + PrintTemplateParameters(true), Bool(LO.Bool), TerseOutput(false), PolishForDeclaration(false), Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar), IncludeNewlines(true), MSVCFormatting(false) { } @@ -143,6 +144,10 @@ /// constructors. unsigned SuppressTemplateArgsInCXXConstructors : 1; + /// \brief When true, template declaration name is printed with parameters, + /// e.g. 'C1::C2' instead of 'C1::C2'. + bool PrintTemplateParameters : 1; + /// \brief Whether we can use 'bool' rather than '_Bool', even if the language /// doesn't actually have 'bool' (because, e.g., it is defined as a macro). unsigned Bool : 1; Index: include/clang/Basic/DiagnosticGroups.td =================================================================== --- include/clang/Basic/DiagnosticGroups.td +++ include/clang/Basic/DiagnosticGroups.td @@ -75,6 +75,8 @@ def GNUDesignator : DiagGroup<"gnu-designator">; def GNUStringLiteralOperatorTemplate : DiagGroup<"gnu-string-literal-operator-template">; +def UndefinedVarTemplate : DiagGroup<"undefined-var-template">; +def UndefinedFuncTemplate : DiagGroup<"undefined-func-template">; def DeleteIncomplete : DiagGroup<"delete-incomplete">; def DeleteNonVirtualDtor : DiagGroup<"delete-non-virtual-dtor">; Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -3883,7 +3883,15 @@ "in instantiation of template type alias %0 requested here">; def note_template_exception_spec_instantiation_here : Note< "in instantiation of exception specification for %0 requested here">; - +def warn_var_template_missing : Warning<"instantiation of variable %q0 " + "required here, but %q1 is not defined">, InGroup; +def warn_func_template_missing : Warning<"instantiation of function %q0 " + "required here, but %q1 is not defined">, InGroup, + DefaultIgnore; +def note_inst_declaration_hint : Note<"add an explicit instantiation " + "declaration to suppress this warning if %q0 is explicitly instantiated in " + "another translation unit">; + def note_default_arg_instantiation_here : Note< "in instantiation of default argument for '%0' required here">; def note_default_function_arg_instantiation_here : Note< Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -7171,7 +7171,8 @@ void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, FunctionDecl *Function, bool Recursive = false, - bool DefinitionRequired = false); + bool DefinitionRequired = false, + bool AtEndOfTU = false); VarTemplateSpecializationDecl *BuildVarTemplateInstantiation( VarTemplateDecl *VarTemplate, VarDecl *FromVar, const TemplateArgumentList &TemplateArgList, @@ -7195,7 +7196,8 @@ const MultiLevelTemplateArgumentList &TemplateArgs); void InstantiateVariableDefinition(SourceLocation PointOfInstantiation, VarDecl *Var, bool Recursive = false, - bool DefinitionRequired = false); + bool DefinitionRequired = false, + bool AtEndOfTU = false); void InstantiateStaticDataMemberDefinition( SourceLocation PointOfInstantiation, VarDecl *Var, Index: lib/AST/Decl.cpp =================================================================== --- lib/AST/Decl.cpp +++ lib/AST/Decl.cpp @@ -1404,6 +1404,40 @@ printQualifiedName(OS, getASTContext().getPrintingPolicy()); } +namespace { + +/// \brief Prints template parameters in diagnostic messages. +/// +/// Allows a bit more readable reference to templates in the case of several +/// template levels. For instance, a reference to the template function \c meth +/// in the code: +/// +/// \code +/// template struct C1 { +/// template class TC> struct C2 { +/// template static void meth(); +/// }; +/// }; +/// \endcode +/// +/// is printed as C1::C2::meth rather than C1::C2::meth. +/// +void printTemplateParameters(raw_ostream &OS, const TemplateDecl *Templ) { + OS << "<"; + TemplateParameterList *TPL = Templ->getTemplateParameters(); + for (unsigned I = 0, E = TPL->size(); I != E; ++I) { + if (I != 0) + OS << ","; + const NamedDecl *Param = TPL->getParam(I); + if (Param->isTemplateParameterPack()) + OS << "..."; + OS << Param->getDeclName(); + } + OS << ">"; +} + +} + void NamedDecl::printQualifiedName(raw_ostream &OS, const PrintingPolicy &P) const { const DeclContext *Ctx = getDeclContext(); @@ -1444,8 +1478,13 @@ } else if (const auto *RD = dyn_cast(*I)) { if (!RD->getIdentifier()) OS << "(anonymous " << RD->getKindName() << ')'; - else + else { OS << *RD; + if (P.PrintTemplateParameters) + if (auto *CXXRD = dyn_cast(RD)) + if (ClassTemplateDecl *Templ = CXXRD->getDescribedClassTemplate()) + printTemplateParameters(OS, Templ); + } } else if (const auto *FD = dyn_cast(*I)) { const FunctionProtoType *FT = nullptr; if (FD->hasWrittenPrototype()) @@ -1482,9 +1521,12 @@ OS << "::"; } - if (getDeclName()) - OS << *this; - else + if (getDeclName()) { + printName(OS); + if (P.PrintTemplateParameters) + if (const TemplateDecl *TD = getDescribedTemplate()) + printTemplateParameters(OS, TD); + } else OS << "(anonymous)"; } Index: lib/AST/DeclBase.cpp =================================================================== --- lib/AST/DeclBase.cpp +++ lib/AST/DeclBase.cpp @@ -196,6 +196,17 @@ return isa(this); } +TemplateDecl *Decl::getDescribedTemplate() const { + if (auto *FD = dyn_cast(this)) + return FD->getDescribedFunctionTemplate(); + else if (auto *RD = dyn_cast(this)) + return RD->getDescribedClassTemplate(); + else if (auto *VD = dyn_cast(this)) + return VD->getDescribedVarTemplate(); + + return nullptr; +} + const DeclContext *Decl::getParentFunctionOrMethod() const { for (const DeclContext *DC = getDeclContext(); DC && !DC->isTranslationUnit() && !DC->isNamespace(); Index: lib/ASTMatchers/ASTMatchersInternal.cpp =================================================================== --- lib/ASTMatchers/ASTMatchersInternal.cpp +++ lib/ASTMatchers/ASTMatchersInternal.cpp @@ -469,13 +469,11 @@ llvm::SmallString<128> NodeName = StringRef("::"); llvm::raw_svector_ostream OS(NodeName); - if (SkipUnwritten) { - PrintingPolicy Policy = Node.getASTContext().getPrintingPolicy(); + PrintingPolicy Policy = Node.getASTContext().getPrintingPolicy(); + Policy.PrintTemplateParameters = false; + if (SkipUnwritten) Policy.SuppressUnwrittenScope = true; - Node.printQualifiedName(OS, Policy); - } else { - Node.printQualifiedName(OS); - } + Node.printQualifiedName(OS, Policy); const StringRef FullName = OS.str(); Index: lib/Sema/SemaOverload.cpp =================================================================== --- lib/Sema/SemaOverload.cpp +++ lib/Sema/SemaOverload.cpp @@ -9324,11 +9324,8 @@ } static TemplateDecl *getDescribedTemplate(Decl *Templated) { - if (FunctionDecl *FD = dyn_cast(Templated)) - return FD->getDescribedFunctionTemplate(); - else if (CXXRecordDecl *RD = dyn_cast(Templated)) - return RD->getDescribedClassTemplate(); - + if (TemplateDecl *TD = Templated->getDescribedTemplate()) + return TD; llvm_unreachable("Unsupported: Getting the described template declaration" " for bad deduction diagnosis"); } Index: lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- lib/Sema/SemaTemplateInstantiateDecl.cpp +++ lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3530,7 +3530,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, FunctionDecl *Function, bool Recursive, - bool DefinitionRequired) { + bool DefinitionRequired, + bool AtEndOfTU) { if (Function->isInvalidDecl() || Function->isDefined()) return; @@ -3604,6 +3605,15 @@ assert(!Recursive); PendingInstantiations.push_back( std::make_pair(Function, PointOfInstantiation)); + } else if (Function->getTemplateSpecializationKind() + == TSK_ImplicitInstantiation) { + if (AtEndOfTU && !getDiagnostics().hasErrorOccurred()) { + Diag(PointOfInstantiation, diag::warn_func_template_missing) + << Function << PatternDecl; + if (getLangOpts().CPlusPlus11) + Diag(PointOfInstantiation, diag::note_inst_declaration_hint) + << Function; + } } return; @@ -3951,7 +3961,7 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation, VarDecl *Var, bool Recursive, - bool DefinitionRequired) { + bool DefinitionRequired, bool AtEndOfTU) { if (Var->isInvalidDecl()) return; @@ -4083,6 +4093,15 @@ == TSK_ExplicitInstantiationDefinition) { PendingInstantiations.push_back( std::make_pair(Var, PointOfInstantiation)); + } else if (Var->getTemplateSpecializationKind() + == TSK_ImplicitInstantiation) { + // Warn about missing definition at the end of translation unit. + if (AtEndOfTU && !getDiagnostics().hasErrorOccurred()) { + Diag(PointOfInstantiation, diag::warn_var_template_missing) + << Var << PatternDecl; + if (getLangOpts().CPlusPlus11) + Diag(PointOfInstantiation, diag::note_inst_declaration_hint) << Var; + } } return; @@ -4852,7 +4871,7 @@ bool DefinitionRequired = Function->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition; InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true, - DefinitionRequired); + DefinitionRequired, true); continue; } @@ -4893,7 +4912,7 @@ // Instantiate static data member definitions or variable template // specializations. InstantiateVariableDefinition(/*FIXME:*/ Inst.second, Var, true, - DefinitionRequired); + DefinitionRequired, true); } } Index: test/CXX/temp/temp.decls/temp.mem/p1.cpp =================================================================== --- test/CXX/temp/temp.decls/temp.mem/p1.cpp +++ test/CXX/temp/temp.decls/temp.mem/p1.cpp @@ -10,6 +10,7 @@ } }; }; +extern template bool A::cond; int foo() { A::cond = true; Index: test/Modules/merge-using-decls.cpp =================================================================== --- test/Modules/merge-using-decls.cpp +++ test/Modules/merge-using-decls.cpp @@ -37,34 +37,34 @@ // Here, we're instantiating the definition from 'A' and merging the definition // from 'B' into it. -// expected-error@b.h:* {{'E::value' from module 'B' is not present in definition of 'E' in module 'A'}} -// expected-error@b.h:* {{'E::v' from module 'B' is not present in definition of 'E' in module 'A'}} +// expected-error@b.h:* {{'E::value' from module 'B' is not present in definition of 'E' in module 'A'}} +// expected-error@b.h:* {{'E::v' from module 'B' is not present in definition of 'E' in module 'A'}} -// expected-error@b.h:* {{'F::type' from module 'B' is not present in definition of 'F' in module 'A'}} -// expected-error@b.h:* {{'F::t' from module 'B' is not present in definition of 'F' in module 'A'}} -// expected-error@b.h:* {{'F::value' from module 'B' is not present in definition of 'F' in module 'A'}} -// expected-error@b.h:* {{'F::v' from module 'B' is not present in definition of 'F' in module 'A'}} +// expected-error@b.h:* {{'F::type' from module 'B' is not present in definition of 'F' in module 'A'}} +// expected-error@b.h:* {{'F::t' from module 'B' is not present in definition of 'F' in module 'A'}} +// expected-error@b.h:* {{'F::value' from module 'B' is not present in definition of 'F' in module 'A'}} +// expected-error@b.h:* {{'F::v' from module 'B' is not present in definition of 'F' in module 'A'}} // expected-note@a.h:* +{{does not match}} #else // Here, we're instantiating the definition from 'B' and merging the definition // from 'A' into it. -// expected-error@a.h:* {{'D::type' from module 'A' is not present in definition of 'D' in module 'B'}} -// expected-error@a.h:* {{'D::value' from module 'A' is not present in definition of 'D' in module 'B'}} +// expected-error@a.h:* {{'D::type' from module 'A' is not present in definition of 'D' in module 'B'}} +// expected-error@a.h:* {{'D::value' from module 'A' is not present in definition of 'D' in module 'B'}} // expected-error@b.h:* 2{{'typename' keyword used on a non-type}} // expected-error@b.h:* 2{{dependent using declaration resolved to type without 'typename'}} -// expected-error@a.h:* {{'E::type' from module 'A' is not present in definition of 'E' in module 'B'}} -// expected-error@a.h:* {{'E::t' from module 'A' is not present in definition of 'E' in module 'B'}} -// expected-error@a.h:* {{'E::value' from module 'A' is not present in definition of 'E' in module 'B'}} -// expected-error@a.h:* {{'E::v' from module 'A' is not present in definition of 'E' in module 'B'}} +// expected-error@a.h:* {{'E::type' from module 'A' is not present in definition of 'E' in module 'B'}} +// expected-error@a.h:* {{'E::t' from module 'A' is not present in definition of 'E' in module 'B'}} +// expected-error@a.h:* {{'E::value' from module 'A' is not present in definition of 'E' in module 'B'}} +// expected-error@a.h:* {{'E::v' from module 'A' is not present in definition of 'E' in module 'B'}} // expected-note@b.h:* 2{{definition has no member}} -// expected-error@a.h:* {{'F::type' from module 'A' is not present in definition of 'F' in module 'B'}} -// expected-error@a.h:* {{'F::t' from module 'A' is not present in definition of 'F' in module 'B'}} -// expected-error@a.h:* {{'F::value' from module 'A' is not present in definition of 'F' in module 'B'}} -// expected-error@a.h:* {{'F::v' from module 'A' is not present in definition of 'F' in module 'B'}} +// expected-error@a.h:* {{'F::type' from module 'A' is not present in definition of 'F' in module 'B'}} +// expected-error@a.h:* {{'F::t' from module 'A' is not present in definition of 'F' in module 'B'}} +// expected-error@a.h:* {{'F::value' from module 'A' is not present in definition of 'F' in module 'B'}} +// expected-error@a.h:* {{'F::v' from module 'A' is not present in definition of 'F' in module 'B'}} // expected-note@b.h:* +{{does not match}} // expected-note@b.h:* +{{target of using}} Index: test/OpenMP/parallel_ast_print.cpp =================================================================== --- test/OpenMP/parallel_ast_print.cpp +++ test/OpenMP/parallel_ast_print.cpp @@ -132,7 +132,7 @@ // CHECK-NEXT: } // CHECK: template struct S { // CHECK: static T TS; -// CHECK-NEXT: #pragma omp threadprivate(S::TS) +// CHECK-NEXT: #pragma omp threadprivate(S::TS) // CHECK: }; template @@ -227,4 +227,7 @@ } } +template +T S::TS = 0; + #endif Index: test/OpenMP/parallel_sections_ast_print.cpp =================================================================== --- test/OpenMP/parallel_sections_ast_print.cpp +++ test/OpenMP/parallel_sections_ast_print.cpp @@ -25,7 +25,7 @@ // CHECK-NEXT: } // CHECK: template struct S { // CHECK: static T TS; -// CHECK-NEXT: #pragma omp threadprivate(S::TS) +// CHECK-NEXT: #pragma omp threadprivate(S::TS) // CHECK: }; template @@ -141,4 +141,7 @@ return tmain(b, &b) + tmain(x, &x); } +template +T S::TS = 0; + #endif Index: test/OpenMP/target_parallel_ast_print.cpp =================================================================== --- test/OpenMP/target_parallel_ast_print.cpp +++ test/OpenMP/target_parallel_ast_print.cpp @@ -25,7 +25,7 @@ // CHECK-NEXT: } // CHECK: template struct S { // CHECK: static T TS; -// CHECK-NEXT: #pragma omp threadprivate(S::TS) +// CHECK-NEXT: #pragma omp threadprivate(S::TS) // CHECK: }; template @@ -227,4 +227,7 @@ return tmain(argc, &argc) + tmain(argv[0][0], argv[0]); } +extern template int S::TS; +extern template char S::TS; + #endif Index: test/OpenMP/task_ast_print.cpp =================================================================== --- test/OpenMP/task_ast_print.cpp +++ test/OpenMP/task_ast_print.cpp @@ -76,7 +76,7 @@ // CHECK-NEXT: } // CHECK: template struct S { // CHECK: static T TS; -// CHECK-NEXT: #pragma omp threadprivate(S::TS) +// CHECK-NEXT: #pragma omp threadprivate(S::TS) // CHECK: }; template @@ -149,4 +149,7 @@ return tmain(b, &b) + tmain(x, &x); } +extern template int S::TS; +extern template long S::TS; + #endif Index: test/OpenMP/teams_ast_print.cpp =================================================================== --- test/OpenMP/teams_ast_print.cpp +++ test/OpenMP/teams_ast_print.cpp @@ -25,7 +25,7 @@ // CHECK-NEXT: } // CHECK: template struct S { // CHECK: static T TS; -// CHECK-NEXT: #pragma omp threadprivate(S::TS) +// CHECK-NEXT: #pragma omp threadprivate(S::TS) // CHECK: }; template @@ -109,4 +109,6 @@ return tmain(b, &b) + tmain(x, &x); } +extern template int S::TS; +extern template long S::TS; #endif Index: test/OpenMP/threadprivate_ast_print.cpp =================================================================== --- test/OpenMP/threadprivate_ast_print.cpp +++ test/OpenMP/threadprivate_ast_print.cpp @@ -69,4 +69,5 @@ return (foo()); } +extern template int ST::m; #endif Index: test/SemaCXX/PR10177.cpp =================================================================== --- test/SemaCXX/PR10177.cpp +++ test/SemaCXX/PR10177.cpp @@ -54,6 +54,7 @@ namespace { template extern int n; } template int g() { return n; } +namespace { extern template int n; } #endif Index: test/SemaCXX/dllexport.cpp =================================================================== --- test/SemaCXX/dllexport.cpp +++ test/SemaCXX/dllexport.cpp @@ -113,15 +113,15 @@ template int VarTmplRedecl2 = 1; template extern int VarTmplRedecl3; // expected-note{{previous declaration is here}} -template __declspec(dllexport) extern int VarTmplRedecl3; // expected-error{{redeclaration of 'VarTmplRedecl3' cannot add 'dllexport' attribute}} +template __declspec(dllexport) extern int VarTmplRedecl3; // expected-error{{redeclaration of 'VarTmplRedecl3' cannot add 'dllexport' attribute}} // External linkage is required. -template __declspec(dllexport) static int StaticVarTmpl; // expected-error{{'StaticVarTmpl' must have external linkage when declared 'dllexport'}} -template __declspec(dllexport) Internal InternalTypeVarTmpl; // expected-error{{'InternalTypeVarTmpl' must have external linkage when declared 'dllexport'}} -namespace { template __declspec(dllexport) int InternalVarTmpl; } // expected-error{{'(anonymous namespace)::InternalVarTmpl' must have external linkage when declared 'dllexport'}} +template __declspec(dllexport) static int StaticVarTmpl; // expected-error{{'StaticVarTmpl' must have external linkage when declared 'dllexport'}} +template __declspec(dllexport) Internal InternalTypeVarTmpl; // expected-error{{'InternalTypeVarTmpl' must have external linkage when declared 'dllexport'}} +namespace { template __declspec(dllexport) int InternalVarTmpl; } // expected-error{{'(anonymous namespace)::InternalVarTmpl' must have external linkage when declared 'dllexport'}} namespace ns { template __declspec(dllexport) int ExternalVarTmpl = 1; } -template __declspec(dllexport) auto InternalAutoTypeVarTmpl = Internal(); // expected-error{{'InternalAutoTypeVarTmpl' must have external linkage when declared 'dllexport'}} +template __declspec(dllexport) auto InternalAutoTypeVarTmpl = Internal(); // expected-error{{'InternalAutoTypeVarTmpl' must have external linkage when declared 'dllexport'}} template __declspec(dllexport) auto ExternalAutoTypeVarTmpl = External(); template External ExternalAutoTypeVarTmpl; @@ -264,10 +264,10 @@ template void funcTmplRedecl2() {} template void funcTmplRedecl3(); // expected-note{{previous declaration is here}} -template __declspec(dllexport) void funcTmplRedecl3(); // expected-error{{redeclaration of 'funcTmplRedecl3' cannot add 'dllexport' attribute}} +template __declspec(dllexport) void funcTmplRedecl3(); // expected-error{{redeclaration of 'funcTmplRedecl3' cannot add 'dllexport' attribute}} template void funcTmplRedecl4(); // expected-note{{previous declaration is here}} -template __declspec(dllexport) inline void funcTmplRedecl4() {} // expected-error{{redeclaration of 'funcTmplRedecl4' cannot add 'dllexport' attribute}} +template __declspec(dllexport) inline void funcTmplRedecl4() {} // expected-error{{redeclaration of 'funcTmplRedecl4' cannot add 'dllexport' attribute}} // Function template friends struct FuncTmplFriend { @@ -278,13 +278,13 @@ }; template __declspec(dllexport) void funcTmplFriend1() {} template void funcTmplFriend2() {} -template __declspec(dllexport) void funcTmplFriend3() {} // expected-error{{redeclaration of 'funcTmplFriend3' cannot add 'dllexport' attribute}} -template __declspec(dllexport) inline void funcTmplFriend4() {} // expected-error{{redeclaration of 'funcTmplFriend4' cannot add 'dllexport' attribute}} +template __declspec(dllexport) void funcTmplFriend3() {} // expected-error{{redeclaration of 'funcTmplFriend3' cannot add 'dllexport' attribute}} +template __declspec(dllexport) inline void funcTmplFriend4() {} // expected-error{{redeclaration of 'funcTmplFriend4' cannot add 'dllexport' attribute}} // External linkage is required. -template __declspec(dllexport) static int staticFuncTmpl(); // expected-error{{'staticFuncTmpl' must have external linkage when declared 'dllexport'}} -template __declspec(dllexport) Internal internalRetFuncTmpl(); // expected-error{{'internalRetFuncTmpl' must have external linkage when declared 'dllexport'}} -namespace { template __declspec(dllexport) void internalFuncTmpl(); } // expected-error{{'(anonymous namespace)::internalFuncTmpl' must have external linkage when declared 'dllexport'}} +template __declspec(dllexport) static int staticFuncTmpl(); // expected-error{{'staticFuncTmpl' must have external linkage when declared 'dllexport'}} +template __declspec(dllexport) Internal internalRetFuncTmpl(); // expected-error{{'internalRetFuncTmpl' must have external linkage when declared 'dllexport'}} +namespace { template __declspec(dllexport) void internalFuncTmpl(); } // expected-error{{'(anonymous namespace)::internalFuncTmpl' must have external linkage when declared 'dllexport'}} namespace ns { template __declspec(dllexport) void externalFuncTmpl(); } @@ -795,17 +795,17 @@ #endif // __has_feature(cxx_variable_templates) }; -template __declspec(dllexport) void MemTmplRedecl::normalDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalDef' cannot add 'dllexport' attribute}} -template __declspec(dllexport) inline void MemTmplRedecl::normalInlineDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalInlineDef' cannot add 'dllexport' attribute}} -template __declspec(dllexport) void MemTmplRedecl::normalInlineDecl() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalInlineDecl' cannot add 'dllexport' attribute}} -template __declspec(dllexport) void MemTmplRedecl::staticDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticDef' cannot add 'dllexport' attribute}} -template __declspec(dllexport) inline void MemTmplRedecl::staticInlineDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDef' cannot add 'dllexport' attribute}} -template __declspec(dllexport) void MemTmplRedecl::staticInlineDecl() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDecl' cannot add 'dllexport' attribute}} +template __declspec(dllexport) void MemTmplRedecl::normalDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalDef' cannot add 'dllexport' attribute}} +template __declspec(dllexport) inline void MemTmplRedecl::normalInlineDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalInlineDef' cannot add 'dllexport' attribute}} +template __declspec(dllexport) void MemTmplRedecl::normalInlineDecl() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalInlineDecl' cannot add 'dllexport' attribute}} +template __declspec(dllexport) void MemTmplRedecl::staticDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticDef' cannot add 'dllexport' attribute}} +template __declspec(dllexport) inline void MemTmplRedecl::staticInlineDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDef' cannot add 'dllexport' attribute}} +template __declspec(dllexport) void MemTmplRedecl::staticInlineDecl() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDecl' cannot add 'dllexport' attribute}} #if __has_feature(cxx_variable_templates) -template __declspec(dllexport) int MemTmplRedecl::StaticField = 1; // expected-error{{redeclaration of 'MemTmplRedecl::StaticField' cannot add 'dllexport' attribute}} -template __declspec(dllexport) const int MemTmplRedecl::StaticConstField = 1; // expected-error{{redeclaration of 'MemTmplRedecl::StaticConstField' cannot add 'dllexport' attribute}} -template __declspec(dllexport) constexpr int MemTmplRedecl::ConstexprField; // expected-error{{redeclaration of 'MemTmplRedecl::ConstexprField' cannot add 'dllexport' attribute}} +template __declspec(dllexport) int MemTmplRedecl::StaticField = 1; // expected-error{{redeclaration of 'MemTmplRedecl::StaticField' cannot add 'dllexport' attribute}} +template __declspec(dllexport) const int MemTmplRedecl::StaticConstField = 1; // expected-error{{redeclaration of 'MemTmplRedecl::StaticConstField' cannot add 'dllexport' attribute}} +template __declspec(dllexport) constexpr int MemTmplRedecl::ConstexprField; // expected-error{{redeclaration of 'MemTmplRedecl::ConstexprField' cannot add 'dllexport' attribute}} #endif // __has_feature(cxx_variable_templates) @@ -998,19 +998,19 @@ constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}} }; -template __declspec(dllexport) void CTMR::normalDef() {} // expected-error{{redeclaration of 'CTMR::normalDef' cannot add 'dllexport' attribute}} -template __declspec(dllexport) inline void CTMR::normalInlineDef() {} // expected-error{{redeclaration of 'CTMR::normalInlineDef' cannot add 'dllexport' attribute}} -template __declspec(dllexport) void CTMR::normalInlineDecl() {} // expected-error{{redeclaration of 'CTMR::normalInlineDecl' cannot add 'dllexport' attribute}} -template __declspec(dllexport) void CTMR::virtualDef() {} // expected-error{{redeclaration of 'CTMR::virtualDef' cannot add 'dllexport' attribute}} -template __declspec(dllexport) inline void CTMR::virtualInlineDef() {} // expected-error{{redeclaration of 'CTMR::virtualInlineDef' cannot add 'dllexport' attribute}} -template __declspec(dllexport) void CTMR::virtualInlineDecl() {} // expected-error{{redeclaration of 'CTMR::virtualInlineDecl' cannot add 'dllexport' attribute}} -template __declspec(dllexport) void CTMR::staticDef() {} // expected-error{{redeclaration of 'CTMR::staticDef' cannot add 'dllexport' attribute}} -template __declspec(dllexport) inline void CTMR::staticInlineDef() {} // expected-error{{redeclaration of 'CTMR::staticInlineDef' cannot add 'dllexport' attribute}} -template __declspec(dllexport) void CTMR::staticInlineDecl() {} // expected-error{{redeclaration of 'CTMR::staticInlineDecl' cannot add 'dllexport' attribute}} +template __declspec(dllexport) void CTMR::normalDef() {} // expected-error{{redeclaration of 'CTMR::normalDef' cannot add 'dllexport' attribute}} +template __declspec(dllexport) inline void CTMR::normalInlineDef() {} // expected-error{{redeclaration of 'CTMR::normalInlineDef' cannot add 'dllexport' attribute}} +template __declspec(dllexport) void CTMR::normalInlineDecl() {} // expected-error{{redeclaration of 'CTMR::normalInlineDecl' cannot add 'dllexport' attribute}} +template __declspec(dllexport) void CTMR::virtualDef() {} // expected-error{{redeclaration of 'CTMR::virtualDef' cannot add 'dllexport' attribute}} +template __declspec(dllexport) inline void CTMR::virtualInlineDef() {} // expected-error{{redeclaration of 'CTMR::virtualInlineDef' cannot add 'dllexport' attribute}} +template __declspec(dllexport) void CTMR::virtualInlineDecl() {} // expected-error{{redeclaration of 'CTMR::virtualInlineDecl' cannot add 'dllexport' attribute}} +template __declspec(dllexport) void CTMR::staticDef() {} // expected-error{{redeclaration of 'CTMR::staticDef' cannot add 'dllexport' attribute}} +template __declspec(dllexport) inline void CTMR::staticInlineDef() {} // expected-error{{redeclaration of 'CTMR::staticInlineDef' cannot add 'dllexport' attribute}} +template __declspec(dllexport) void CTMR::staticInlineDecl() {} // expected-error{{redeclaration of 'CTMR::staticInlineDecl' cannot add 'dllexport' attribute}} -template __declspec(dllexport) int CTMR::StaticField = 1; // expected-error{{redeclaration of 'CTMR::StaticField' cannot add 'dllexport' attribute}} -template __declspec(dllexport) const int CTMR::StaticConstField = 1; // expected-error{{redeclaration of 'CTMR::StaticConstField' cannot add 'dllexport' attribute}} -template __declspec(dllexport) constexpr int CTMR::ConstexprField; // expected-error{{redeclaration of 'CTMR::ConstexprField' cannot add 'dllexport' attribute}} +template __declspec(dllexport) int CTMR::StaticField = 1; // expected-error{{redeclaration of 'CTMR::StaticField' cannot add 'dllexport' attribute}} +template __declspec(dllexport) const int CTMR::StaticConstField = 1; // expected-error{{redeclaration of 'CTMR::StaticConstField' cannot add 'dllexport' attribute}} +template __declspec(dllexport) constexpr int CTMR::ConstexprField; // expected-error{{redeclaration of 'CTMR::ConstexprField' cannot add 'dllexport' attribute}} @@ -1074,17 +1074,17 @@ #endif // __has_feature(cxx_variable_templates) }; -template template __declspec(dllexport) void CTMTR::normalDef() {} // expected-error{{redeclaration of 'CTMTR::normalDef' cannot add 'dllexport' attribute}} -template template __declspec(dllexport) inline void CTMTR::normalInlineDef() {} // expected-error{{redeclaration of 'CTMTR::normalInlineDef' cannot add 'dllexport' attribute}} -template template __declspec(dllexport) void CTMTR::normalInlineDecl() {} // expected-error{{redeclaration of 'CTMTR::normalInlineDecl' cannot add 'dllexport' attribute}} -template template __declspec(dllexport) void CTMTR::staticDef() {} // expected-error{{redeclaration of 'CTMTR::staticDef' cannot add 'dllexport' attribute}} -template template __declspec(dllexport) inline void CTMTR::staticInlineDef() {} // expected-error{{redeclaration of 'CTMTR::staticInlineDef' cannot add 'dllexport' attribute}} -template template __declspec(dllexport) void CTMTR::staticInlineDecl() {} // expected-error{{redeclaration of 'CTMTR::staticInlineDecl' cannot add 'dllexport' attribute}} +template template __declspec(dllexport) void CTMTR::normalDef() {} // expected-error{{redeclaration of 'CTMTR::normalDef' cannot add 'dllexport' attribute}} +template template __declspec(dllexport) inline void CTMTR::normalInlineDef() {} // expected-error{{redeclaration of 'CTMTR::normalInlineDef' cannot add 'dllexport' attribute}} +template template __declspec(dllexport) void CTMTR::normalInlineDecl() {} // expected-error{{redeclaration of 'CTMTR::normalInlineDecl' cannot add 'dllexport' attribute}} +template template __declspec(dllexport) void CTMTR::staticDef() {} // expected-error{{redeclaration of 'CTMTR::staticDef' cannot add 'dllexport' attribute}} +template template __declspec(dllexport) inline void CTMTR::staticInlineDef() {} // expected-error{{redeclaration of 'CTMTR::staticInlineDef' cannot add 'dllexport' attribute}} +template template __declspec(dllexport) void CTMTR::staticInlineDecl() {} // expected-error{{redeclaration of 'CTMTR::staticInlineDecl' cannot add 'dllexport' attribute}} #if __has_feature(cxx_variable_templates) -template template __declspec(dllexport) int CTMTR::StaticField = 1; // expected-error{{redeclaration of 'CTMTR::StaticField' cannot add 'dllexport' attribute}} -template template __declspec(dllexport) const int CTMTR::StaticConstField = 1; // expected-error{{redeclaration of 'CTMTR::StaticConstField' cannot add 'dllexport' attribute}} -template template __declspec(dllexport) constexpr int CTMTR::ConstexprField; // expected-error{{redeclaration of 'CTMTR::ConstexprField' cannot add 'dllexport' attribute}} +template template __declspec(dllexport) int CTMTR::StaticField = 1; // expected-error{{redeclaration of 'CTMTR::StaticField' cannot add 'dllexport' attribute}} +template template __declspec(dllexport) const int CTMTR::StaticConstField = 1; // expected-error{{redeclaration of 'CTMTR::StaticConstField' cannot add 'dllexport' attribute}} +template template __declspec(dllexport) constexpr int CTMTR::ConstexprField; // expected-error{{redeclaration of 'CTMTR::ConstexprField' cannot add 'dllexport' attribute}} #endif // __has_feature(cxx_variable_templates) // FIXME: Precedence rules seem to be different for classes. Index: test/SemaCXX/dllimport.cpp =================================================================== --- test/SemaCXX/dllimport.cpp +++ test/SemaCXX/dllimport.cpp @@ -136,10 +136,10 @@ // Declare, then reject definition. template __declspec(dllimport) extern int ExternVarTmplDeclInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} -template int ExternVarTmplDeclInit = 1; // expected-warning{{'ExternVarTmplDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +template int ExternVarTmplDeclInit = 1; // expected-warning{{'ExternVarTmplDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} template __declspec(dllimport) int VarTmplDeclInit; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} -template int VarTmplDeclInit = 1; // expected-warning{{'VarTmplDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +template int VarTmplDeclInit = 1; // expected-warning{{'VarTmplDeclInit' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} // Redeclarations template __declspec(dllimport) extern int VarTmplRedecl1; @@ -149,18 +149,18 @@ template __declspec(dllimport) int VarTmplRedecl2; template __declspec(dllimport) extern int VarTmplRedecl3; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} -template extern int VarTmplRedecl3; // expected-warning{{'VarTmplRedecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +template extern int VarTmplRedecl3; // expected-warning{{'VarTmplRedecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} template extern int VarTmplRedecl4; // expected-note{{previous declaration is here}} -template __declspec(dllimport) extern int VarTmplRedecl4; // expected-error{{redeclaration of 'VarTmplRedecl4' cannot add 'dllimport' attribute}} +template __declspec(dllimport) extern int VarTmplRedecl4; // expected-error{{redeclaration of 'VarTmplRedecl4' cannot add 'dllimport' attribute}} // External linkage is required. -template __declspec(dllimport) static int StaticVarTmpl; // expected-error{{'StaticVarTmpl' must have external linkage when declared 'dllimport'}} -template __declspec(dllimport) Internal InternalTypeVarTmpl; // expected-error{{'InternalTypeVarTmpl' must have external linkage when declared 'dllimport'}} -namespace { template __declspec(dllimport) int InternalVarTmpl; } // expected-error{{'(anonymous namespace)::InternalVarTmpl' must have external linkage when declared 'dllimport'}} +template __declspec(dllimport) static int StaticVarTmpl; // expected-error{{'StaticVarTmpl' must have external linkage when declared 'dllimport'}} +template __declspec(dllimport) Internal InternalTypeVarTmpl; // expected-error{{'InternalTypeVarTmpl' must have external linkage when declared 'dllimport'}} +namespace { template __declspec(dllimport) int InternalVarTmpl; } // expected-error{{'(anonymous namespace)::InternalVarTmpl' must have external linkage when declared 'dllimport'}} namespace ns { template __declspec(dllimport) int ExternalVarTmpl; } -template __declspec(dllimport) auto InternalAutoTypeVarTmpl = Internal(); // expected-error{{definition of dllimport data}} // expected-error{{'InternalAutoTypeVarTmpl' must have external linkage when declared 'dllimport'}} +template __declspec(dllimport) auto InternalAutoTypeVarTmpl = Internal(); // expected-error{{definition of dllimport data}} // expected-error{{'InternalAutoTypeVarTmpl' must have external linkage when declared 'dllimport'}} template int VarTmpl; @@ -329,7 +329,7 @@ // expected-warning@+5{{'dllimport' attribute ignored on inline function}} // expected-warning@+5{{'dllimport' attribute ignored on inline function}} // expected-warning@+6{{'dllimport' attribute ignored on inline function}} -// expected-warning@+9{{'inlineFuncTmplDef' redeclared inline; 'dllimport' attribute ignored}} +// expected-warning@+9{{'inlineFuncTmplDef' redeclared inline; 'dllimport' attribute ignored}} #endif template __declspec(dllimport) inline void inlineFuncTmpl1() {} template inline void __attribute__((dllimport)) inlineFuncTmpl2() {} @@ -345,17 +345,17 @@ template __declspec(dllimport) void funcTmplRedecl1(); template __declspec(dllimport) void funcTmplRedecl2(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} -template void funcTmplRedecl2(); // expected-warning{{'funcTmplRedecl2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +template void funcTmplRedecl2(); // expected-warning{{'funcTmplRedecl2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} template __declspec(dllimport) void funcTmplRedecl3(); // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} -template void funcTmplRedecl3() {} // expected-warning{{'funcTmplRedecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +template void funcTmplRedecl3() {} // expected-warning{{'funcTmplRedecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} template void funcTmplRedecl4(); // expected-note{{previous declaration is here}} -template __declspec(dllimport) void funcTmplRedecl4(); // expected-error{{redeclaration of 'funcTmplRedecl4' cannot add 'dllimport' attribute}} +template __declspec(dllimport) void funcTmplRedecl4(); // expected-error{{redeclaration of 'funcTmplRedecl4' cannot add 'dllimport' attribute}} #ifdef MS template void funcTmplRedecl5(); // expected-note{{previous declaration is here}} -template __declspec(dllimport) inline void funcTmplRedecl5() {} // expected-error{{redeclaration of 'funcTmplRedecl5' cannot add 'dllimport' attribute}} +template __declspec(dllimport) inline void funcTmplRedecl5() {} // expected-error{{redeclaration of 'funcTmplRedecl5' cannot add 'dllimport' attribute}} #endif // Function template friends @@ -370,15 +370,15 @@ template friend __declspec(dllimport) inline void funcTmplFriend5(); }; template __declspec(dllimport) void funcTmplFriend1(); -template void funcTmplFriend2(); // expected-warning{{'funcTmplFriend2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} -template void funcTmplFriend3() {} // expected-warning{{'funcTmplFriend3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} -template __declspec(dllimport) void funcTmplFriend4(); // expected-error{{redeclaration of 'funcTmplFriend4' cannot add 'dllimport' attribute}} +template void funcTmplFriend2(); // expected-warning{{'funcTmplFriend2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +template void funcTmplFriend3() {} // expected-warning{{'funcTmplFriend3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +template __declspec(dllimport) void funcTmplFriend4(); // expected-error{{redeclaration of 'funcTmplFriend4' cannot add 'dllimport' attribute}} template inline void funcTmplFriend5() {} // External linkage is required. -template __declspec(dllimport) static int staticFuncTmpl(); // expected-error{{'staticFuncTmpl' must have external linkage when declared 'dllimport'}} -template __declspec(dllimport) Internal internalRetFuncTmpl(); // expected-error{{'internalRetFuncTmpl' must have external linkage when declared 'dllimport'}} -namespace { template __declspec(dllimport) void internalFuncTmpl(); } // expected-error{{'(anonymous namespace)::internalFuncTmpl' must have external linkage when declared 'dllimport'}} +template __declspec(dllimport) static int staticFuncTmpl(); // expected-error{{'staticFuncTmpl' must have external linkage when declared 'dllimport'}} +template __declspec(dllimport) Internal internalRetFuncTmpl(); // expected-error{{'internalRetFuncTmpl' must have external linkage when declared 'dllimport'}} +namespace { template __declspec(dllimport) void internalFuncTmpl(); } // expected-error{{'(anonymous namespace)::internalFuncTmpl' must have external linkage when declared 'dllimport'}} namespace ns { template __declspec(dllimport) void externalFuncTmpl(); } @@ -743,14 +743,14 @@ #endif // __has_feature(cxx_variable_templates) }; -template void ImportMemberTmpl::normalDef() {} // expected-warning{{'ImportMemberTmpl::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +template void ImportMemberTmpl::normalDef() {} // expected-warning{{'ImportMemberTmpl::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} template void ImportMemberTmpl::normalInlineDecl() {} -template void ImportMemberTmpl::staticDef() {} // expected-warning{{'ImportMemberTmpl::staticDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +template void ImportMemberTmpl::staticDef() {} // expected-warning{{'ImportMemberTmpl::staticDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} template void ImportMemberTmpl::staticInlineDecl() {} #ifdef GNU -// expected-warning@+3{{ImportMemberTmpl::normalInlineDef' redeclared inline; 'dllimport' attribute ignored}} -// expected-warning@+3{{ImportMemberTmpl::staticInlineDef' redeclared inline; 'dllimport' attribute ignored}} +// expected-warning@+3{{ImportMemberTmpl::normalInlineDef' redeclared inline; 'dllimport' attribute ignored}} +// expected-warning@+3{{ImportMemberTmpl::staticInlineDef' redeclared inline; 'dllimport' attribute ignored}} #endif template inline void ImportMemberTmpl::normalInlineDef() {} template inline void ImportMemberTmpl::staticInlineDef() {} @@ -783,31 +783,31 @@ #endif // __has_feature(cxx_variable_templates) }; -template __declspec(dllimport) void MemTmplRedecl::normalDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalDef' cannot add 'dllimport' attribute}} +template __declspec(dllimport) void MemTmplRedecl::normalDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalDef' cannot add 'dllimport' attribute}} // expected-error@-1{{dllimport cannot be applied to non-inline function definition}} #ifdef MS -template __declspec(dllimport) inline void MemTmplRedecl::normalInlineDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalInlineDef' cannot add 'dllimport' attribute}} +template __declspec(dllimport) inline void MemTmplRedecl::normalInlineDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalInlineDef' cannot add 'dllimport' attribute}} #else template __declspec(dllimport) inline void MemTmplRedecl::normalInlineDef() {} // expected-warning{{'dllimport' attribute ignored on inline function}} #endif -template __declspec(dllimport) void MemTmplRedecl::normalInlineDecl() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalInlineDecl' cannot add 'dllimport' attribute}} -template __declspec(dllimport) void MemTmplRedecl::staticDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticDef' cannot add 'dllimport' attribute}} +template __declspec(dllimport) void MemTmplRedecl::normalInlineDecl() {} // expected-error{{redeclaration of 'MemTmplRedecl::normalInlineDecl' cannot add 'dllimport' attribute}} +template __declspec(dllimport) void MemTmplRedecl::staticDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticDef' cannot add 'dllimport' attribute}} // expected-error@-1{{dllimport cannot be applied to non-inline function definition}} #ifdef MS -template __declspec(dllimport) inline void MemTmplRedecl::staticInlineDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDef' cannot add 'dllimport' attribute}} +template __declspec(dllimport) inline void MemTmplRedecl::staticInlineDef() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDef' cannot add 'dllimport' attribute}} #else template __declspec(dllimport) inline void MemTmplRedecl::staticInlineDef() {} // expected-warning{{'dllimport' attribute ignored on inline function}} #endif -template __declspec(dllimport) void MemTmplRedecl::staticInlineDecl() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDecl' cannot add 'dllimport' attribute}} +template __declspec(dllimport) void MemTmplRedecl::staticInlineDecl() {} // expected-error{{redeclaration of 'MemTmplRedecl::staticInlineDecl' cannot add 'dllimport' attribute}} #if __has_feature(cxx_variable_templates) -template __declspec(dllimport) int MemTmplRedecl::StaticField = 1; // expected-error{{redeclaration of 'MemTmplRedecl::StaticField' cannot add 'dllimport' attribute}} +template __declspec(dllimport) int MemTmplRedecl::StaticField = 1; // expected-error{{redeclaration of 'MemTmplRedecl::StaticField' cannot add 'dllimport' attribute}} // expected-error@-1{{definition of dllimport static field not allowed}} // expected-note@-2{{attribute is here}} -template __declspec(dllimport) const int MemTmplRedecl::StaticConstField = 1; // expected-error{{redeclaration of 'MemTmplRedecl::StaticConstField' cannot add 'dllimport' attribute}} +template __declspec(dllimport) const int MemTmplRedecl::StaticConstField = 1; // expected-error{{redeclaration of 'MemTmplRedecl::StaticConstField' cannot add 'dllimport' attribute}} // expected-error@-1{{definition of dllimport static field not allowed}} // expected-note@-2{{attribute is here}} -template __declspec(dllimport) constexpr int MemTmplRedecl::ConstexprField; // expected-error{{redeclaration of 'MemTmplRedecl::ConstexprField' cannot add 'dllimport' attribute}} +template __declspec(dllimport) constexpr int MemTmplRedecl::ConstexprField; // expected-error{{redeclaration of 'MemTmplRedecl::ConstexprField' cannot add 'dllimport' attribute}} // expected-error@-1{{definition of dllimport static field not allowed}} // expected-note@-2{{attribute is here}} #endif // __has_feature(cxx_variable_templates) @@ -1013,21 +1013,21 @@ // NB: MSVC is inconsistent here and disallows *InlineDef on class templates, // but allows it on classes. We allow both. -template void ImportClassTmplMembers::normalDef() {} // expected-warning{{'ImportClassTmplMembers::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +template void ImportClassTmplMembers::normalDef() {} // expected-warning{{'ImportClassTmplMembers::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} #ifdef GNU -// expected-warning@+2{{'ImportClassTmplMembers::normalInlineDef' redeclared inline; 'dllimport' attribute ignored}} +// expected-warning@+2{{'ImportClassTmplMembers::normalInlineDef' redeclared inline; 'dllimport' attribute ignored}} #endif template inline void ImportClassTmplMembers::normalInlineDef() {} template void ImportClassTmplMembers::normalInlineDecl() {} -template void ImportClassTmplMembers::virtualDef() {} // expected-warning{{'ImportClassTmplMembers::virtualDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +template void ImportClassTmplMembers::virtualDef() {} // expected-warning{{'ImportClassTmplMembers::virtualDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} #ifdef GNU -// expected-warning@+2{{'ImportClassTmplMembers::virtualInlineDef' redeclared inline; 'dllimport' attribute ignored}} +// expected-warning@+2{{'ImportClassTmplMembers::virtualInlineDef' redeclared inline; 'dllimport' attribute ignored}} #endif template inline void ImportClassTmplMembers::virtualInlineDef() {} template void ImportClassTmplMembers::virtualInlineDecl() {} -template void ImportClassTmplMembers::staticDef() {} // expected-warning{{'ImportClassTmplMembers::staticDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +template void ImportClassTmplMembers::staticDef() {} // expected-warning{{'ImportClassTmplMembers::staticDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} #ifdef GNU -// expected-warning@+2{{'ImportClassTmplMembers::staticInlineDef' redeclared inline; 'dllimport' attribute ignored}} +// expected-warning@+2{{'ImportClassTmplMembers::staticInlineDef' redeclared inline; 'dllimport' attribute ignored}} #endif template inline void ImportClassTmplMembers::staticInlineDef() {} template void ImportClassTmplMembers::staticInlineDecl() {} @@ -1061,33 +1061,33 @@ constexpr static int ConstexprField = 1; // expected-note{{previous declaration is here}} }; -template __declspec(dllimport) void CTMR::normalDef() {} // expected-error{{redeclaration of 'CTMR::normalDef' cannot add 'dllimport' attribute}} +template __declspec(dllimport) void CTMR::normalDef() {} // expected-error{{redeclaration of 'CTMR::normalDef' cannot add 'dllimport' attribute}} // expected-error@-1{{dllimport cannot be applied to non-inline function definition}} -template __declspec(dllimport) void CTMR::normalInlineDecl() {} // expected-error{{redeclaration of 'CTMR::normalInlineDecl' cannot add 'dllimport' attribute}} -template __declspec(dllimport) void CTMR::virtualDef() {} // expected-error{{redeclaration of 'CTMR::virtualDef' cannot add 'dllimport' attribute}} +template __declspec(dllimport) void CTMR::normalInlineDecl() {} // expected-error{{redeclaration of 'CTMR::normalInlineDecl' cannot add 'dllimport' attribute}} +template __declspec(dllimport) void CTMR::virtualDef() {} // expected-error{{redeclaration of 'CTMR::virtualDef' cannot add 'dllimport' attribute}} // expected-error@-1{{dllimport cannot be applied to non-inline function definition}} -template __declspec(dllimport) void CTMR::virtualInlineDecl() {} // expected-error{{redeclaration of 'CTMR::virtualInlineDecl' cannot add 'dllimport' attribute}} -template __declspec(dllimport) void CTMR::staticDef() {} // expected-error{{redeclaration of 'CTMR::staticDef' cannot add 'dllimport' attribute}} +template __declspec(dllimport) void CTMR::virtualInlineDecl() {} // expected-error{{redeclaration of 'CTMR::virtualInlineDecl' cannot add 'dllimport' attribute}} +template __declspec(dllimport) void CTMR::staticDef() {} // expected-error{{redeclaration of 'CTMR::staticDef' cannot add 'dllimport' attribute}} // expected-error@-1{{dllimport cannot be applied to non-inline function definition}} -template __declspec(dllimport) void CTMR::staticInlineDecl() {} // expected-error{{redeclaration of 'CTMR::staticInlineDecl' cannot add 'dllimport' attribute}} +template __declspec(dllimport) void CTMR::staticInlineDecl() {} // expected-error{{redeclaration of 'CTMR::staticInlineDecl' cannot add 'dllimport' attribute}} #ifdef MS -template __declspec(dllimport) inline void CTMR::normalInlineDef() {} // expected-error{{redeclaration of 'CTMR::normalInlineDef' cannot add 'dllimport' attribute}} -template __declspec(dllimport) inline void CTMR::virtualInlineDef() {} // expected-error{{redeclaration of 'CTMR::virtualInlineDef' cannot add 'dllimport' attribute}} -template __declspec(dllimport) inline void CTMR::staticInlineDef() {} // expected-error{{redeclaration of 'CTMR::staticInlineDef' cannot add 'dllimport' attribute}} +template __declspec(dllimport) inline void CTMR::normalInlineDef() {} // expected-error{{redeclaration of 'CTMR::normalInlineDef' cannot add 'dllimport' attribute}} +template __declspec(dllimport) inline void CTMR::virtualInlineDef() {} // expected-error{{redeclaration of 'CTMR::virtualInlineDef' cannot add 'dllimport' attribute}} +template __declspec(dllimport) inline void CTMR::staticInlineDef() {} // expected-error{{redeclaration of 'CTMR::staticInlineDef' cannot add 'dllimport' attribute}} #else template __declspec(dllimport) inline void CTMR::normalInlineDef() {} // expected-warning{{'dllimport' attribute ignored on inline function}} template __declspec(dllimport) inline void CTMR::virtualInlineDef() {} // expected-warning{{'dllimport' attribute ignored on inline function}} template __declspec(dllimport) inline void CTMR::staticInlineDef() {} // expected-warning{{'dllimport' attribute ignored on inline function}} #endif -template __declspec(dllimport) int CTMR::StaticField = 1; // expected-error{{redeclaration of 'CTMR::StaticField' cannot add 'dllimport' attribute}} +template __declspec(dllimport) int CTMR::StaticField = 1; // expected-error{{redeclaration of 'CTMR::StaticField' cannot add 'dllimport' attribute}} // expected-warning@-1{{definition of dllimport static field}} // expected-note@-2{{attribute is here}} -template __declspec(dllimport) const int CTMR::StaticConstField = 1; // expected-error{{redeclaration of 'CTMR::StaticConstField' cannot add 'dllimport' attribute}} +template __declspec(dllimport) const int CTMR::StaticConstField = 1; // expected-error{{redeclaration of 'CTMR::StaticConstField' cannot add 'dllimport' attribute}} // expected-warning@-1{{definition of dllimport static field}} // expected-note@-2{{attribute is here}} -template __declspec(dllimport) constexpr int CTMR::ConstexprField; // expected-error{{redeclaration of 'CTMR::ConstexprField' cannot add 'dllimport' attribute}} +template __declspec(dllimport) constexpr int CTMR::ConstexprField; // expected-error{{redeclaration of 'CTMR::ConstexprField' cannot add 'dllimport' attribute}} // expected-warning@-1{{definition of dllimport static field}} // expected-note@-2{{attribute is here}} @@ -1129,14 +1129,14 @@ #endif // __has_feature(cxx_variable_templates) }; -template template void ImportClsTmplMemTmpl::normalDef() {} // expected-warning{{'ImportClsTmplMemTmpl::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +template template void ImportClsTmplMemTmpl::normalDef() {} // expected-warning{{'ImportClsTmplMemTmpl::normalDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} template template void ImportClsTmplMemTmpl::normalInlineDecl() {} -template template void ImportClsTmplMemTmpl::staticDef() {} // expected-warning{{'ImportClsTmplMemTmpl::staticDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +template template void ImportClsTmplMemTmpl::staticDef() {} // expected-warning{{'ImportClsTmplMemTmpl::staticDef' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} template template void ImportClsTmplMemTmpl::staticInlineDecl() {} #ifdef GNU -// expected-warning@+3{{'ImportClsTmplMemTmpl::normalInlineDef' redeclared inline; 'dllimport' attribute ignored}} -// expected-warning@+3{{'ImportClsTmplMemTmpl::staticInlineDef' redeclared inline; 'dllimport' attribute ignored}} +// expected-warning@+3{{'ImportClsTmplMemTmpl::normalInlineDef' redeclared inline; 'dllimport' attribute ignored}} +// expected-warning@+3{{'ImportClsTmplMemTmpl::staticInlineDef' redeclared inline; 'dllimport' attribute ignored}} #endif template template inline void ImportClsTmplMemTmpl::normalInlineDef() {} template template inline void ImportClsTmplMemTmpl::staticInlineDef() {} @@ -1170,29 +1170,29 @@ #endif // __has_feature(cxx_variable_templates) }; -template template __declspec(dllimport) void CTMTR::normalDef() {} // expected-error{{redeclaration of 'CTMTR::normalDef' cannot add 'dllimport' attribute}} +template template __declspec(dllimport) void CTMTR::normalDef() {} // expected-error{{redeclaration of 'CTMTR::normalDef' cannot add 'dllimport' attribute}} // expected-error@-1{{dllimport cannot be applied to non-inline function definition}} -template template __declspec(dllimport) void CTMTR::normalInlineDecl() {} // expected-error{{redeclaration of 'CTMTR::normalInlineDecl' cannot add 'dllimport' attribute}} -template template __declspec(dllimport) void CTMTR::staticDef() {} // expected-error{{redeclaration of 'CTMTR::staticDef' cannot add 'dllimport' attribute}} +template template __declspec(dllimport) void CTMTR::normalInlineDecl() {} // expected-error{{redeclaration of 'CTMTR::normalInlineDecl' cannot add 'dllimport' attribute}} +template template __declspec(dllimport) void CTMTR::staticDef() {} // expected-error{{redeclaration of 'CTMTR::staticDef' cannot add 'dllimport' attribute}} // expected-error@-1{{dllimport cannot be applied to non-inline function definition}} -template template __declspec(dllimport) void CTMTR::staticInlineDecl() {} // expected-error{{redeclaration of 'CTMTR::staticInlineDecl' cannot add 'dllimport' attribute}} +template template __declspec(dllimport) void CTMTR::staticInlineDecl() {} // expected-error{{redeclaration of 'CTMTR::staticInlineDecl' cannot add 'dllimport' attribute}} #ifdef MS -template template __declspec(dllimport) inline void CTMTR::normalInlineDef() {} // expected-error{{redeclaration of 'CTMTR::normalInlineDef' cannot add 'dllimport' attribute}} -template template __declspec(dllimport) inline void CTMTR::staticInlineDef() {} // expected-error{{redeclaration of 'CTMTR::staticInlineDef' cannot add 'dllimport' attribute}} +template template __declspec(dllimport) inline void CTMTR::normalInlineDef() {} // expected-error{{redeclaration of 'CTMTR::normalInlineDef' cannot add 'dllimport' attribute}} +template template __declspec(dllimport) inline void CTMTR::staticInlineDef() {} // expected-error{{redeclaration of 'CTMTR::staticInlineDef' cannot add 'dllimport' attribute}} #else template template __declspec(dllimport) inline void CTMTR::normalInlineDef() {} // expected-warning{{'dllimport' attribute ignored on inline function}} template template __declspec(dllimport) inline void CTMTR::staticInlineDef() {} // expected-warning{{'dllimport' attribute ignored on inline function}} #endif #if __has_feature(cxx_variable_templates) -template template __declspec(dllimport) int CTMTR::StaticField = 1; // expected-error{{redeclaration of 'CTMTR::StaticField' cannot add 'dllimport' attribute}} +template template __declspec(dllimport) int CTMTR::StaticField = 1; // expected-error{{redeclaration of 'CTMTR::StaticField' cannot add 'dllimport' attribute}} // expected-warning@-1{{definition of dllimport static field}} // expected-note@-2{{attribute is here}} -template template __declspec(dllimport) const int CTMTR::StaticConstField = 1; // expected-error{{redeclaration of 'CTMTR::StaticConstField' cannot add 'dllimport' attribute}} +template template __declspec(dllimport) const int CTMTR::StaticConstField = 1; // expected-error{{redeclaration of 'CTMTR::StaticConstField' cannot add 'dllimport' attribute}} // expected-warning@-1{{definition of dllimport static field}} // expected-note@-2{{attribute is here}} -template template __declspec(dllimport) constexpr int CTMTR::ConstexprField; // expected-error{{redeclaration of 'CTMTR::ConstexprField' cannot add 'dllimport' attribute}} +template template __declspec(dllimport) constexpr int CTMTR::ConstexprField; // expected-error{{redeclaration of 'CTMTR::ConstexprField' cannot add 'dllimport' attribute}} // expected-warning@-1{{definition of dllimport static field}} // expected-note@-2{{attribute is here}} #endif // __has_feature(cxx_variable_templates) Index: test/SemaCXX/undefined-internal.cpp =================================================================== --- test/SemaCXX/undefined-internal.cpp +++ test/SemaCXX/undefined-internal.cpp @@ -82,6 +82,7 @@ static int var; // expected-warning {{variable 'test5::B::var' has internal linkage but is not defined}} static void foo(); // expected-warning {{function 'test5::B::foo' has internal linkage but is not defined}} }; + extern template int B::var; void test() { B::var = 0; // expected-note {{used here}} Index: test/SemaTemplate/undefined-template.cpp =================================================================== --- /dev/null +++ test/SemaTemplate/undefined-template.cpp @@ -0,0 +1,139 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 -Wundefined-func-template %s + +template struct C1 { + static char s_var_1; + static char s_var_2; + static void s_func_1(); + static void s_func_2(); + void meth_1(); + void meth_2(); + template static char s_tvar_2; + template static void s_tfunc_2(); + template struct C2 { + static char s_var_2; + static void s_func_2(); + void meth_2(); + template static char s_tvar_2; + template void tmeth_2(); + }; +}; + +extern template char C1::s_var_2; +extern template void C1::s_func_2(); +extern template void C1::meth_2(); +extern template char C1::s_tvar_2; +extern template void C1::s_tfunc_2(); +extern template void C1::C2::s_var_2; +extern template void C1::C2::s_func_2(); +extern template void C1::C2::meth_2(); +extern template char C1::C2::s_tvar_2; +extern template void C1::C2::tmeth_2(); + +char func_01() { + return C1::s_var_2; +} + +char func_02() { + return C1::s_var_1; // expected-warning{{instantiation of variable 'C1::s_var_1' required here, but 'C1::s_var_1' is not defined}} + // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1::s_var_1' is explicitly instantiated in another translation unit}} +} + +char func_03() { + return C1::s_var_2; // expected-warning{{instantiation of variable 'C1::s_var_2' required here, but 'C1::s_var_2' is not defined}} + // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1::s_var_2' is explicitly instantiated in another translation unit}} +} + +void func_04() { + C1::s_func_1(); // expected-warning{{instantiation of function 'C1::s_func_1' required here, but 'C1::s_func_1' is not defined}} + // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1::s_func_1' is explicitly instantiated in another translation unit}} +} + +void func_05() { + C1::s_func_2(); +} + +void func_06() { + C1::s_func_2(); // expected-warning{{instantiation of function 'C1::s_func_2' required here, but 'C1::s_func_2' is not defined}} + // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1::s_func_2' is explicitly instantiated in another translation unit}} +} + +void func_07(C1 *x) { + x->meth_1(); // expected-warning{{instantiation of function 'C1::meth_1' required here, but 'C1::meth_1' is not defined}} + // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1::meth_1' is explicitly instantiated in another translation unit}} +} + +void func_08(C1 *x) { + x->meth_2(); +} + +void func_09(C1 *x) { + x->meth_1(); // expected-warning{{instantiation of function 'C1::meth_1' required here, but 'C1::meth_1' is not defined}} + // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1::meth_1' is explicitly instantiated in another translation unit}} +} + +char func_10() { + return C1::s_tvar_2; +} + +char func_11() { + return C1::s_tvar_2; // expected-warning{{instantiation of variable 'C1::s_tvar_2' required here, but 'C1::s_tvar_2' is not defined}} + // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1::s_tvar_2' is explicitly instantiated in another translation unit}} +} + +void func_12() { + C1::s_tfunc_2(); +} + +void func_13() { + C1::s_tfunc_2(); // expected-warning{{instantiation of function 'C1::s_tfunc_2' required here, but 'C1::s_tfunc_2' is not defined}} + // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1::s_tfunc_2' is explicitly instantiated in another translation unit}} +} + +char func_14() { + return C1::C2::s_var_2; +} + +char func_15() { + return C1::C2::s_var_2; //expected-warning {{instantiation of variable 'C1::C2::s_var_2' required here, but 'C1::C2::s_var_2' is not defined}} + // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1::C2::s_var_2' is explicitly instantiated in another translation unit}} +} + +void func_16() { + C1::C2::s_func_2(); +} + +void func_17() { + C1::C2::s_func_2(); // expected-warning{{instantiation of function 'C1::C2::s_func_2' required here, but 'C1::C2::s_func_2' is not defined}} + // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1::C2::s_func_2' is explicitly instantiated in another translation unit}} +} + +void func_18(C1::C2 *x) { + x->meth_2(); +} + +void func_19(C1::C2 *x) { + x->meth_2(); // expected-warning{{instantiation of function 'C1::C2::meth_2' required here, but 'C1::C2::meth_2' is not defined}} + // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1::C2::meth_2' is explicitly instantiated in another translation unit}} +} + +char func_20() { + return C1::C2::s_tvar_2; +} + +char func_21() { + return C1::C2::s_tvar_2; // expected-warning{{instantiation of variable 'C1::C2::s_tvar_2' required here, but 'C1::C2::s_tvar_2' is not defined}} + // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1::C2::s_tvar_2' is explicitly instantiated in another translation unit}} +} + +void func_22(C1::C2 *x) { + x->tmeth_2(); +} + +void func_23(C1::C2 *x) { + x->tmeth_2(); // expected-warning{{instantiation of function 'C1::C2::tmeth_2' required here, but 'C1::C2::tmeth_2' is not defined}} + // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1::C2::tmeth_2' is explicitly instantiated in another translation unit}} +} + +int main() { + return 0; +}