https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/129031
>From 5bf873e8ab3b97956ca03ef6337baa0f52320003 Mon Sep 17 00:00:00 2001 From: Haojian Wu <hokein...@gmail.com> Date: Thu, 27 Feb 2025 11:15:09 +0100 Subject: [PATCH 1/4] Improve the -Wundefined-func-template diagnostic note for invisible function templates --- .../clang/Basic/DiagnosticSemaKinds.td | 2 ++ clang/include/clang/Sema/Sema.h | 12 ++++----- clang/lib/Sema/SemaTemplate.cpp | 14 +++++----- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 26 ++++++++++++------- 4 files changed, 31 insertions(+), 23 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index f10af8f5bd6b2..8370695912fe1 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5654,6 +5654,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<"declaration of template entity is unreachable 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 a501b901862b6..dfe1c0342252f 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -11183,13 +11183,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 38fa3ff3ab5b4..9a0e37f344287 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -759,13 +759,11 @@ Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS, TemplateArgs); } -bool Sema::DiagnoseUninstantiableTemplate(SourceLocation PointOfInstantiation, - NamedDecl *Instantiation, - bool InstantiatedFromMember, - const NamedDecl *Pattern, - const NamedDecl *PatternDef, - TemplateSpecializationKind TSK, - bool Complain /*= true*/) { +bool Sema::DiagnoseUninstantiableTemplate( + SourceLocation PointOfInstantiation, NamedDecl *Instantiation, + bool InstantiatedFromMember, const NamedDecl *Pattern, + const NamedDecl *PatternDef, TemplateSpecializationKind TSK, + bool Complain /*= true*/, bool *Unreachable) { assert(isa<TagDecl>(Instantiation) || isa<FunctionDecl>(Instantiation) || isa<VarDecl>(Instantiation)); @@ -778,6 +776,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 1f42f9500959e..f5071e9835e36 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -5052,12 +5052,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 || @@ -5082,11 +5085,16 @@ 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) { + 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; + } } } >From b24cbb918fe9d2ecb75470d68b3633d8bc68cc32 Mon Sep 17 00:00:00 2001 From: Haojian Wu <hokein...@gmail.com> Date: Fri, 28 Feb 2025 14:40:41 +0100 Subject: [PATCH 2/4] Add a lit test. --- clang/test/Modules/Inputs/undefined-template/hoge.h | 7 +++++++ .../Modules/Inputs/undefined-template/module.modulemap | 7 +++++++ .../Modules/Inputs/undefined-template/shared_ptr2.h | 4 ++++ clang/test/Modules/diag-undefined-template.cpp | 10 ++++++++++ 4 files changed, 28 insertions(+) create mode 100644 clang/test/Modules/Inputs/undefined-template/hoge.h create mode 100644 clang/test/Modules/Inputs/undefined-template/module.modulemap create mode 100644 clang/test/Modules/Inputs/undefined-template/shared_ptr2.h create mode 100644 clang/test/Modules/diag-undefined-template.cpp diff --git a/clang/test/Modules/Inputs/undefined-template/hoge.h b/clang/test/Modules/Inputs/undefined-template/hoge.h new file mode 100644 index 0000000000000..c67e85ed06734 --- /dev/null +++ b/clang/test/Modules/Inputs/undefined-template/hoge.h @@ -0,0 +1,7 @@ +#pragma once + +#include "shared_ptr2.h" + +inline void f() { + x<int>(); +} diff --git a/clang/test/Modules/Inputs/undefined-template/module.modulemap b/clang/test/Modules/Inputs/undefined-template/module.modulemap new file mode 100644 index 0000000000000..89cc78cd5a2de --- /dev/null +++ b/clang/test/Modules/Inputs/undefined-template/module.modulemap @@ -0,0 +1,7 @@ +module hoge { + header "hoge.h" +} + +module shared_ptr2 { + header "shared_ptr2.h" +} diff --git a/clang/test/Modules/Inputs/undefined-template/shared_ptr2.h b/clang/test/Modules/Inputs/undefined-template/shared_ptr2.h new file mode 100644 index 0000000000000..495cc6fe539c1 --- /dev/null +++ b/clang/test/Modules/Inputs/undefined-template/shared_ptr2.h @@ -0,0 +1,4 @@ +#pragma once + +template<class T> +void x() { } diff --git a/clang/test/Modules/diag-undefined-template.cpp b/clang/test/Modules/diag-undefined-template.cpp new file mode 100644 index 0000000000000..79b1586a702cc --- /dev/null +++ b/clang/test/Modules/diag-undefined-template.cpp @@ -0,0 +1,10 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -std=c++20 -fmodules -fmodules-cache-path=%t -I%S/Inputs/undefined-template \ +// RUN: -Wundefined-func-template \ +// RUN: -fimplicit-module-maps %s 2>&1 | grep "declaration of template entity is unreachable here" + +#include "hoge.h" + +int main() { + f(); +} >From 2cb0ad367c250912a2883f2b190e73ad37ab182e Mon Sep 17 00:00:00 2001 From: Haojian Wu <hokein...@gmail.com> Date: Fri, 28 Feb 2025 15:19:06 +0100 Subject: [PATCH 3/4] Address review comments --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 2 ++ clang/test/Modules/diag-undefined-template.cpp | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 8370695912fe1..80f2d54c8a893 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5655,7 +5655,7 @@ def warn_func_template_missing : Warning<"instantiation of function %q0 " def note_forward_template_decl : Note< "forward declaration of template entity is here">; def note_unreachable_template_decl - : Note<"declaration of template entity is unreachable here">; + : 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/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index f5071e9835e36..398e41b236ae4 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -5087,6 +5087,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, Diag(PointOfInstantiation, diag::warn_func_template_missing) << 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 { diff --git a/clang/test/Modules/diag-undefined-template.cpp b/clang/test/Modules/diag-undefined-template.cpp index 79b1586a702cc..027984c3125f3 100644 --- a/clang/test/Modules/diag-undefined-template.cpp +++ b/clang/test/Modules/diag-undefined-template.cpp @@ -1,7 +1,7 @@ // RUN: rm -rf %t // RUN: %clang_cc1 -std=c++20 -fmodules -fmodules-cache-path=%t -I%S/Inputs/undefined-template \ // RUN: -Wundefined-func-template \ -// RUN: -fimplicit-module-maps %s 2>&1 | grep "declaration of template entity is unreachable here" +// RUN: -fimplicit-module-maps %s 2>&1 | grep "unreachable declaration of template entity is her" #include "hoge.h" >From aaaffe7721a52bfdc6cbe1ea4b516646870fc58f Mon Sep 17 00:00:00 2001 From: Haojian Wu <hokein...@gmail.com> Date: Mon, 17 Mar 2025 12:38:30 +0100 Subject: [PATCH 4/4] Use split-file for the lit test --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/Sema/SemaTemplate.cpp | 2 +- .../Modules/Inputs/undefined-template/hoge.h | 7 ---- .../undefined-template/module.modulemap | 7 ---- .../Inputs/undefined-template/shared_ptr2.h | 4 --- .../test/Modules/diag-undefined-template.cpp | 33 +++++++++++++++++-- 6 files changed, 33 insertions(+), 21 deletions(-) delete mode 100644 clang/test/Modules/Inputs/undefined-template/hoge.h delete mode 100644 clang/test/Modules/Inputs/undefined-template/module.modulemap delete mode 100644 clang/test/Modules/Inputs/undefined-template/shared_ptr2.h diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 6272f32fa845a..1d3cfae46635f 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -142,6 +142,7 @@ Improvements to Clang's diagnostics - Fixed a bug where Clang's Analysis did not correctly model the destructor behavior of ``union`` members (#GH119415). - A statement attribute applied to a ``case`` label no longer suppresses 'bypassing variable initialization' diagnostics (#84072). +- 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/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 9a0e37f344287..e5d37973e7617 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -763,7 +763,7 @@ bool Sema::DiagnoseUninstantiableTemplate( SourceLocation PointOfInstantiation, NamedDecl *Instantiation, bool InstantiatedFromMember, const NamedDecl *Pattern, const NamedDecl *PatternDef, TemplateSpecializationKind TSK, - bool Complain /*= true*/, bool *Unreachable) { + bool Complain, bool *Unreachable) { assert(isa<TagDecl>(Instantiation) || isa<FunctionDecl>(Instantiation) || isa<VarDecl>(Instantiation)); diff --git a/clang/test/Modules/Inputs/undefined-template/hoge.h b/clang/test/Modules/Inputs/undefined-template/hoge.h deleted file mode 100644 index c67e85ed06734..0000000000000 --- a/clang/test/Modules/Inputs/undefined-template/hoge.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include "shared_ptr2.h" - -inline void f() { - x<int>(); -} diff --git a/clang/test/Modules/Inputs/undefined-template/module.modulemap b/clang/test/Modules/Inputs/undefined-template/module.modulemap deleted file mode 100644 index 89cc78cd5a2de..0000000000000 --- a/clang/test/Modules/Inputs/undefined-template/module.modulemap +++ /dev/null @@ -1,7 +0,0 @@ -module hoge { - header "hoge.h" -} - -module shared_ptr2 { - header "shared_ptr2.h" -} diff --git a/clang/test/Modules/Inputs/undefined-template/shared_ptr2.h b/clang/test/Modules/Inputs/undefined-template/shared_ptr2.h deleted file mode 100644 index 495cc6fe539c1..0000000000000 --- a/clang/test/Modules/Inputs/undefined-template/shared_ptr2.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -template<class T> -void x() { } diff --git a/clang/test/Modules/diag-undefined-template.cpp b/clang/test/Modules/diag-undefined-template.cpp index 027984c3125f3..3fb2c1f8c05c9 100644 --- a/clang/test/Modules/diag-undefined-template.cpp +++ b/clang/test/Modules/diag-undefined-template.cpp @@ -1,8 +1,37 @@ // RUN: rm -rf %t -// RUN: %clang_cc1 -std=c++20 -fmodules -fmodules-cache-path=%t -I%S/Inputs/undefined-template \ +// 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 %s 2>&1 | grep "unreachable declaration of template entity is her" +// 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() { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits