r266719 - Warn if function or variable cannot be implicitly instantiated

Sean Silva via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 20 16:26:32 PDT 2016


On Tue, Apr 19, 2016 at 7:28 AM, Nico Weber via cfe-commits <
cfe-commits at 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 <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
>>>
>>
>>
>
> _______________________________________________
> 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/20160420/04cc9d7b/attachment-0001.html>


More information about the cfe-commits mailing list