mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-18 19:26:45 +00:00
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. ```
This commit is contained in:
parent
1f84495255
commit
434ac4612f
@ -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
|
||||
----------------------------------
|
||||
|
||||
|
@ -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">;
|
||||
|
@ -11268,13 +11268,11 @@ public:
|
||||
|
||||
/// 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
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
39
clang/test/Modules/diag-undefined-template.cpp
Normal file
39
clang/test/Modules/diag-undefined-template.cpp
Normal file
@ -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();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user