Skip to content

[clang] print correct context for diagnostics suppressed by deduction #125453

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,8 @@ Bug Fixes to C++ Support
^^^^^^^^^^^^^^^^^^^^^^^^

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

Expand Down Expand Up @@ -271,7 +273,7 @@ Code Completion
Static Analyzer
---------------

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

Expand Down
30 changes: 25 additions & 5 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -1908,7 +1908,23 @@ class Sema final : public SemaBase {
/// '\#pragma clang attribute push' directives to the given declaration.
void AddPragmaAttributes(Scope *S, Decl *D);

void PrintPragmaAttributeInstantiationPoint();
using InstantiationContextDiagFuncRef =
llvm::function_ref<void(SourceLocation, PartialDiagnostic)>;
auto getDefaultDiagFunc() {
return [this](SourceLocation Loc, PartialDiagnostic PD) {
// This bypasses a lot of the filters in the diag engine, as it's
// to be used to attach notes to diagnostics which have already
// been filtered through.
DiagnosticBuilder Builder(Diags.Report(Loc, PD.getDiagID()));
PD.Emit(Builder);
};
}

void PrintPragmaAttributeInstantiationPoint(
InstantiationContextDiagFuncRef DiagFunc);
void PrintPragmaAttributeInstantiationPoint() {
PrintPragmaAttributeInstantiationPoint(getDefaultDiagFunc());
}

void DiagnoseUnterminatedPragmaAttribute();

Expand Down Expand Up @@ -13263,18 +13279,22 @@ class Sema final : public SemaBase {
void pushCodeSynthesisContext(CodeSynthesisContext Ctx);
void popCodeSynthesisContext();

void PrintContextStack() {
void PrintContextStack(InstantiationContextDiagFuncRef 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(InstantiationContextDiagFuncRef DiagFunc);
void PrintInstantiationStack() {
PrintInstantiationStack(getDefaultDiagFunc());
}

/// Determines whether we are currently in a context where
/// template argument substitution failures are not considered
Expand Down
13 changes: 11 additions & 2 deletions clang/lib/Sema/Sema.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1655,11 +1655,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.
Expand Down
7 changes: 4 additions & 3 deletions clang/lib/Sema/SemaAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1221,10 +1221,11 @@ void Sema::AddPragmaAttributes(Scope *S, Decl *D) {
}
}

void Sema::PrintPragmaAttributeInstantiationPoint() {
void Sema::PrintPragmaAttributeInstantiationPoint(
InstantiationContextDiagFuncRef 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() {
Expand Down
7 changes: 4 additions & 3 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading