[clang] [clang][diagnostics] suggest extern template syntax for -Wundefined-var-template (PR #187896)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Mar 21 19:14:23 PDT 2026
https://github.com/diohabara updated https://github.com/llvm/llvm-project/pull/187896
>From 3349dabfc52cd6f440c3bc64ed5e453476d4dd47 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=8D=8Ddiohabara=E5=8D=8D?=
<37092773+diohabara at users.noreply.github.com>
Date: Sat, 21 Mar 2026 18:52:57 +0900
Subject: [PATCH 1/2] [clang][diagnostics] suggest extern template syntax for
-Wundefined-var-template and -Wundefined-func-template
---
.../clang/Basic/DiagnosticSemaKinds.td | 2 +
.../lib/Sema/SemaTemplateInstantiateDecl.cpp | 68 ++++++++++++++++++-
...antiation.diagnose_on_undefined_entity.cpp | 4 ++
clang/test/SemaCXX/cxx1z-ast-print.cpp | 4 +-
.../instantiate-pure-virtual-function.cpp | 6 +-
.../test/SemaTemplate/undefined-template.cpp | 13 ++++
6 files changed, 93 insertions(+), 4 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index d4d09a8ecef36..d8647f6d426c9 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5954,6 +5954,8 @@ def note_unreachable_template_decl
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_inst_declaration_example : Note<
+ "e.g., '%0'">;
def note_evaluating_exception_spec_here : Note<
"in evaluation of exception specification for %q0 needed here">;
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index cc24e03e77c07..f221b180e2bdd 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -5636,9 +5636,58 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
diag::note_unreachable_template_decl);
} else {
Diag(PatternDecl->getLocation(), diag::note_forward_template_decl);
- if (getLangOpts().CPlusPlus11)
+ if (getLangOpts().CPlusPlus11) {
Diag(PointOfInstantiation, diag::note_inst_declaration_hint)
<< Function;
+ // Suggest the exact extern template declaration syntax.
+ // Note: for functions with complex declarator return types
+ // (e.g., function pointers), the suggestion may not be
+ // perfectly formatted, but these cases are rare in practice.
+ std::string Suggestion;
+ {
+ llvm::raw_string_ostream OS(Suggestion);
+ OS << "extern template ";
+ // Constructors, destructors, and conversion operators have no
+ // separate return type in the declaration syntax.
+ if (!isa<CXXConstructorDecl>(Function) &&
+ !isa<CXXDestructorDecl>(Function) &&
+ !isa<CXXConversionDecl>(Function)) {
+ Function->getReturnType().print(OS, getPrintingPolicy());
+ OS << " ";
+ }
+ Function->getNameForDiagnostic(OS, getPrintingPolicy(),
+ /*Qualified=*/true);
+ OS << "(";
+ for (unsigned I = 0, N = Function->getNumParams(); I != N; ++I) {
+ if (I > 0)
+ OS << ", ";
+ Function->getParamDecl(I)->getType().print(
+ OS, getPrintingPolicy());
+ }
+ if (Function->isVariadic()) {
+ if (Function->getNumParams() > 0)
+ OS << ", ";
+ OS << "...";
+ }
+ OS << ")";
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(Function)) {
+ if (MD->getMethodQualifiers().hasConst())
+ OS << " const";
+ if (MD->getMethodQualifiers().hasVolatile())
+ OS << " volatile";
+ if (MD->getRefQualifier() == RQ_LValue)
+ OS << " &";
+ else if (MD->getRefQualifier() == RQ_RValue)
+ OS << " &&";
+ }
+ if (auto EST = Function->getExceptionSpecType();
+ EST == EST_BasicNoexcept)
+ OS << " noexcept";
+ OS << ";";
+ }
+ Diag(PointOfInstantiation, diag::note_inst_declaration_example)
+ << Suggestion;
+ }
}
}
}
@@ -6379,8 +6428,23 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
Diag(PointOfInstantiation, diag::warn_var_template_missing)
<< Var;
Diag(PatternDecl->getLocation(), diag::note_forward_template_decl);
- if (getLangOpts().CPlusPlus11)
+ if (getLangOpts().CPlusPlus11) {
Diag(PointOfInstantiation, diag::note_inst_declaration_hint) << Var;
+ // Suggest the exact extern template declaration syntax.
+ std::string Suggestion;
+ {
+ llvm::raw_string_ostream OS(Suggestion);
+ OS << "extern template ";
+ std::string QualName;
+ llvm::raw_string_ostream NameOS(QualName);
+ Var->getNameForDiagnostic(NameOS, getPrintingPolicy(),
+ /*Qualified=*/true);
+ Var->getType().print(OS, getPrintingPolicy(), QualName);
+ OS << ";";
+ }
+ Diag(PointOfInstantiation, diag::note_inst_declaration_example)
+ << Suggestion;
+ }
}
return;
}
diff --git a/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.diagnose_on_undefined_entity.cpp b/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.diagnose_on_undefined_entity.cpp
index 24e24221939fa..b79e5983fe6be 100644
--- a/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.diagnose_on_undefined_entity.cpp
+++ b/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.diagnose_on_undefined_entity.cpp
@@ -24,13 +24,17 @@ void use() {
foo.non_static_member_function(); // expected-warning{{instantiation of function 'Foo<int>::non_static_member_function' required here, but no definition is available}}
// expected-note at -1 {{add an explicit instantiation}}
+ // expected-note at -2 {{e.g., 'extern template}}
Foo<int>::static_member_function(); // expected-warning{{instantiation of function 'Foo<int>::static_member_function' required here, but no definition is available}}
// expected-note at -1 {{add an explicit instantiation}}
+ // expected-note at -2 {{e.g., 'extern template}}
(void)Foo<int>::static_data_member; // expected-warning{{instantiation of variable 'Foo<int>::static_data_member' required here, but no definition is available}}
// expected-note at -1 {{add an explicit instantiation}}
+ // expected-note at -2 {{e.g., 'extern template}}
Foo<int>::nested::static_member_function(); // expected-warning{{instantiation of function 'Foo<int>::nested::static_member_function' required here, but no definition is available}}
// expected-note at -1 {{add an explicit instantiation}}
+ // expected-note at -2 {{e.g., 'extern template}}
}
diff --git a/clang/test/SemaCXX/cxx1z-ast-print.cpp b/clang/test/SemaCXX/cxx1z-ast-print.cpp
index a6ba149e974ef..642b7ceff935e 100644
--- a/clang/test/SemaCXX/cxx1z-ast-print.cpp
+++ b/clang/test/SemaCXX/cxx1z-ast-print.cpp
@@ -7,5 +7,7 @@ struct TypeSuffix {
// CHECK: int k = TypeSuffix().x<0L> + TypeSuffix().y<0L>;
int k = TypeSuffix().x<0L> + TypeSuffix().y<0L>; // expected-warning {{instantiation of variable 'TypeSuffix::x<0>' required here, but no definition is available}} \
// expected-note {{add an explicit instantiation declaration to suppress this warning if 'TypeSuffix::x<0>' is explicitly instantiated in another translation unit}} \
+ // expected-note {{e.g., 'extern template}} \
// expected-warning {{instantiation of variable 'TypeSuffix::y<0L>' required here, but no definition is available}} \
- // expected-note {{add an explicit instantiation declaration to suppress this warning if 'TypeSuffix::y<0L>' is explicitly instantiated in another translation unit}}
+ // expected-note {{add an explicit instantiation declaration to suppress this warning if 'TypeSuffix::y<0L>' is explicitly instantiated in another translation unit}} \
+ // expected-note {{e.g., 'extern template}}
diff --git a/clang/test/SemaTemplate/instantiate-pure-virtual-function.cpp b/clang/test/SemaTemplate/instantiate-pure-virtual-function.cpp
index caec42b6b77f9..548f7662b0af5 100644
--- a/clang/test/SemaTemplate/instantiate-pure-virtual-function.cpp
+++ b/clang/test/SemaTemplate/instantiate-pure-virtual-function.cpp
@@ -23,6 +23,7 @@ namespace call_pure_virtual_function_from_virtual {
public:
const void foo(const T &) { B::bar(1); } // expected-warning {{instantiation of function 'call_pure_virtual_function_from_virtual::B<int>::bar' required here, but no definition is available}}
// expected-note at -1 {{add an explicit instantiation declaration to suppress this warning if 'call_pure_virtual_function_from_virtual::B<int>::bar' is explicitly instantiated in another translation unit}}
+ // expected-note at -2 {{e.g., 'extern template}}
virtual const void bar(unsigned int) = 0; // expected-note {{forward declaration of template entity is here}}
};
@@ -54,7 +55,10 @@ namespace non_pure_virtual_function {
// expected-note at -3 {{add an explicit instantiation declaration to suppress this warning if 'non_pure_virtual_function::B<int>::bar' is explicitly instantiated in another translation unit}}
// expected-note at -4 {{add an explicit instantiation declaration to suppress this warning if 'non_pure_virtual_function::B<int>::bar' is explicitly instantiated in another translation unit}}
// expected-note at -5 {{add an explicit instantiation declaration to suppress this warning if 'non_pure_virtual_function::B<int>::bar' is explicitly instantiated in another translation unit}}
-// expected-note at -6 {{used here}}
+// expected-note at -6 {{e.g., 'extern template}}
+// expected-note at -7 {{e.g., 'extern template}}
+// expected-note at -8 {{e.g., 'extern template}}
+// expected-note at -9 {{used here}}
public:
constexpr void bar(unsigned int) override { }
diff --git a/clang/test/SemaTemplate/undefined-template.cpp b/clang/test/SemaTemplate/undefined-template.cpp
index 52530e2e3909a..c26ab6c8ff03a 100644
--- a/clang/test/SemaTemplate/undefined-template.cpp
+++ b/clang/test/SemaTemplate/undefined-template.cpp
@@ -37,16 +37,19 @@ char func_01() {
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}}
+ // expected-note at -2{{e.g., 'extern template char C1<int>::s_var_1;'}}
}
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}}
+ // expected-note at -2{{e.g., 'extern template char C1<char>::s_var_2;'}}
}
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}}
+ // expected-note at -2{{e.g., 'extern template void C1<int>::s_func_1();'}}
}
void func_05() {
@@ -56,11 +59,13 @@ void func_05() {
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}}
+ // expected-note at -2{{e.g., 'extern template void C1<char>::s_func_2();'}}
}
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}}
+ // expected-note at -2{{e.g., 'extern template void C1<int>::meth_1();'}}
}
void func_08(C1<int> *x) {
@@ -70,6 +75,7 @@ void func_08(C1<int> *x) {
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}}
+ // expected-note at -2{{e.g., 'extern template void C1<char>::meth_1();'}}
}
char func_10() {
@@ -79,6 +85,7 @@ char func_10() {
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}}
+ // expected-note at -2{{e.g., 'extern template char C1<int>::s_tvar_2<long>;'}}
}
void func_12() {
@@ -88,6 +95,7 @@ void func_12() {
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}}
+ // expected-note at -2{{e.g., 'extern template void C1<int>::s_tfunc_2<long>();'}}
}
char func_14() {
@@ -97,6 +105,7 @@ char func_14() {
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}}
+ // expected-note at -2{{e.g., 'extern template char C1<int>::C2<char>::s_var_2;'}}
}
void func_16() {
@@ -106,6 +115,7 @@ void func_16() {
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}}
+ // expected-note at -2{{e.g., 'extern template void C1<int>::C2<char>::s_func_2();'}}
}
void func_18(C1<int>::C2<long> *x) {
@@ -115,6 +125,7 @@ void func_18(C1<int>::C2<long> *x) {
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}}
+ // expected-note at -2{{e.g., 'extern template void C1<int>::C2<char>::meth_2();'}}
}
char func_20() {
@@ -124,6 +135,7 @@ char func_20() {
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}}
+ // expected-note at -2{{e.g., 'extern template char C1<int>::C2<long>::s_tvar_2<long>;'}}
}
void func_22(C1<int>::C2<long> *x) {
@@ -133,6 +145,7 @@ void func_22(C1<int>::C2<long> *x) {
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}}
+ // expected-note at -2{{e.g., 'extern template void C1<int>::C2<long>::tmeth_2<int>();'}}
}
namespace test_24 {
>From 7465dfc4dbbdb05cf463d7f26a65825bb4941718 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=8D=8Ddiohabara=E5=8D=8D?=
<37092773+diohabara at users.noreply.github.com>
Date: Sun, 22 Mar 2026 11:13:34 +0900
Subject: [PATCH 2/2] chore: remove func warning suggestion
---
.../lib/Sema/SemaTemplateInstantiateDecl.cpp | 51 +------------------
...antiation.diagnose_on_undefined_entity.cpp | 3 --
.../instantiate-pure-virtual-function.cpp | 6 +--
.../test/SemaTemplate/undefined-template.cpp | 8 ---
4 files changed, 2 insertions(+), 66 deletions(-)
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index f221b180e2bdd..5590433d05818 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -5636,58 +5636,9 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
diag::note_unreachable_template_decl);
} else {
Diag(PatternDecl->getLocation(), diag::note_forward_template_decl);
- if (getLangOpts().CPlusPlus11) {
+ if (getLangOpts().CPlusPlus11)
Diag(PointOfInstantiation, diag::note_inst_declaration_hint)
<< Function;
- // Suggest the exact extern template declaration syntax.
- // Note: for functions with complex declarator return types
- // (e.g., function pointers), the suggestion may not be
- // perfectly formatted, but these cases are rare in practice.
- std::string Suggestion;
- {
- llvm::raw_string_ostream OS(Suggestion);
- OS << "extern template ";
- // Constructors, destructors, and conversion operators have no
- // separate return type in the declaration syntax.
- if (!isa<CXXConstructorDecl>(Function) &&
- !isa<CXXDestructorDecl>(Function) &&
- !isa<CXXConversionDecl>(Function)) {
- Function->getReturnType().print(OS, getPrintingPolicy());
- OS << " ";
- }
- Function->getNameForDiagnostic(OS, getPrintingPolicy(),
- /*Qualified=*/true);
- OS << "(";
- for (unsigned I = 0, N = Function->getNumParams(); I != N; ++I) {
- if (I > 0)
- OS << ", ";
- Function->getParamDecl(I)->getType().print(
- OS, getPrintingPolicy());
- }
- if (Function->isVariadic()) {
- if (Function->getNumParams() > 0)
- OS << ", ";
- OS << "...";
- }
- OS << ")";
- if (const auto *MD = dyn_cast<CXXMethodDecl>(Function)) {
- if (MD->getMethodQualifiers().hasConst())
- OS << " const";
- if (MD->getMethodQualifiers().hasVolatile())
- OS << " volatile";
- if (MD->getRefQualifier() == RQ_LValue)
- OS << " &";
- else if (MD->getRefQualifier() == RQ_RValue)
- OS << " &&";
- }
- if (auto EST = Function->getExceptionSpecType();
- EST == EST_BasicNoexcept)
- OS << " noexcept";
- OS << ";";
- }
- Diag(PointOfInstantiation, diag::note_inst_declaration_example)
- << Suggestion;
- }
}
}
}
diff --git a/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.diagnose_on_undefined_entity.cpp b/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.diagnose_on_undefined_entity.cpp
index b79e5983fe6be..24f6852171f44 100644
--- a/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.diagnose_on_undefined_entity.cpp
+++ b/clang/test/SemaCXX/attr-exclude_from_explicit_instantiation.diagnose_on_undefined_entity.cpp
@@ -24,11 +24,9 @@ void use() {
foo.non_static_member_function(); // expected-warning{{instantiation of function 'Foo<int>::non_static_member_function' required here, but no definition is available}}
// expected-note at -1 {{add an explicit instantiation}}
- // expected-note at -2 {{e.g., 'extern template}}
Foo<int>::static_member_function(); // expected-warning{{instantiation of function 'Foo<int>::static_member_function' required here, but no definition is available}}
// expected-note at -1 {{add an explicit instantiation}}
- // expected-note at -2 {{e.g., 'extern template}}
(void)Foo<int>::static_data_member; // expected-warning{{instantiation of variable 'Foo<int>::static_data_member' required here, but no definition is available}}
// expected-note at -1 {{add an explicit instantiation}}
@@ -36,5 +34,4 @@ void use() {
Foo<int>::nested::static_member_function(); // expected-warning{{instantiation of function 'Foo<int>::nested::static_member_function' required here, but no definition is available}}
// expected-note at -1 {{add an explicit instantiation}}
- // expected-note at -2 {{e.g., 'extern template}}
}
diff --git a/clang/test/SemaTemplate/instantiate-pure-virtual-function.cpp b/clang/test/SemaTemplate/instantiate-pure-virtual-function.cpp
index 548f7662b0af5..caec42b6b77f9 100644
--- a/clang/test/SemaTemplate/instantiate-pure-virtual-function.cpp
+++ b/clang/test/SemaTemplate/instantiate-pure-virtual-function.cpp
@@ -23,7 +23,6 @@ namespace call_pure_virtual_function_from_virtual {
public:
const void foo(const T &) { B::bar(1); } // expected-warning {{instantiation of function 'call_pure_virtual_function_from_virtual::B<int>::bar' required here, but no definition is available}}
// expected-note at -1 {{add an explicit instantiation declaration to suppress this warning if 'call_pure_virtual_function_from_virtual::B<int>::bar' is explicitly instantiated in another translation unit}}
- // expected-note at -2 {{e.g., 'extern template}}
virtual const void bar(unsigned int) = 0; // expected-note {{forward declaration of template entity is here}}
};
@@ -55,10 +54,7 @@ namespace non_pure_virtual_function {
// expected-note at -3 {{add an explicit instantiation declaration to suppress this warning if 'non_pure_virtual_function::B<int>::bar' is explicitly instantiated in another translation unit}}
// expected-note at -4 {{add an explicit instantiation declaration to suppress this warning if 'non_pure_virtual_function::B<int>::bar' is explicitly instantiated in another translation unit}}
// expected-note at -5 {{add an explicit instantiation declaration to suppress this warning if 'non_pure_virtual_function::B<int>::bar' is explicitly instantiated in another translation unit}}
-// expected-note at -6 {{e.g., 'extern template}}
-// expected-note at -7 {{e.g., 'extern template}}
-// expected-note at -8 {{e.g., 'extern template}}
-// expected-note at -9 {{used here}}
+// expected-note at -6 {{used here}}
public:
constexpr void bar(unsigned int) override { }
diff --git a/clang/test/SemaTemplate/undefined-template.cpp b/clang/test/SemaTemplate/undefined-template.cpp
index c26ab6c8ff03a..f1331c3437b93 100644
--- a/clang/test/SemaTemplate/undefined-template.cpp
+++ b/clang/test/SemaTemplate/undefined-template.cpp
@@ -49,7 +49,6 @@ char func_03() {
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}}
- // expected-note at -2{{e.g., 'extern template void C1<int>::s_func_1();'}}
}
void func_05() {
@@ -59,13 +58,11 @@ void func_05() {
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}}
- // expected-note at -2{{e.g., 'extern template void C1<char>::s_func_2();'}}
}
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}}
- // expected-note at -2{{e.g., 'extern template void C1<int>::meth_1();'}}
}
void func_08(C1<int> *x) {
@@ -75,7 +72,6 @@ void func_08(C1<int> *x) {
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}}
- // expected-note at -2{{e.g., 'extern template void C1<char>::meth_1();'}}
}
char func_10() {
@@ -95,7 +91,6 @@ void func_12() {
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}}
- // expected-note at -2{{e.g., 'extern template void C1<int>::s_tfunc_2<long>();'}}
}
char func_14() {
@@ -115,7 +110,6 @@ void func_16() {
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}}
- // expected-note at -2{{e.g., 'extern template void C1<int>::C2<char>::s_func_2();'}}
}
void func_18(C1<int>::C2<long> *x) {
@@ -125,7 +119,6 @@ void func_18(C1<int>::C2<long> *x) {
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}}
- // expected-note at -2{{e.g., 'extern template void C1<int>::C2<char>::meth_2();'}}
}
char func_20() {
@@ -145,7 +138,6 @@ void func_22(C1<int>::C2<long> *x) {
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}}
- // expected-note at -2{{e.g., 'extern template void C1<int>::C2<long>::tmeth_2<int>();'}}
}
namespace test_24 {
More information about the cfe-commits
mailing list