[clang] [clang] print correct context for diagnostics suppressed by deduction (PR #125453)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Feb 2 19:27:03 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Matheus Izvekov (mizvekov)
<details>
<summary>Changes</summary>
This patch makes it so the correct instantiation context is printed for diagnostics suppessed by template argument deduction.
The context is saved along with the suppressed diagnostic, and when the declaration they were attached to becomes used, we print the correct context, instead of whatever context was at this point.
---
Patch is 38.76 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/125453.diff
18 Files Affected:
- (modified) clang/docs/ReleaseNotes.rst (+3)
- (modified) clang/include/clang/Sema/Sema.h (+21-5)
- (modified) clang/lib/Sema/Sema.cpp (+11-2)
- (modified) clang/lib/Sema/SemaAttr.cpp (+3-3)
- (modified) clang/lib/Sema/SemaExpr.cpp (+4-3)
- (modified) clang/lib/Sema/SemaTemplateInstantiate.cpp (+136-135)
- (modified) clang/test/CXX/drs/cwg0xx.cpp (+5)
- (modified) clang/test/CXX/drs/cwg4xx.cpp (+2-1)
- (modified) clang/test/CXX/temp/temp.arg/temp.arg.type/p2.cpp (+6-3)
- (modified) clang/test/SemaCXX/anonymous-struct.cpp (+2-3)
- (modified) clang/test/SemaCXX/bool-increment-SFINAE.cpp (+2-2)
- (modified) clang/test/SemaCXX/cxx98-compat-flags.cpp (+2)
- (modified) clang/test/SemaCXX/cxx98-compat.cpp (+2)
- (modified) clang/test/SemaCXX/deprecated.cpp (+2-2)
- (modified) clang/test/SemaCXX/lambda-expressions.cpp (+2)
- (modified) clang/test/SemaCXX/undefined-internal.cpp (+4-2)
- (modified) clang/test/SemaTemplate/recovery-crash.cpp (+1)
- (modified) clang/test/SemaTemplate/temp_arg_nontype.cpp (+1)
``````````diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 8be1ea2fb01455..70c3b062d97717 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -128,6 +128,9 @@ Bug Fixes to Attribute Support
Bug Fixes to C++ Support
^^^^^^^^^^^^^^^^^^^^^^^^
+- Clang now prints the correct instantiation context for diagnostics suppressed
+ by template argument deduction.
+
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 472a0e25adc975..7d01dc1aa4c00b 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -1909,7 +1909,19 @@ class Sema final : public SemaBase {
/// '\#pragma clang attribute push' directives to the given declaration.
void AddPragmaAttributes(Scope *S, Decl *D);
- void PrintPragmaAttributeInstantiationPoint();
+ using DiagFuncRef =
+ llvm::function_ref<void(SourceLocation, PartialDiagnostic)>;
+ auto getDefaultDiagFunc() {
+ return [this](SourceLocation Loc, PartialDiagnostic PD) {
+ DiagnosticBuilder Builder(Diags.Report(Loc, PD.getDiagID()));
+ PD.Emit(Builder);
+ };
+ }
+
+ void PrintPragmaAttributeInstantiationPoint(DiagFuncRef DiagFunc);
+ void PrintPragmaAttributeInstantiationPoint() {
+ PrintPragmaAttributeInstantiationPoint(getDefaultDiagFunc());
+ }
void DiagnoseUnterminatedPragmaAttribute();
@@ -13260,18 +13272,22 @@ class Sema final : public SemaBase {
void pushCodeSynthesisContext(CodeSynthesisContext Ctx);
void popCodeSynthesisContext();
- void PrintContextStack() {
+ void PrintContextStack(DiagFuncRef DiagFunc) {
if (!CodeSynthesisContexts.empty() &&
CodeSynthesisContexts.size() != LastEmittedCodeSynthesisContextDepth) {
- PrintInstantiationStack();
+ PrintInstantiationStack(DiagFunc);
LastEmittedCodeSynthesisContextDepth = CodeSynthesisContexts.size();
}
if (PragmaAttributeCurrentTargetDecl)
- PrintPragmaAttributeInstantiationPoint();
+ PrintPragmaAttributeInstantiationPoint(DiagFunc);
}
+ void PrintContextStack() { PrintContextStack(getDefaultDiagFunc()); }
/// Prints the current instantiation stack through a series of
/// notes.
- void PrintInstantiationStack();
+ void PrintInstantiationStack(DiagFuncRef DiagFunc);
+ void PrintInstantiationStack() {
+ PrintInstantiationStack(getDefaultDiagFunc());
+ }
/// Determines whether we are currently in a context where
/// template argument substitution failures are not considered
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 9507d7602aa401..33e2bd1e030513 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -1654,11 +1654,20 @@ void Sema::EmitDiagnostic(unsigned DiagID, const DiagnosticBuilder &DB) {
}
case DiagnosticIDs::SFINAE_Suppress:
+ if (DiagnosticsEngine::Level Level = getDiagnostics().getDiagnosticLevel(
+ DiagInfo.getID(), DiagInfo.getLocation());
+ Level == DiagnosticsEngine::Ignored)
+ return;
// Make a copy of this suppressed diagnostic and store it with the
// template-deduction information;
if (*Info) {
- (*Info)->addSuppressedDiagnostic(DiagInfo.getLocation(),
- PartialDiagnostic(DiagInfo, Context.getDiagAllocator()));
+ (*Info)->addSuppressedDiagnostic(
+ DiagInfo.getLocation(),
+ PartialDiagnostic(DiagInfo, Context.getDiagAllocator()));
+ if (!Diags.getDiagnosticIDs()->isNote(DiagID))
+ PrintContextStack([Info](SourceLocation Loc, PartialDiagnostic PD) {
+ (*Info)->addSuppressedDiagnostic(Loc, std::move(PD));
+ });
}
// Suppress this diagnostic.
diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp
index 6907fa91e28c20..b66c7d3024adc9 100644
--- a/clang/lib/Sema/SemaAttr.cpp
+++ b/clang/lib/Sema/SemaAttr.cpp
@@ -1217,10 +1217,10 @@ void Sema::AddPragmaAttributes(Scope *S, Decl *D) {
}
}
-void Sema::PrintPragmaAttributeInstantiationPoint() {
+void Sema::PrintPragmaAttributeInstantiationPoint(DiagFuncRef DiagFunc) {
assert(PragmaAttributeCurrentTargetDecl && "Expected an active declaration");
- Diags.Report(PragmaAttributeCurrentTargetDecl->getBeginLoc(),
- diag::note_pragma_attribute_applied_decl_here);
+ DiagFunc(PragmaAttributeCurrentTargetDecl->getBeginLoc(),
+ PDiag(diag::note_pragma_attribute_applied_decl_here));
}
void Sema::DiagnosePrecisionLossInComplexDivision() {
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index ba4aaa94b90ffd..1d693333fef58b 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -225,9 +225,10 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
// emit them now.
auto Pos = SuppressedDiagnostics.find(D->getCanonicalDecl());
if (Pos != SuppressedDiagnostics.end()) {
- for (const PartialDiagnosticAt &Suppressed : Pos->second)
- Diag(Suppressed.first, Suppressed.second);
-
+ for (const auto &[DiagLoc, PD] : Pos->second) {
+ DiagnosticBuilder Builder(Diags.Report(DiagLoc, PD.getDiagID()));
+ PD.Emit(Builder);
+ }
// Clear out the list of suppressed diagnostics, so that we don't emit
// them again for this specialization. However, we don't obsolete this
// entry from the table, because we want to avoid ever emitting these
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index dc3bfa97eff399..dd832d0dd709bf 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -904,7 +904,7 @@ bool Sema::InstantiatingTemplate::CheckInstantiationDepth(
return true;
}
-void Sema::PrintInstantiationStack() {
+void Sema::PrintInstantiationStack(DiagFuncRef DiagFunc) {
// Determine which template instantiations to skip, if any.
unsigned SkipStart = CodeSynthesisContexts.size(), SkipEnd = SkipStart;
unsigned Limit = Diags.getTemplateBacktraceLimit();
@@ -924,9 +924,9 @@ void Sema::PrintInstantiationStack() {
if (InstantiationIdx >= SkipStart && InstantiationIdx < SkipEnd) {
if (InstantiationIdx == SkipStart) {
// Note that we're skipping instantiations.
- Diags.Report(Active->PointOfInstantiation,
- diag::note_instantiation_contexts_suppressed)
- << unsigned(CodeSynthesisContexts.size() - Limit);
+ DiagFunc(Active->PointOfInstantiation,
+ PDiag(diag::note_instantiation_contexts_suppressed)
+ << unsigned(CodeSynthesisContexts.size() - Limit));
}
continue;
}
@@ -938,37 +938,34 @@ void Sema::PrintInstantiationStack() {
unsigned DiagID = diag::note_template_member_class_here;
if (isa<ClassTemplateSpecializationDecl>(Record))
DiagID = diag::note_template_class_instantiation_here;
- Diags.Report(Active->PointOfInstantiation, DiagID)
- << Record << Active->InstantiationRange;
+ DiagFunc(Active->PointOfInstantiation,
+ PDiag(DiagID) << Record << Active->InstantiationRange);
} else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
unsigned DiagID;
if (Function->getPrimaryTemplate())
DiagID = diag::note_function_template_spec_here;
else
DiagID = diag::note_template_member_function_here;
- Diags.Report(Active->PointOfInstantiation, DiagID)
- << Function
- << Active->InstantiationRange;
+ DiagFunc(Active->PointOfInstantiation,
+ PDiag(DiagID) << Function << Active->InstantiationRange);
} else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
- Diags.Report(Active->PointOfInstantiation,
- VD->isStaticDataMember()?
- diag::note_template_static_data_member_def_here
- : diag::note_template_variable_def_here)
- << VD
- << Active->InstantiationRange;
+ DiagFunc(Active->PointOfInstantiation,
+ PDiag(VD->isStaticDataMember()
+ ? diag::note_template_static_data_member_def_here
+ : diag::note_template_variable_def_here)
+ << VD << Active->InstantiationRange);
} else if (EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
- Diags.Report(Active->PointOfInstantiation,
- diag::note_template_enum_def_here)
- << ED
- << Active->InstantiationRange;
+ DiagFunc(Active->PointOfInstantiation,
+ PDiag(diag::note_template_enum_def_here)
+ << ED << Active->InstantiationRange);
} else if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
- Diags.Report(Active->PointOfInstantiation,
- diag::note_template_nsdmi_here)
- << FD << Active->InstantiationRange;
+ DiagFunc(Active->PointOfInstantiation,
+ PDiag(diag::note_template_nsdmi_here)
+ << FD << Active->InstantiationRange);
} else if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(D)) {
- Diags.Report(Active->PointOfInstantiation,
- diag::note_template_class_instantiation_here)
- << CTD << Active->InstantiationRange;
+ DiagFunc(Active->PointOfInstantiation,
+ PDiag(diag::note_template_class_instantiation_here)
+ << CTD << Active->InstantiationRange);
}
break;
}
@@ -980,35 +977,35 @@ void Sema::PrintInstantiationStack() {
Template->printName(OS, getPrintingPolicy());
printTemplateArgumentList(OS, Active->template_arguments(),
getPrintingPolicy());
- Diags.Report(Active->PointOfInstantiation,
- diag::note_default_arg_instantiation_here)
- << OS.str()
- << Active->InstantiationRange;
+ DiagFunc(Active->PointOfInstantiation,
+ PDiag(diag::note_default_arg_instantiation_here)
+ << OS.str() << Active->InstantiationRange);
break;
}
case CodeSynthesisContext::ExplicitTemplateArgumentSubstitution: {
FunctionTemplateDecl *FnTmpl = cast<FunctionTemplateDecl>(Active->Entity);
- Diags.Report(Active->PointOfInstantiation,
- diag::note_explicit_template_arg_substitution_here)
- << FnTmpl
- << getTemplateArgumentBindingsText(FnTmpl->getTemplateParameters(),
- Active->TemplateArgs,
- Active->NumTemplateArgs)
- << Active->InstantiationRange;
+ DiagFunc(Active->PointOfInstantiation,
+ PDiag(diag::note_explicit_template_arg_substitution_here)
+ << FnTmpl
+ << getTemplateArgumentBindingsText(
+ FnTmpl->getTemplateParameters(), Active->TemplateArgs,
+ Active->NumTemplateArgs)
+ << Active->InstantiationRange);
break;
}
case CodeSynthesisContext::DeducedTemplateArgumentSubstitution: {
if (FunctionTemplateDecl *FnTmpl =
dyn_cast<FunctionTemplateDecl>(Active->Entity)) {
- Diags.Report(Active->PointOfInstantiation,
- diag::note_function_template_deduction_instantiation_here)
- << FnTmpl
- << getTemplateArgumentBindingsText(FnTmpl->getTemplateParameters(),
- Active->TemplateArgs,
- Active->NumTemplateArgs)
- << Active->InstantiationRange;
+ DiagFunc(
+ Active->PointOfInstantiation,
+ PDiag(diag::note_function_template_deduction_instantiation_here)
+ << FnTmpl
+ << getTemplateArgumentBindingsText(
+ FnTmpl->getTemplateParameters(), Active->TemplateArgs,
+ Active->NumTemplateArgs)
+ << Active->InstantiationRange);
} else {
bool IsVar = isa<VarTemplateDecl>(Active->Entity) ||
isa<VarTemplateSpecializationDecl>(Active->Entity);
@@ -1027,12 +1024,13 @@ void Sema::PrintInstantiationStack() {
llvm_unreachable("unexpected template kind");
}
- Diags.Report(Active->PointOfInstantiation,
- diag::note_deduced_template_arg_substitution_here)
- << IsVar << IsTemplate << cast<NamedDecl>(Active->Entity)
- << getTemplateArgumentBindingsText(Params, Active->TemplateArgs,
- Active->NumTemplateArgs)
- << Active->InstantiationRange;
+ DiagFunc(Active->PointOfInstantiation,
+ PDiag(diag::note_deduced_template_arg_substitution_here)
+ << IsVar << IsTemplate << cast<NamedDecl>(Active->Entity)
+ << getTemplateArgumentBindingsText(Params,
+ Active->TemplateArgs,
+ Active->NumTemplateArgs)
+ << Active->InstantiationRange);
}
break;
}
@@ -1046,10 +1044,9 @@ void Sema::PrintInstantiationStack() {
FD->printName(OS, getPrintingPolicy());
printTemplateArgumentList(OS, Active->template_arguments(),
getPrintingPolicy());
- Diags.Report(Active->PointOfInstantiation,
- diag::note_default_function_arg_instantiation_here)
- << OS.str()
- << Active->InstantiationRange;
+ DiagFunc(Active->PointOfInstantiation,
+ PDiag(diag::note_default_function_arg_instantiation_here)
+ << OS.str() << Active->InstantiationRange);
break;
}
@@ -1066,14 +1063,13 @@ void Sema::PrintInstantiationStack() {
TemplateParams =
cast<ClassTemplatePartialSpecializationDecl>(Active->Template)
->getTemplateParameters();
- Diags.Report(Active->PointOfInstantiation,
- diag::note_prior_template_arg_substitution)
- << isa<TemplateTemplateParmDecl>(Parm)
- << Name
- << getTemplateArgumentBindingsText(TemplateParams,
- Active->TemplateArgs,
- Active->NumTemplateArgs)
- << Active->InstantiationRange;
+ DiagFunc(Active->PointOfInstantiation,
+ PDiag(diag::note_prior_template_arg_substitution)
+ << isa<TemplateTemplateParmDecl>(Parm) << Name
+ << getTemplateArgumentBindingsText(TemplateParams,
+ Active->TemplateArgs,
+ Active->NumTemplateArgs)
+ << Active->InstantiationRange);
break;
}
@@ -1086,55 +1082,56 @@ void Sema::PrintInstantiationStack() {
cast<ClassTemplatePartialSpecializationDecl>(Active->Template)
->getTemplateParameters();
- Diags.Report(Active->PointOfInstantiation,
- diag::note_template_default_arg_checking)
- << getTemplateArgumentBindingsText(TemplateParams,
- Active->TemplateArgs,
- Active->NumTemplateArgs)
- << Active->InstantiationRange;
+ DiagFunc(Active->PointOfInstantiation,
+ PDiag(diag::note_template_default_arg_checking)
+ << getTemplateArgumentBindingsText(TemplateParams,
+ Active->TemplateArgs,
+ Active->NumTemplateArgs)
+ << Active->InstantiationRange);
break;
}
case CodeSynthesisContext::ExceptionSpecEvaluation:
- Diags.Report(Active->PointOfInstantiation,
- diag::note_evaluating_exception_spec_here)
- << cast<FunctionDecl>(Active->Entity);
+ DiagFunc(Active->PointOfInstantiation,
+ PDiag(diag::note_evaluating_exception_spec_here)
+ << cast<FunctionDecl>(Active->Entity));
break;
case CodeSynthesisContext::ExceptionSpecInstantiation:
- Diags.Report(Active->PointOfInstantiation,
- diag::note_template_exception_spec_instantiation_here)
- << cast<FunctionDecl>(Active->Entity)
- << Active->InstantiationRange;
+ DiagFunc(Active->PointOfInstantiation,
+ PDiag(diag::note_template_exception_spec_instantiation_here)
+ << cast<FunctionDecl>(Active->Entity)
+ << Active->InstantiationRange);
break;
case CodeSynthesisContext::RequirementInstantiation:
- Diags.Report(Active->PointOfInstantiation,
- diag::note_template_requirement_instantiation_here)
- << Active->InstantiationRange;
+ DiagFunc(Active->PointOfInstantiation,
+ PDiag(diag::note_template_requirement_instantiation_here)
+ << Active->InstantiationRange);
break;
case CodeSynthesisContext::RequirementParameterInstantiation:
- Diags.Report(Active->PointOfInstantiation,
- diag::note_template_requirement_params_instantiation_here)
- << Active->InstantiationRange;
+ DiagFunc(Active->PointOfInstantiation,
+ PDiag(diag::note_template_requirement_params_instantiation_here)
+ << Active->InstantiationRange);
break;
case CodeSynthesisContext::NestedRequirementConstraintsCheck:
- Diags.Report(Active->PointOfInstantiation,
- diag::note_nested_requirement_here)
- << Active->InstantiationRange;
+ DiagFunc(Active->PointOfInstantiation,
+ PDiag(diag::note_nested_requirement_here)
+ << Active->InstantiationRange);
break;
case CodeSynthesisContext::DeclaringSpecialMember:
- Diags.Report(Active->PointOfInstantiation,
- diag::note_in_declaration_of_implicit_special_member)
- << cast<CXXRecordDecl>(Active->Entity)
- << llvm::to_underlying(Active->SpecialMember);
+ DiagFunc(Active->PointOfInstantiation,
+ PDiag(diag::note_in_declaration_of_implicit_special_member)
+ << cast<CXXRecordDecl>(Active->Entity)
+ << llvm::to_underlying(Active->SpecialMember));
break;
case CodeSynthesisContext::DeclaringImplicitEqualityComparison:
- Diags.Report(Active->Entity->getLocation(),
- diag::note_in_declaration_of_implicit_equality_comparison);
+ DiagFunc(
+ Active->Entity->getLocation(),
+ PDiag(diag::note_in_declaration_of_implicit_equality_comparison));
break;
case CodeSynthesisContext::DefiningSynthesizedFunction: {
@@ -1145,60 +1142,62 @@ void Sema::PrintInstantiationStack() {
FD ? getDefaultedFunctionKind(FD) : DefaultedFunctionKind();
if (DFK.isSpecialMember()) {
auto *MD = cast<CXXMethodDecl>(FD);
- Diags.Report(Active->PointOfInstantiation,
- diag::note_member_synthesized_at)
- << MD->isExplicitlyDefaulted()
- << llvm::to_underlying(DFK.asSpecialMember())
- << Context.getTagDeclType(MD->getParent());
+ DiagFunc(Active->PointOfInstantiation,
+ PDiag(diag::note_member_synthesized_at)
+ << MD->isExplicitlyDefaulted()
+ << llvm::to_underlying(DFK.asSpecialMember())
+ << Context.getTagDeclType(MD->getParent()));
} else if (DFK.isComparison()) {
QualType RecordType = FD->getParamDecl(0)
->getType()
.getNonReferenceType()
.getUnqualifiedType();
- Diags.Report(Active->PointOfInstantiation,
- diag::note_comparison_synthesized_at)
- << (int)DFK.asComparis...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/125453
More information about the cfe-commits
mailing list