r266719 - Warn if function or variable cannot be implicitly instantiated

Serge Pavlov via cfe-commits cfe-commits at lists.llvm.org
Tue Apr 19 08:05:44 PDT 2016


Hi Nico,

This message indicates that compiler sees a reference to static member
'cache' of some specialization of template 'LSubKindOperand' (namely
'LSubKindOperand<v8::internal::LOperand::Kind::DOUBLE_STACK_SLOT, 128>').
This is a static member, so compiler needs corresponding template
definition to instantiate it, but there is no such in the file being
compiled. So compiler cannot implicitly generate 'LSubKindOperand<...>::cache'.
It is not an error if the definition is defined somewhere in the project,
in other translation units. In the case of v8 it is defined
in src\crankshaft\lithium.cc.

The warning can help in detection of some cases, difficult to diagnose for
user, the problem described in PR24425 is one of such. If the project v8
didn't have definition in lithium.cc linker error would be seen.

I would recommend moving definition of static member template:

template<LOperand::Kind kOperandKind, int kNumCachedOperands>
LSubKindOperand<kOperandKind, kNumCachedOperands>*
LSubKindOperand<kOperandKind, kNumCachedOperands>::cache = NULL;

from lithium.cc to lithium.h.

Thanks,
--Serge

2016-04-19 20:28 GMT+06:00 Nico Weber <thakis at chromium.org>:

> (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.
>
> On Tue, Apr 19, 2016 at 10:27 AM, Nico Weber <thakis at 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 at 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 at -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 at -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 at -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 at -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 at -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 at -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 at -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 at -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 at -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 at -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 at -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 at -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 at -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 at lists.llvm.org
>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>>>
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20160419/5039d4a7/attachment-0001.html>


More information about the cfe-commits mailing list