[clang] 434ac46 - Improve the -Wundefined-func-template diagnostic note for invisible template functions (#129031)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Mar 19 02:51:48 PDT 2025
Author: Haojian Wu
Date: 2025-03-19T10:51:45+01:00
New Revision: 434ac4612f2b43a5b7f1a8e3b5310e8d129360e6
URL: https://github.com/llvm/llvm-project/commit/434ac4612f2b43a5b7f1a8e3b5310e8d129360e6
DIFF: https://github.com/llvm/llvm-project/commit/434ac4612f2b43a5b7f1a8e3b5310e8d129360e6.diff
LOG: Improve the -Wundefined-func-template diagnostic note for invisible template functions (#129031)
See discussion in https://github.com/llvm/llvm-project/issues/125071.
Makes the note clearer for the unreachable case:
Before:
```
./hoge.h:5:12: warning: instantiation of function 'x<int>' required here, but no definition is available [-Wundefined-func-template]
5 | void f() { x<int>(); }
| ^
./shared_ptr2.h:4:6: note: forward declaration of template entity is here
4 | void x() { T t; (void)t; }
| ^
./hoge.h:5:12: note: add an explicit instantiation declaration to suppress this warning if 'x<int>' is explicitly instantiated in another translation unit
5 | void f() { x<int>(); }
|
```
After:
```
./hoge.h:5:12: warning: instantiation of function 'x<int>' required here, but no definition is available [-Wundefined-func-template]
5 | void f() { x<int>(); }
| ^
./shared_ptr2.h:4:6: note: declaration of template entity is unreachable here
4 | void x() { T t; (void)t; }
| ^
1 warning generated.
```
Added:
clang/test/Modules/diag-undefined-template.cpp
Modified:
clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Sema/Sema.h
clang/lib/Sema/SemaTemplate.cpp
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 1c0504d831e3f..867ce60207b9d 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -278,6 +278,8 @@ Improvements to Clang's diagnostics
- Improve the diagnostics for shadows template parameter to report correct location (#GH129060).
+- Improve the ``-Wundefined-func-template`` warning when a function template is not instantiated due to being unreachable in modules.
+
Improvements to Clang's time-trace
----------------------------------
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index e156ad03e7640..1536a3b8c920a 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5700,6 +5700,8 @@ def warn_func_template_missing : Warning<"instantiation of function %q0 "
InGroup<UndefinedFuncTemplate>, DefaultIgnore;
def note_forward_template_decl : Note<
"forward declaration of template entity is here">;
+def note_unreachable_template_decl
+ : Note<"unreachable 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">;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 9561c59b1facf..2b80d91a881ec 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -11268,13 +11268,11 @@ class Sema final : public SemaBase {
/// Determine whether we would be unable to instantiate this template (because
/// it either has no definition, or is in the process of being instantiated).
- bool DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation,
- NamedDecl *Instantiation,
- bool InstantiatedFromMember,
- const NamedDecl *Pattern,
- const NamedDecl *PatternDef,
- TemplateSpecializationKind TSK,
- bool Complain = true);
+ bool DiagnoseUninstantiableTemplate(
+ SourceLocation PointOfInstantiation, NamedDecl *Instantiation,
+ bool InstantiatedFromMember, const NamedDecl *Pattern,
+ const NamedDecl *PatternDef, TemplateSpecializationKind TSK,
+ bool Complain = true, bool *Unreachable = nullptr);
/// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining
/// that the template parameter 'PrevDecl' is being shadowed by a new
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index a56720ec26fbd..c3c993d51b79d 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -765,7 +765,7 @@ bool Sema::DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation,
const NamedDecl *Pattern,
const NamedDecl *PatternDef,
TemplateSpecializationKind TSK,
- bool Complain /*= true*/) {
+ bool Complain, bool *Unreachable) {
assert(isa<TagDecl>(Instantiation) || isa<FunctionDecl>(Instantiation) ||
isa<VarDecl>(Instantiation));
@@ -778,6 +778,8 @@ bool Sema::DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation,
if (!hasReachableDefinition(const_cast<NamedDecl *>(PatternDef),
&SuggestedDef,
/*OnlyNeedComplete*/ false)) {
+ if (Unreachable)
+ *Unreachable = true;
// If we're allowed to diagnose this and recover, do so.
bool Recover = Complain && !isSFINAEContext();
if (Complain)
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 170c0b0d39f86..da9bd4fcf7552 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -5386,12 +5386,15 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
PatternDef = nullptr;
}
+ // True is the template definition is unreachable, otherwise false.
+ bool Unreachable = false;
// FIXME: We need to track the instantiation stack in order to know which
// definitions should be visible within this instantiation.
- if (DiagnoseUninstantiableTemplate(PointOfInstantiation, Function,
- Function->getInstantiatedFromMemberFunction(),
- PatternDecl, PatternDef, TSK,
- /*Complain*/DefinitionRequired)) {
+ if (DiagnoseUninstantiableTemplate(
+ PointOfInstantiation, Function,
+ Function->getInstantiatedFromMemberFunction(), PatternDecl,
+ PatternDef, TSK,
+ /*Complain*/ DefinitionRequired, &Unreachable)) {
if (DefinitionRequired)
Function->setInvalidDecl();
else if (TSK == TSK_ExplicitInstantiationDefinition ||
@@ -5416,11 +5419,18 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
if (AtEndOfTU && !getDiagnostics().hasErrorOccurred() &&
!getSourceManager().isInSystemHeader(PatternDecl->getBeginLoc())) {
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;
+ << Function;
+ if (Unreachable) {
+ // FIXME: would be nice to mention which module the function template
+ // comes from.
+ Diag(PatternDecl->getLocation(),
+ diag::note_unreachable_template_decl);
+ } else {
+ Diag(PatternDecl->getLocation(), diag::note_forward_template_decl);
+ if (getLangOpts().CPlusPlus11)
+ Diag(PointOfInstantiation, diag::note_inst_declaration_hint)
+ << Function;
+ }
}
}
diff --git a/clang/test/Modules/diag-undefined-template.cpp b/clang/test/Modules/diag-undefined-template.cpp
new file mode 100644
index 0000000000000..3fb2c1f8c05c9
--- /dev/null
+++ b/clang/test/Modules/diag-undefined-template.cpp
@@ -0,0 +1,39 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: %clang_cc1 -std=c++20 -fmodules -fmodules-cache-path=%t -I%t \
+// RUN: -Wundefined-func-template \
+// RUN: -fimplicit-module-maps %t/main.cpp 2>&1 | grep "unreachable declaration of template entity is here"
+
+// Note that the diagnostics are triggered when building the 'hoge' module, which is imported from the main file.
+// The "-verify" flag doesn't work in this case. Instead, we grep the expected text to verify the test.
+
+//--- shared_ptr2.h
+#pragma once
+
+template<class T>
+void x() { }
+
+//--- hoge.h
+#pragma once
+
+#include "shared_ptr2.h"
+
+inline void f() {
+ x<int>();
+}
+
+//--- module.modulemap
+module hoge {
+ header "hoge.h"
+}
+
+module shared_ptr2 {
+ header "shared_ptr2.h"
+}
+
+//--- main.cpp
+#include "hoge.h"
+
+int main() {
+ f();
+}
More information about the cfe-commits
mailing list