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(); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits