Skip to content

Commit 228d525

Browse files
committed
[clang] print correct context for diagnostics suppressed by deduction
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.
1 parent 7781e10 commit 228d525

18 files changed

+214
-162
lines changed

clang/docs/ReleaseNotes.rst

+3-1
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,8 @@ Bug Fixes to C++ Support
168168
^^^^^^^^^^^^^^^^^^^^^^^^
169169

170170
- Clang is now better at keeping track of friend function template instance contexts. (#GH55509)
171+
- Clang now prints the correct instantiation context for diagnostics suppressed
172+
by template argument deduction.
171173
- The initialization kind of elements of structured bindings
172174
direct-list-initialized from an array is corrected to direct-initialization.
173175

@@ -271,7 +273,7 @@ Code Completion
271273
Static Analyzer
272274
---------------
273275

274-
- Clang currently support extending lifetime of object bound to
276+
- Clang currently support extending lifetime of object bound to
275277
reference members of aggregates in CFG and ExprEngine, that are
276278
created from default member initializer.
277279

clang/include/clang/Sema/Sema.h

+25-5
Original file line numberDiff line numberDiff line change
@@ -1908,7 +1908,23 @@ class Sema final : public SemaBase {
19081908
/// '\#pragma clang attribute push' directives to the given declaration.
19091909
void AddPragmaAttributes(Scope *S, Decl *D);
19101910

1911-
void PrintPragmaAttributeInstantiationPoint();
1911+
using InstantiationContextDiagFuncRef =
1912+
llvm::function_ref<void(SourceLocation, PartialDiagnostic)>;
1913+
auto getDefaultDiagFunc() {
1914+
return [this](SourceLocation Loc, PartialDiagnostic PD) {
1915+
// This bypasses a lot of the filters in the diag engine, as it's
1916+
// to be used to attach notes to diagnostics which have already
1917+
// been filtered through.
1918+
DiagnosticBuilder Builder(Diags.Report(Loc, PD.getDiagID()));
1919+
PD.Emit(Builder);
1920+
};
1921+
}
1922+
1923+
void PrintPragmaAttributeInstantiationPoint(
1924+
InstantiationContextDiagFuncRef DiagFunc);
1925+
void PrintPragmaAttributeInstantiationPoint() {
1926+
PrintPragmaAttributeInstantiationPoint(getDefaultDiagFunc());
1927+
}
19121928

19131929
void DiagnoseUnterminatedPragmaAttribute();
19141930

@@ -13263,18 +13279,22 @@ class Sema final : public SemaBase {
1326313279
void pushCodeSynthesisContext(CodeSynthesisContext Ctx);
1326413280
void popCodeSynthesisContext();
1326513281

13266-
void PrintContextStack() {
13282+
void PrintContextStack(InstantiationContextDiagFuncRef DiagFunc) {
1326713283
if (!CodeSynthesisContexts.empty() &&
1326813284
CodeSynthesisContexts.size() != LastEmittedCodeSynthesisContextDepth) {
13269-
PrintInstantiationStack();
13285+
PrintInstantiationStack(DiagFunc);
1327013286
LastEmittedCodeSynthesisContextDepth = CodeSynthesisContexts.size();
1327113287
}
1327213288
if (PragmaAttributeCurrentTargetDecl)
13273-
PrintPragmaAttributeInstantiationPoint();
13289+
PrintPragmaAttributeInstantiationPoint(DiagFunc);
1327413290
}
13291+
void PrintContextStack() { PrintContextStack(getDefaultDiagFunc()); }
1327513292
/// Prints the current instantiation stack through a series of
1327613293
/// notes.
13277-
void PrintInstantiationStack();
13294+
void PrintInstantiationStack(InstantiationContextDiagFuncRef DiagFunc);
13295+
void PrintInstantiationStack() {
13296+
PrintInstantiationStack(getDefaultDiagFunc());
13297+
}
1327813298

1327913299
/// Determines whether we are currently in a context where
1328013300
/// template argument substitution failures are not considered

clang/lib/Sema/Sema.cpp

+11-2
Original file line numberDiff line numberDiff line change
@@ -1655,11 +1655,20 @@ void Sema::EmitDiagnostic(unsigned DiagID, const DiagnosticBuilder &DB) {
16551655
}
16561656

16571657
case DiagnosticIDs::SFINAE_Suppress:
1658+
if (DiagnosticsEngine::Level Level = getDiagnostics().getDiagnosticLevel(
1659+
DiagInfo.getID(), DiagInfo.getLocation());
1660+
Level == DiagnosticsEngine::Ignored)
1661+
return;
16581662
// Make a copy of this suppressed diagnostic and store it with the
16591663
// template-deduction information;
16601664
if (*Info) {
1661-
(*Info)->addSuppressedDiagnostic(DiagInfo.getLocation(),
1662-
PartialDiagnostic(DiagInfo, Context.getDiagAllocator()));
1665+
(*Info)->addSuppressedDiagnostic(
1666+
DiagInfo.getLocation(),
1667+
PartialDiagnostic(DiagInfo, Context.getDiagAllocator()));
1668+
if (!Diags.getDiagnosticIDs()->isNote(DiagID))
1669+
PrintContextStack([Info](SourceLocation Loc, PartialDiagnostic PD) {
1670+
(*Info)->addSuppressedDiagnostic(Loc, std::move(PD));
1671+
});
16631672
}
16641673

16651674
// Suppress this diagnostic.

clang/lib/Sema/SemaAttr.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -1221,10 +1221,11 @@ void Sema::AddPragmaAttributes(Scope *S, Decl *D) {
12211221
}
12221222
}
12231223

1224-
void Sema::PrintPragmaAttributeInstantiationPoint() {
1224+
void Sema::PrintPragmaAttributeInstantiationPoint(
1225+
InstantiationContextDiagFuncRef DiagFunc) {
12251226
assert(PragmaAttributeCurrentTargetDecl && "Expected an active declaration");
1226-
Diags.Report(PragmaAttributeCurrentTargetDecl->getBeginLoc(),
1227-
diag::note_pragma_attribute_applied_decl_here);
1227+
DiagFunc(PragmaAttributeCurrentTargetDecl->getBeginLoc(),
1228+
PDiag(diag::note_pragma_attribute_applied_decl_here));
12281229
}
12291230

12301231
void Sema::DiagnosePrecisionLossInComplexDivision() {

clang/lib/Sema/SemaExpr.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,10 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs,
225225
// emit them now.
226226
auto Pos = SuppressedDiagnostics.find(D->getCanonicalDecl());
227227
if (Pos != SuppressedDiagnostics.end()) {
228-
for (const PartialDiagnosticAt &Suppressed : Pos->second)
229-
Diag(Suppressed.first, Suppressed.second);
230-
228+
for (const auto &[DiagLoc, PD] : Pos->second) {
229+
DiagnosticBuilder Builder(Diags.Report(DiagLoc, PD.getDiagID()));
230+
PD.Emit(Builder);
231+
}
231232
// Clear out the list of suppressed diagnostics, so that we don't emit
232233
// them again for this specialization. However, we don't obsolete this
233234
// entry from the table, because we want to avoid ever emitting these

0 commit comments

Comments
 (0)