On Tue, Apr 19, 2016 at 7:28 AM, Nico Weber via cfe-commits < cfe-commits@lists.llvm.org> wrote:
> (sorry, accidentally sent this mid-mail) > > ../../v8/src/crankshaft/lithium.h:322:45: error: instantiation of variable > 'v8::internal::LSubKindOperand<v8::internal::LOperand::Kind::DOUBLE_STACK_SLOT, > 128>::cache' required here, but no definition is available > [-Werror,-Wundefined-var-template] > if (index < kNumCachedOperands) return &cache[index]; > ^ > ../../v8/src/crankshaft/x64/lithium-x64.cc:334:30: note: in instantiation > of member function > 'v8::internal::LSubKindOperand<v8::internal::LOperand::Kind::DOUBLE_STACK_SLOT, > 128>::Create' requested here > return LDoubleStackSlot::Create(index, zone()); > ^ > ../../v8/src/crankshaft/lithium.h:335:27: note: forward declaration of > template entity is here > static LSubKindOperand* cache; > ^ > ../../v8/src/crankshaft/lithium.h:322:45: note: add an explicit > instantiation declaration to suppress this warning if > 'v8::internal::LSubKindOperand<v8::internal::LOperand::Kind::DOUBLE_STACK_SLOT, > 128>::cache' is explicitly instantiated in another translation unit > if (index < kNumCachedOperands) return &cache[index]; > ^ > > I don't understand what this warning wants to tell me, or what it wants me > to do. What is this warning good for? Neither warning text nor commit > message explain that. > +1 I'm seeing a similar error in an internal codebase for a Singleton<T> class. Something like: template <typename T> struct Singleton { ... other stuff ... T *getInstance(); private: static T *instance; }; And `instance` is defined in a .cpp file somewhere. This seems to be deliberate. -- Sean Silva > > On Tue, Apr 19, 2016 at 10:27 AM, Nico Weber <tha...@chromium.org> wrote: > >> Hi Serge, >> >> this complains on this snippet from v8: >> >> template <LOperand::Kind kOperandKind, int kNumCachedOperands> >> class LSubKindOperand final : public LOperand { >> public: >> static LSubKindOperand* Create(int index, Zone* zone) { >> if (index < kNumCachedOperands) return &cache[index]; >> return new(zone) LSubKindOperand(index); >> } >> private: >> static LSubKindOperand* cache; >> explicit LSubKindOperand(int index); >> }; >> >> >> >> On Tue, Apr 19, 2016 at 2:19 AM, Serge Pavlov via cfe-commits < >> cfe-commits@lists.llvm.org> wrote: >> >>> Author: sepavloff >>> Date: Tue Apr 19 01:19:52 2016 >>> New Revision: 266719 >>> >>> URL: http://llvm.org/viewvc/llvm-project?rev=266719&view=rev >>> Log: >>> Warn if function or variable cannot be implicitly instantiated >>> >>> With this patch compiler emits warning if it tries to make implicit >>> instantiation >>> of a template but cannot find the template definition. The warning can >>> be suppressed >>> by explicit instantiation declaration or by command line options >>> -Wundefined-var-template and -Wundefined-func-template. The >>> implementation follows >>> the discussion of http://reviews.llvm.org/D12326. >>> >>> Differential Revision: http://reviews.llvm.org/D16396 >>> >>> Added: >>> cfe/trunk/test/SemaTemplate/undefined-template.cpp >>> Modified: >>> cfe/trunk/include/clang/AST/DeclBase.h >>> cfe/trunk/include/clang/Basic/DiagnosticGroups.td >>> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td >>> cfe/trunk/include/clang/Sema/Sema.h >>> cfe/trunk/lib/AST/DeclBase.cpp >>> cfe/trunk/lib/Sema/SemaOverload.cpp >>> cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp >>> cfe/trunk/test/CXX/temp/temp.decls/temp.mem/p1.cpp >>> cfe/trunk/test/OpenMP/parallel_ast_print.cpp >>> cfe/trunk/test/OpenMP/parallel_sections_ast_print.cpp >>> cfe/trunk/test/OpenMP/target_parallel_ast_print.cpp >>> cfe/trunk/test/OpenMP/task_ast_print.cpp >>> cfe/trunk/test/OpenMP/teams_ast_print.cpp >>> cfe/trunk/test/OpenMP/threadprivate_ast_print.cpp >>> cfe/trunk/test/SemaCXX/PR10177.cpp >>> cfe/trunk/test/SemaCXX/undefined-internal.cpp >>> >>> Modified: cfe/trunk/include/clang/AST/DeclBase.h >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=266719&r1=266718&r2=266719&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/include/clang/AST/DeclBase.h (original) >>> +++ cfe/trunk/include/clang/AST/DeclBase.h Tue Apr 19 01:19:52 2016 >>> @@ -52,6 +52,7 @@ struct PrintingPolicy; >>> class RecordDecl; >>> class Stmt; >>> class StoredDeclsMap; >>> +class TemplateDecl; >>> class TranslationUnitDecl; >>> class UsingDirectiveDecl; >>> } >>> @@ -905,6 +906,10 @@ public: >>> 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; >>> >>> Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=266719&r1=266718&r2=266719&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original) >>> +++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Tue Apr 19 >>> 01:19:52 2016 >>> @@ -75,6 +75,8 @@ def : DiagGroup<"ctor-dtor-privacy">; >>> 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">; >>> >>> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=266719&r1=266718&r2=266719&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) >>> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Apr 19 >>> 01:19:52 2016 >>> @@ -3883,7 +3883,18 @@ def note_template_type_alias_instantiati >>> "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 no definition is available">, >>> + InGroup<UndefinedVarTemplate>; >>> +def warn_func_template_missing : Warning<"instantiation of function %q0 >>> " >>> + "required here, but no definition is available">, >>> + InGroup<UndefinedFuncTemplate>, DefaultIgnore; >>> +def note_forward_template_decl : Note< >>> + "forward declaration of template entity is here">; >>> +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< >>> >>> Modified: cfe/trunk/include/clang/Sema/Sema.h >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=266719&r1=266718&r2=266719&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/include/clang/Sema/Sema.h (original) >>> +++ cfe/trunk/include/clang/Sema/Sema.h Tue Apr 19 01:19:52 2016 >>> @@ -7171,7 +7171,8 @@ public: >>> 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 @@ public: >>> 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, >>> >>> Modified: cfe/trunk/lib/AST/DeclBase.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=266719&r1=266718&r2=266719&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/lib/AST/DeclBase.cpp (original) >>> +++ cfe/trunk/lib/AST/DeclBase.cpp Tue Apr 19 01:19:52 2016 >>> @@ -196,6 +196,17 @@ bool Decl::isTemplateDecl() const { >>> return isa<TemplateDecl>(this); >>> } >>> >>> +TemplateDecl *Decl::getDescribedTemplate() const { >>> + if (auto *FD = dyn_cast<FunctionDecl>(this)) >>> + return FD->getDescribedFunctionTemplate(); >>> + else if (auto *RD = dyn_cast<CXXRecordDecl>(this)) >>> + return RD->getDescribedClassTemplate(); >>> + else if (auto *VD = dyn_cast<VarDecl>(this)) >>> + return VD->getDescribedVarTemplate(); >>> + >>> + return nullptr; >>> +} >>> + >>> const DeclContext *Decl::getParentFunctionOrMethod() const { >>> for (const DeclContext *DC = getDeclContext(); >>> DC && !DC->isTranslationUnit() && !DC->isNamespace(); >>> >>> Modified: cfe/trunk/lib/Sema/SemaOverload.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=266719&r1=266718&r2=266719&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/lib/Sema/SemaOverload.cpp (original) >>> +++ cfe/trunk/lib/Sema/SemaOverload.cpp Tue Apr 19 01:19:52 2016 >>> @@ -9324,11 +9324,8 @@ static void DiagnoseArityMismatch(Sema & >>> } >>> >>> static TemplateDecl *getDescribedTemplate(Decl *Templated) { >>> - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Templated)) >>> - return FD->getDescribedFunctionTemplate(); >>> - else if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Templated)) >>> - return RD->getDescribedClassTemplate(); >>> - >>> + if (TemplateDecl *TD = Templated->getDescribedTemplate()) >>> + return TD; >>> llvm_unreachable("Unsupported: Getting the described template >>> declaration" >>> " for bad deduction diagnosis"); >>> } >>> >>> Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=266719&r1=266718&r2=266719&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original) >>> +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Tue Apr 19 >>> 01:19:52 2016 >>> @@ -3530,7 +3530,8 @@ TemplateDeclInstantiator::InitMethodInst >>> void Sema::InstantiateFunctionDefinition(SourceLocation >>> PointOfInstantiation, >>> FunctionDecl *Function, >>> bool Recursive, >>> - bool DefinitionRequired) { >>> + bool DefinitionRequired, >>> + bool AtEndOfTU) { >>> if (Function->isInvalidDecl() || Function->isDefined()) >>> return; >>> >>> @@ -3604,6 +3605,16 @@ void Sema::InstantiateFunctionDefinition >>> 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; >>> + Diag(PatternDecl->getLocation(), >>> diag::note_forward_template_decl); >>> + if (getLangOpts().CPlusPlus11) >>> + Diag(PointOfInstantiation, diag::note_inst_declaration_hint) >>> + << Function; >>> + } >>> } >>> >>> return; >>> @@ -3951,7 +3962,7 @@ void Sema::InstantiateStaticDataMemberDe >>> >>> void Sema::InstantiateVariableDefinition(SourceLocation >>> PointOfInstantiation, >>> VarDecl *Var, bool Recursive, >>> - bool DefinitionRequired) { >>> + bool DefinitionRequired, bool >>> AtEndOfTU) { >>> if (Var->isInvalidDecl()) >>> return; >>> >>> @@ -4083,6 +4094,16 @@ void Sema::InstantiateVariableDefinition >>> == 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; >>> + Diag(PatternDecl->getLocation(), >>> diag::note_forward_template_decl); >>> + if (getLangOpts().CPlusPlus11) >>> + Diag(PointOfInstantiation, diag::note_inst_declaration_hint) >>> << Var; >>> + } >>> } >>> >>> return; >>> @@ -4852,7 +4873,7 @@ void Sema::PerformPendingInstantiations( >>> bool DefinitionRequired = >>> Function->getTemplateSpecializationKind() == >>> TSK_ExplicitInstantiationDefinition; >>> InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, >>> true, >>> - DefinitionRequired); >>> + DefinitionRequired, true); >>> continue; >>> } >>> >>> @@ -4893,7 +4914,7 @@ void Sema::PerformPendingInstantiations( >>> // Instantiate static data member definitions or variable template >>> // specializations. >>> InstantiateVariableDefinition(/*FIXME:*/ Inst.second, Var, true, >>> - DefinitionRequired); >>> + DefinitionRequired, true); >>> } >>> } >>> >>> >>> Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.mem/p1.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.mem/p1.cpp?rev=266719&r1=266718&r2=266719&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/test/CXX/temp/temp.decls/temp.mem/p1.cpp (original) >>> +++ cfe/trunk/test/CXX/temp/temp.decls/temp.mem/p1.cpp Tue Apr 19 >>> 01:19:52 2016 >>> @@ -10,6 +10,7 @@ template <class T> struct A { >>> } >>> }; >>> }; >>> +extern template bool A<bool>::cond; >>> >>> int foo() { >>> A<bool>::cond = true; >>> >>> Modified: cfe/trunk/test/OpenMP/parallel_ast_print.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_ast_print.cpp?rev=266719&r1=266718&r2=266719&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/test/OpenMP/parallel_ast_print.cpp (original) >>> +++ cfe/trunk/test/OpenMP/parallel_ast_print.cpp Tue Apr 19 01:19:52 2016 >>> @@ -227,4 +227,7 @@ void foo(const Foo<int> &arg) { >>> } >>> } >>> >>> +template<typename T> >>> +T S<T>::TS = 0; >>> + >>> #endif >>> >>> Modified: cfe/trunk/test/OpenMP/parallel_sections_ast_print.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_sections_ast_print.cpp?rev=266719&r1=266718&r2=266719&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/test/OpenMP/parallel_sections_ast_print.cpp (original) >>> +++ cfe/trunk/test/OpenMP/parallel_sections_ast_print.cpp Tue Apr 19 >>> 01:19:52 2016 >>> @@ -141,4 +141,7 @@ int main(int argc, char **argv) { >>> return tmain<int, 5>(b, &b) + tmain<long, 1>(x, &x); >>> } >>> >>> +template<typename T> >>> +T S<T>::TS = 0; >>> + >>> #endif >>> >>> Modified: cfe/trunk/test/OpenMP/target_parallel_ast_print.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/target_parallel_ast_print.cpp?rev=266719&r1=266718&r2=266719&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/test/OpenMP/target_parallel_ast_print.cpp (original) >>> +++ cfe/trunk/test/OpenMP/target_parallel_ast_print.cpp Tue Apr 19 >>> 01:19:52 2016 >>> @@ -227,4 +227,7 @@ int main (int argc, char **argv) { >>> return tmain<int, 5>(argc, &argc) + tmain<char, 1>(argv[0][0], >>> argv[0]); >>> } >>> >>> +extern template int S<int>::TS; >>> +extern template char S<char>::TS; >>> + >>> #endif >>> >>> Modified: cfe/trunk/test/OpenMP/task_ast_print.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/task_ast_print.cpp?rev=266719&r1=266718&r2=266719&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/test/OpenMP/task_ast_print.cpp (original) >>> +++ cfe/trunk/test/OpenMP/task_ast_print.cpp Tue Apr 19 01:19:52 2016 >>> @@ -149,4 +149,7 @@ int main(int argc, char **argv) { >>> return tmain<int, 5>(b, &b) + tmain<long, 1>(x, &x); >>> } >>> >>> +extern template int S<int>::TS; >>> +extern template long S<long>::TS; >>> + >>> #endif >>> >>> Modified: cfe/trunk/test/OpenMP/teams_ast_print.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/teams_ast_print.cpp?rev=266719&r1=266718&r2=266719&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/test/OpenMP/teams_ast_print.cpp (original) >>> +++ cfe/trunk/test/OpenMP/teams_ast_print.cpp Tue Apr 19 01:19:52 2016 >>> @@ -109,4 +109,6 @@ int main (int argc, char **argv) { >>> return tmain<int, 5>(b, &b) + tmain<long, 1>(x, &x); >>> } >>> >>> +extern template int S<int>::TS; >>> +extern template long S<long>::TS; >>> #endif >>> >>> Modified: cfe/trunk/test/OpenMP/threadprivate_ast_print.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/threadprivate_ast_print.cpp?rev=266719&r1=266718&r2=266719&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/test/OpenMP/threadprivate_ast_print.cpp (original) >>> +++ cfe/trunk/test/OpenMP/threadprivate_ast_print.cpp Tue Apr 19 >>> 01:19:52 2016 >>> @@ -69,4 +69,5 @@ int main () { >>> return (foo<int>()); >>> } >>> >>> +extern template int ST<int>::m; >>> #endif >>> >>> Modified: cfe/trunk/test/SemaCXX/PR10177.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/PR10177.cpp?rev=266719&r1=266718&r2=266719&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/test/SemaCXX/PR10177.cpp (original) >>> +++ cfe/trunk/test/SemaCXX/PR10177.cpp Tue Apr 19 01:19:52 2016 >>> @@ -54,6 +54,7 @@ namespace N { >>> >>> namespace { template<typename> extern int n; } >>> template<typename T> int g() { return n<int>; } >>> +namespace { extern template int n<int>; } >>> >>> #endif >>> >>> >>> Modified: cfe/trunk/test/SemaCXX/undefined-internal.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/undefined-internal.cpp?rev=266719&r1=266718&r2=266719&view=diff >>> >>> ============================================================================== >>> --- cfe/trunk/test/SemaCXX/undefined-internal.cpp (original) >>> +++ cfe/trunk/test/SemaCXX/undefined-internal.cpp Tue Apr 19 01:19:52 >>> 2016 >>> @@ -82,6 +82,7 @@ namespace test5 { >>> static int var; // expected-warning {{variable >>> 'test5::B<test5::(anonymous namespace)::A>::var' has internal linkage but >>> is not defined}} >>> static void foo(); // expected-warning {{function >>> 'test5::B<test5::(anonymous namespace)::A>::foo' has internal linkage but >>> is not defined}} >>> }; >>> + extern template int B<A>::var; >>> >>> void test() { >>> B<A>::var = 0; // expected-note {{used here}} >>> >>> Added: cfe/trunk/test/SemaTemplate/undefined-template.cpp >>> URL: >>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/undefined-template.cpp?rev=266719&view=auto >>> >>> ============================================================================== >>> --- cfe/trunk/test/SemaTemplate/undefined-template.cpp (added) >>> +++ cfe/trunk/test/SemaTemplate/undefined-template.cpp Tue Apr 19 >>> 01:19:52 2016 >>> @@ -0,0 +1,139 @@ >>> +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 >>> -Wundefined-func-template %s >>> + >>> +template <class T> struct C1 { >>> + static char s_var_1; // expected-note{{forward declaration of >>> template entity is here}} >>> + static char s_var_2; // expected-note{{forward declaration of >>> template entity is here}} >>> + static void s_func_1(); // expected-note{{forward declaration of >>> template entity is here}} >>> + static void s_func_2(); // expected-note{{forward declaration of >>> template entity is here}} >>> + void meth_1(); // expected-note2{{forward declaration of >>> template entity is here}} >>> + void meth_2(); >>> + template <class T1> static char s_tvar_2; // >>> expected-note{{forward declaration of template entity is here}} >>> + template <class T1> static void s_tfunc_2(); // >>> expected-note{{forward declaration of template entity is here}} >>> + template<typename T1> struct C2 { >>> + static char s_var_2; // expected-note{{forward declaration of >>> template entity is here}} >>> + static void s_func_2(); // expected-note{{forward declaration of >>> template entity is here}} >>> + void meth_2(); // expected-note{{forward declaration of >>> template entity is here}} >>> + template <class T2> static char s_tvar_2; // >>> expected-note{{forward declaration of template entity is here}} >>> + template <class T2> void tmeth_2(); // >>> expected-note{{forward declaration of template entity is here}} >>> + }; >>> +}; >>> + >>> +extern template char C1<int>::s_var_2; >>> +extern template void C1<int>::s_func_2(); >>> +extern template void C1<int>::meth_2(); >>> +extern template char C1<int>::s_tvar_2<char>; >>> +extern template void C1<int>::s_tfunc_2<char>(); >>> +extern template void C1<int>::C2<long>::s_var_2; >>> +extern template void C1<int>::C2<long>::s_func_2(); >>> +extern template void C1<int>::C2<long>::meth_2(); >>> +extern template char C1<int>::C2<long>::s_tvar_2<char>; >>> +extern template void C1<int>::C2<long>::tmeth_2<char>(); >>> + >>> +char func_01() { >>> + return C1<int>::s_var_2; >>> +} >>> + >>> +char func_02() { >>> + return C1<int>::s_var_1; // expected-warning{{instantiation of >>> variable 'C1<int>::s_var_1' required here, but no definition is available}} >>> + // expected-note@-1{{add an explicit >>> instantiation declaration to suppress this warning if 'C1<int>::s_var_1' is >>> explicitly instantiated in another translation unit}} >>> +} >>> + >>> +char func_03() { >>> + return C1<char>::s_var_2; // expected-warning{{instantiation of >>> variable 'C1<char>::s_var_2' required here, but no definition is available}} >>> + // expected-note@-1{{add an explicit >>> instantiation declaration to suppress this warning if 'C1<char>::s_var_2' >>> is explicitly instantiated in another translation unit}} >>> +} >>> + >>> +void func_04() { >>> + C1<int>::s_func_1(); // expected-warning{{instantiation of function >>> 'C1<int>::s_func_1' required here, but no definition is available}} >>> + // expected-note@-1{{add an explicit >>> instantiation declaration to suppress this warning if 'C1<int>::s_func_1' >>> is explicitly instantiated in another translation unit}} >>> +} >>> + >>> +void func_05() { >>> + C1<int>::s_func_2(); >>> +} >>> + >>> +void func_06() { >>> + C1<char>::s_func_2(); // expected-warning{{instantiation of function >>> 'C1<char>::s_func_2' required here, but no definition is available}} >>> + // expected-note@-1{{add an explicit >>> instantiation declaration to suppress this warning if 'C1<char>::s_func_2' >>> is explicitly instantiated in another translation unit}} >>> +} >>> + >>> +void func_07(C1<int> *x) { >>> + x->meth_1(); // expected-warning{{instantiation of function >>> 'C1<int>::meth_1' required here, but no definition is available}} >>> + // expected-note@-1{{add an explicit instantiation >>> declaration to suppress this warning if 'C1<int>::meth_1' is explicitly >>> instantiated in another translation unit}} >>> +} >>> + >>> +void func_08(C1<int> *x) { >>> + x->meth_2(); >>> +} >>> + >>> +void func_09(C1<char> *x) { >>> + x->meth_1(); // expected-warning{{instantiation of function >>> 'C1<char>::meth_1' required here, but no definition is available}} >>> + // expected-note@-1{{add an explicit instantiation >>> declaration to suppress this warning if 'C1<char>::meth_1' is explicitly >>> instantiated in another translation unit}} >>> +} >>> + >>> +char func_10() { >>> + return C1<int>::s_tvar_2<char>; >>> +} >>> + >>> +char func_11() { >>> + return C1<int>::s_tvar_2<long>; // expected-warning{{instantiation of >>> variable 'C1<int>::s_tvar_2<long>' required here, but no definition is >>> available}} >>> + // expected-note@-1{{add an explicit >>> instantiation declaration to suppress this warning if >>> 'C1<int>::s_tvar_2<long>' is explicitly instantiated in another translation >>> unit}} >>> +} >>> + >>> +void func_12() { >>> + C1<int>::s_tfunc_2<char>(); >>> +} >>> + >>> +void func_13() { >>> + C1<int>::s_tfunc_2<long>(); // expected-warning{{instantiation of >>> function 'C1<int>::s_tfunc_2<long>' required here, but no definition is >>> available}} >>> + // expected-note@-1{{add an explicit >>> instantiation declaration to suppress this warning if >>> 'C1<int>::s_tfunc_2<long>' is explicitly instantiated in another >>> translation unit}} >>> +} >>> + >>> +char func_14() { >>> + return C1<int>::C2<long>::s_var_2; >>> +} >>> + >>> +char func_15() { >>> + return C1<int>::C2<char>::s_var_2; //expected-warning >>> {{instantiation of variable 'C1<int>::C2<char>::s_var_2' required here, but >>> no definition is available}} >>> + // expected-note@-1{{add an >>> explicit instantiation declaration to suppress this warning if >>> 'C1<int>::C2<char>::s_var_2' is explicitly instantiated in another >>> translation unit}} >>> +} >>> + >>> +void func_16() { >>> + C1<int>::C2<long>::s_func_2(); >>> +} >>> + >>> +void func_17() { >>> + C1<int>::C2<char>::s_func_2(); // expected-warning{{instantiation of >>> function 'C1<int>::C2<char>::s_func_2' required here, but no definition is >>> available}} >>> + // expected-note@-1{{add an explicit >>> instantiation declaration to suppress this warning if >>> 'C1<int>::C2<char>::s_func_2' is explicitly instantiated in another >>> translation unit}} >>> +} >>> + >>> +void func_18(C1<int>::C2<long> *x) { >>> + x->meth_2(); >>> +} >>> + >>> +void func_19(C1<int>::C2<char> *x) { >>> + x->meth_2(); // expected-warning{{instantiation of function >>> 'C1<int>::C2<char>::meth_2' required here, but no definition is available}} >>> + // expected-note@-1{{add an explicit >>> instantiation declaration to suppress this warning if >>> 'C1<int>::C2<char>::meth_2' is explicitly instantiated in another >>> translation unit}} >>> +} >>> + >>> +char func_20() { >>> + return C1<int>::C2<long>::s_tvar_2<char>; >>> +} >>> + >>> +char func_21() { >>> + return C1<int>::C2<long>::s_tvar_2<long>; // >>> expected-warning{{instantiation of variable >>> 'C1<int>::C2<long>::s_tvar_2<long>' required here, but no definition is >>> available}} >>> + // expected-note@-1{{add an explicit >>> instantiation declaration to suppress this warning if >>> 'C1<int>::C2<long>::s_tvar_2<long>' is explicitly instantiated in another >>> translation unit}} >>> +} >>> + >>> +void func_22(C1<int>::C2<long> *x) { >>> + x->tmeth_2<char>(); >>> +} >>> + >>> +void func_23(C1<int>::C2<long> *x) { >>> + x->tmeth_2<int>(); // expected-warning{{instantiation of function >>> 'C1<int>::C2<long>::tmeth_2<int>' required here, but no definition is >>> available}} >>> + // expected-note@-1{{add an explicit >>> instantiation declaration to suppress this warning if >>> 'C1<int>::C2<long>::tmeth_2<int>' is explicitly instantiated in another >>> translation unit}} >>> +} >>> + >>> +int main() { >>> + return 0; >>> +} >>> >>> >>> _______________________________________________ >>> cfe-commits mailing list >>> cfe-commits@lists.llvm.org >>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >>> >> >> > > _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits > >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits