cjdb updated this revision to Diff 479492.
cjdb marked 4 inline comments as done.
cjdb added a comment.
responds to feedback
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D138939/new/
https://reviews.llvm.org/D138939
Files:
clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
clang-tools-extra/clangd/Compiler.cpp
clang-tools-extra/clangd/Diagnostics.cpp
clang/include/clang/Basic/Diagnostic.h
clang/include/clang/Basic/Diagnostic.td
clang/include/clang/Basic/DiagnosticAST.h
clang/include/clang/Basic/DiagnosticAnalysis.h
clang/include/clang/Basic/DiagnosticComment.h
clang/include/clang/Basic/DiagnosticCrossTU.h
clang/include/clang/Basic/DiagnosticDriver.h
clang/include/clang/Basic/DiagnosticFrontend.h
clang/include/clang/Basic/DiagnosticIDs.h
clang/include/clang/Basic/DiagnosticLex.h
clang/include/clang/Basic/DiagnosticParse.h
clang/include/clang/Basic/DiagnosticRefactoring.h
clang/include/clang/Basic/DiagnosticSema.h
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Basic/DiagnosticSerialization.h
clang/include/clang/Basic/PartialDiagnostic.h
clang/include/clang/Frontend/ASTUnit.h
clang/lib/Basic/Diagnostic.cpp
clang/lib/Basic/DiagnosticIDs.cpp
clang/lib/Format/TokenAnalyzer.cpp
clang/lib/Frontend/ASTUnit.cpp
clang/lib/Frontend/LogDiagnosticPrinter.cpp
clang/lib/Frontend/SARIFDiagnosticPrinter.cpp
clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
clang/lib/Frontend/TextDiagnosticBuffer.cpp
clang/lib/Frontend/TextDiagnosticPrinter.cpp
clang/lib/Sema/SemaOverload.cpp
clang/test/Frontend/sarif-reason.cpp
clang/test/TableGen/DiagnosticBase.inc
clang/test/TableGen/deferred-diag.td
clang/tools/clang-format/ClangFormat.cpp
clang/tools/clang-import-test/clang-import-test.cpp
clang/tools/diagtool/DiagnosticNames.cpp
clang/unittests/Driver/SimpleDiagnosticConsumer.h
clang/unittests/Driver/ToolChainTest.cpp
clang/unittests/Frontend/FrontendActionTest.cpp
clang/unittests/Tooling/RewriterTestContext.h
clang/utils/TableGen/ClangDiagnosticsEmitter.cpp
flang/lib/Frontend/TextDiagnosticBuffer.cpp
flang/lib/Frontend/TextDiagnosticPrinter.cpp
libcxxabi/test/test_demangle.pass.cpp
lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
Index: lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
===================================================================
--- lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -697,7 +697,7 @@
const clang::Diagnostic &info) override {
if (m_log) {
llvm::SmallVector<char, 32> diag_str(10);
- info.FormatDiagnostic(diag_str);
+ info.FormatLegacyDiagnostic(diag_str);
diag_str.push_back('\0');
LLDB_LOGF(m_log, "Compiler diagnostic: %s\n", diag_str.data());
}
Index: lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
===================================================================
--- lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
+++ lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
@@ -192,7 +192,7 @@
Log *log = GetLog(LLDBLog::Expressions);
if (log) {
llvm::SmallVector<char, 32> diag_str;
- Info.FormatDiagnostic(diag_str);
+ Info.FormatLegacyDiagnostic(diag_str);
diag_str.push_back('\0');
const char *plain_diag = diag_str.data();
LLDB_LOG(log, "Received diagnostic outside parsing: {0}", plain_diag);
Index: flang/lib/Frontend/TextDiagnosticPrinter.cpp
===================================================================
--- flang/lib/Frontend/TextDiagnosticPrinter.cpp
+++ flang/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -37,7 +37,8 @@
// Render the diagnostic message into a temporary buffer eagerly. We'll use
// this later as we print out the diagnostic to the terminal.
llvm::SmallString<100> outStr;
- info.FormatDiagnostic(outStr);
+ info.FormatSummary(outStr);
+ info.FormatLegacyDiagnostic(outStr);
llvm::raw_svector_ostream diagMessageStream(outStr);
Index: flang/lib/Frontend/TextDiagnosticBuffer.cpp
===================================================================
--- flang/lib/Frontend/TextDiagnosticBuffer.cpp
+++ flang/lib/Frontend/TextDiagnosticBuffer.cpp
@@ -29,7 +29,8 @@
DiagnosticConsumer::HandleDiagnostic(level, info);
llvm::SmallString<100> buf;
- info.FormatDiagnostic(buf);
+ info.FormatSummary(buf);
+ info.FormatLegacyDiagnostic(buf);
switch (level) {
default:
llvm_unreachable("Diagnostic not handled during diagnostic buffering!");
Index: clang/utils/TableGen/ClangDiagnosticsEmitter.cpp
===================================================================
--- clang/utils/TableGen/ClangDiagnosticsEmitter.cpp
+++ clang/utils/TableGen/ClangDiagnosticsEmitter.cpp
@@ -604,7 +604,7 @@
std::vector<std::string> buildForDocumentation(StringRef Role,
const Record *R);
- std::string buildForDefinition(const Record *R);
+ std::string buildForDefinition(const Record *R, StringRef Field);
Piece *getSubstitution(SubstitutionPiece *S) const {
auto It = Substitutions.find(S->Name);
@@ -1182,9 +1182,10 @@
return Result;
}
-std::string DiagnosticTextBuilder::buildForDefinition(const Record *R) {
+std::string DiagnosticTextBuilder::buildForDefinition(const Record *R,
+ StringRef Field) {
EvaluatingRecordGuard Guard(&EvaluatingRecord, R);
- StringRef Text = R->getValueAsString("Summary");
+ StringRef Text = R->getValueAsString(Field);
DiagText D(*this, Text);
std::string Result;
DiagTextPrinter{*this, Result}.Visit(D.Root);
@@ -1276,7 +1277,7 @@
// Description string.
OS << ", \"";
- OS.write_escaped(DiagTextBuilder.buildForDefinition(&R)) << '"';
+ OS.write_escaped(DiagTextBuilder.buildForDefinition(&R, "Summary")) << '"';
// Warning group associated with the diagnostic. This is stored as an index
// into the alphabetically sorted warning group table.
@@ -1320,6 +1321,17 @@
// Category number.
OS << ", " << CategoryIDs.getID(getDiagnosticCategory(&R, DGParentMap));
+
+ // Reasons
+ OS << ", /*LegacyReason=*/\"";
+ OS.write_escaped(DiagTextBuilder.buildForDefinition(
+ R.getValueAsDef("Reason")->getValueAsDef("Legacy"), "Value"))
+ << '"';
+
+ OS << ", /*SARIFReason=*/\"";
+ OS.write_escaped(DiagTextBuilder.buildForDefinition(
+ R.getValueAsDef("Reason")->getValueAsDef("SARIF"), "Value"))
+ << '"';
OS << ")\n";
}
}
Index: clang/unittests/Tooling/RewriterTestContext.h
===================================================================
--- clang/unittests/Tooling/RewriterTestContext.h
+++ clang/unittests/Tooling/RewriterTestContext.h
@@ -35,7 +35,7 @@
const Diagnostic &Info) override {
++NumDiagnosticsSeen;
SmallString<100> OutStr;
- Info.FormatDiagnostic(OutStr);
+ Info.FormatLegacyDiagnostic(OutStr);
llvm::errs() << OutStr;
}
unsigned NumDiagnosticsSeen;
Index: clang/unittests/Frontend/FrontendActionTest.cpp
===================================================================
--- clang/unittests/Frontend/FrontendActionTest.cpp
+++ clang/unittests/Frontend/FrontendActionTest.cpp
@@ -221,10 +221,10 @@
// Capture errors and notes. There should be one of each.
if (DiagLevel == DiagnosticsEngine::Error) {
assert(Error.empty());
- Info.FormatDiagnostic(Error);
+ Info.FormatLegacyDiagnostic(Error);
} else {
assert(Note.empty());
- Info.FormatDiagnostic(Note);
+ Info.FormatLegacyDiagnostic(Note);
}
}
SmallString<32> Error;
Index: clang/unittests/Driver/ToolChainTest.cpp
===================================================================
--- clang/unittests/Driver/ToolChainTest.cpp
+++ clang/unittests/Driver/ToolChainTest.cpp
@@ -378,10 +378,10 @@
const Diagnostic &Info) override {
if (DiagLevel == DiagnosticsEngine::Level::Error) {
Errors.emplace_back();
- Info.FormatDiagnostic(Errors.back());
+ Info.FormatLegacyDiagnostic(Errors.back());
} else {
Msgs.emplace_back();
- Info.FormatDiagnostic(Msgs.back());
+ Info.FormatLegacyDiagnostic(Msgs.back());
}
}
void clear() override {
Index: clang/unittests/Driver/SimpleDiagnosticConsumer.h
===================================================================
--- clang/unittests/Driver/SimpleDiagnosticConsumer.h
+++ clang/unittests/Driver/SimpleDiagnosticConsumer.h
@@ -21,10 +21,10 @@
const clang::Diagnostic &Info) override {
if (DiagLevel == clang::DiagnosticsEngine::Level::Error) {
Errors.emplace_back();
- Info.FormatDiagnostic(Errors.back());
+ Info.FormatLegacyDiagnostic(Errors.back());
} else {
Msgs.emplace_back();
- Info.FormatDiagnostic(Msgs.back());
+ Info.FormatLegacyDiagnostic(Msgs.back());
}
}
void clear() override {
Index: clang/tools/diagtool/DiagnosticNames.cpp
===================================================================
--- clang/tools/diagtool/DiagnosticNames.cpp
+++ clang/tools/diagtool/DiagnosticNames.cpp
@@ -28,7 +28,8 @@
// out of sync easily?
static const DiagnosticRecord BuiltinDiagnosticsByID[] = {
#define DIAG(ENUM, CLASS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \
- SHOWINSYSHEADER, SHOWINSYSMACRO, DEFER, CATEGORY) \
+ SHOWINSYSHEADER, SHOWINSYSMACRO, DEFER, CATEGORY, LEGACY_REASON, \
+ SARIF_REASON) \
{#ENUM, diag::ENUM, STR_SIZE(#ENUM, uint8_t)},
#include "clang/Basic/DiagnosticCommonKinds.inc"
#include "clang/Basic/DiagnosticCrossTUKinds.inc"
Index: clang/tools/clang-import-test/clang-import-test.cpp
===================================================================
--- clang/tools/clang-import-test/clang-import-test.cpp
+++ clang/tools/clang-import-test/clang-import-test.cpp
@@ -141,7 +141,7 @@
}
SmallString<16> DiagText;
- Info.FormatDiagnostic(DiagText);
+ Info.FormatLegacyDiagnostic(DiagText);
llvm::errs() << DiagText << '\n';
if (Info.getLocation().isValid()) {
Index: clang/tools/clang-format/ClangFormat.cpp
===================================================================
--- clang/tools/clang-format/ClangFormat.cpp
+++ clang/tools/clang-format/ClangFormat.cpp
@@ -393,7 +393,7 @@
const Diagnostic &Info) override {
SmallVector<char, 16> vec;
- Info.FormatDiagnostic(vec);
+ Info.FormatLegacyDiagnostic(vec);
errs() << "clang-format error:" << vec << "\n";
}
};
Index: clang/test/TableGen/deferred-diag.td
===================================================================
--- clang/test/TableGen/deferred-diag.td
+++ clang/test/TableGen/deferred-diag.td
@@ -5,23 +5,23 @@
// Test usage of Deferrable and NonDeferrable in diagnostics.
def test_default : Error<"This error is non-deferrable by default">;
-// CHECK-DAG: DIAG(test_default, {{.*}}SFINAE_SubstitutionFailure, false, true, true, false, 0)
+// CHECK-DAG: DIAG(test_default, {{.*}}SFINAE_SubstitutionFailure, false, true, true, false, 0, /*Reason.Legacy=*/"", /*Reason.SARIF=*/"")
def test_deferrable : Error<"This error is deferrable">, Deferrable;
-// CHECK-DAG: DIAG(test_deferrable, {{.*}} SFINAE_SubstitutionFailure, false, true, true, true, 0)
+// CHECK-DAG: DIAG(test_deferrable, {{.*}} SFINAE_SubstitutionFailure, false, true, true, true, 0, /*Reason.Legacy=*/"", /*Reason.SARIF=*/"")
def test_non_deferrable : Error<"This error is non-deferrable">, NonDeferrable;
-// CHECK-DAG: DIAG(test_non_deferrable, {{.*}} SFINAE_SubstitutionFailure, false, true, true, false, 0)
+// CHECK-DAG: DIAG(test_non_deferrable, {{.*}} SFINAE_SubstitutionFailure, false, true, true, false, 0, /*Reason.Legacy=*/"", /*Reason.SARIF=*/"")
let Deferrable = 1 in {
def test_let : Error<"This error is deferrable by let">;
-// CHECK-DAG: DIAG(test_let, {{.*}} SFINAE_SubstitutionFailure, false, true, true, true, 0)
+// CHECK-DAG: DIAG(test_let, {{.*}} SFINAE_SubstitutionFailure, false, true, true, true, 0, /*Reason.Legacy=*/"", /*Reason.SARIF=*/"")
// Make sure TextSubstitution is allowed in the let Deferrable block.
def textsub : TextSubstitution<"%select{text1|text2}0">;
def test_let2 : Error<"This error is deferrable by let %sub{textsub}0">;
-// CHECK-DAG: DIAG(test_let2, {{.*}} SFINAE_SubstitutionFailure, false, true, true, true, 0)
+// CHECK-DAG: DIAG(test_let2, {{.*}} SFINAE_SubstitutionFailure, false, true, true, true, 0, /*Reason.Legacy=*/"", /*Reason.SARIF=*/"")
}
Index: clang/test/TableGen/DiagnosticBase.inc
===================================================================
--- clang/test/TableGen/DiagnosticBase.inc
+++ clang/test/TableGen/DiagnosticBase.inc
@@ -64,10 +64,34 @@
class InGroup<DiagGroup G> { DiagGroup Group = G; }
//class IsGroup<string Name> { DiagGroup Group = DiagGroup<Name>; }
+class LegacyR<string value> {
+ string Value = value;
+}
+
+class SARIF<string value> {
+ string Value = value;
+}
+
+class DiagReason<LegacyR legacy, SARIF sarif = SARIF<legacy.Value>> {
+ // A legacy reason is a reason that is part of Clang's legacy diagnostic model,
+ // but needed to be split from the summary in order to facilitate the existence
+ // of the structured diagnostic (which will have very different text). One may
+ // observe that older versions of Clang's diagnostics are the same as
+ // `Diagnostic.Summary + Diagnostic.Reason.Legacy`. This is intentional, so as
+ // to preserve the legacy diagnostic model for the time being.
+ LegacyR Legacy = legacy;
+
+ // The SARIF reason will appear when Clang is asked to emit SARIF diagnostics,
+ // in place of Legacy. Unlike Legacy, which is a fragment of the original
+ // diagnostic from past-Clang, SARIF reasons may have completely different text
+ // to explain the problem, often from the perspective of a user.
+ SARIF SS = structured;
+}
+def NO_REASON_YET : DiagReason<LegacyR<"">>;
include "DiagnosticDocs.inc"
// All diagnostics emitted by the compiler are an indirect subclass of this.
-class Diagnostic<string summary, DiagClass DC, Severity defaultmapping> {
+class Diagnostic<string summary, DiagClass DC, Severity defaultmapping, DiagReason reason> {
/// Component is specified by the file with a big let directive.
string Component = ?;
string Summary = summary;
@@ -81,6 +105,7 @@
Severity DefaultSeverity = defaultmapping;
DiagGroup Group;
string CategoryName = "";
+ DiagReason Reason = reason;
}
class SFINAEFailure {
@@ -118,24 +143,24 @@
}
// FIXME: ExtWarn and Extension should also be SFINAEFailure by default.
-class Error<string str> : Diagnostic<str, CLASS_ERROR, SEV_Error>, SFINAEFailure {
+class Error<string str, DiagReason reason = NO_REASON_YET> : Diagnostic<str, CLASS_ERROR, SEV_Error, reason>, SFINAEFailure {
bit ShowInSystemHeader = 1;
}
// Warnings default to on (but can be default-off'd with DefaultIgnore).
// This is used for warnings about questionable code; warnings about
// accepted language extensions should use Extension or ExtWarn below instead.
-class Warning<string str> : Diagnostic<str, CLASS_WARNING, SEV_Warning>;
+class Warning<string str, DiagReason reason = NO_REASON_YET> : Diagnostic<str, CLASS_WARNING, SEV_Warning, reason>;
// Remarks can be turned on with -R flags and provide commentary, e.g. on
// optimizer decisions.
-class Remark<string str> : Diagnostic<str, CLASS_REMARK, SEV_Ignored>;
+class Remark<string str, DiagReason reason = NO_REASON_YET> : Diagnostic<str, CLASS_REMARK, SEV_Ignored, reason>;
// Extensions are warnings about accepted language extensions.
// Extension warnings are default-off but enabled by -pedantic.
-class Extension<string str> : Diagnostic<str, CLASS_EXTENSION, SEV_Ignored>;
+class Extension<string str, DiagReason reason = NO_REASON_YET> : Diagnostic<str, CLASS_EXTENSION, SEV_Ignored, reason>;
// ExtWarns are warnings about accepted language extensions.
// ExtWarn warnings are default-on.
-class ExtWarn<string str> : Diagnostic<str, CLASS_EXTENSION, SEV_Warning>;
+class ExtWarn<string str, DiagReason reason = NO_REASON_YET> : Diagnostic<str, CLASS_EXTENSION, SEV_Warning, reason>;
// Notes can provide supplementary information on errors, warnings, and remarks.
-class Note<string str> : Diagnostic<str, CLASS_NOTE, SEV_Fatal/*ignored*/>;
+class Note<string str, DiagReason reason = NO_REASON_YET> : Diagnostic<str, CLASS_NOTE, SEV_Fatal/*ignored*/, reason>;
class DefaultIgnore { Severity DefaultSeverity = SEV_Ignored; }
Index: clang/test/Frontend/sarif-reason.cpp
===================================================================
--- /dev/null
+++ clang/test/Frontend/sarif-reason.cpp
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 %s -verify -fsyntax-only
+// RUN: %clang -fsyntax-only -fdiagnostics-format=sarif %s > %t 2>&1
+// RUN: FileCheck -dump-input=always %s --input-file=%t --check-prefix=EXPECTED-ERROR --check-prefix=EXPECTED-NOTE
+
+template<class T>
+void f1();
+template<int T>
+void f2();
+template<template<class> class T>
+void f3();
+
+template<class> struct S;
+
+void g() {
+ f1<0>(); // expected-error{{no matching function for call to 'f1'}}
+ // expected-note@6{{candidate template ignored: invalid explicitly-specified argument for template parameter 'T'}}
+ f1<S>(); // expected-error{{no matching function for call to 'f1'}}
+ // expected-note@6{{candidate template ignored: invalid explicitly-specified argument for template parameter 'T'}}
+
+ f2<int>(); // expected-error{{no matching function for call to 'f2'}}
+ // expected-note@8{{candidate template ignored: invalid explicitly-specified argument for template parameter 'T'}}
+ f2<S>(); // expected-error{{no matching function for call to 'f2'}}
+ // expected-note@8{{candidate template ignored: invalid explicitly-specified argument for template parameter 'T'}}
+
+ f3<int>(); // expected-error{{no matching function for call to 'f3'}}
+ // expected-note@10{{candidate template ignored: invalid explicitly-specified argument for template parameter 'T'}}
+ f3<0>(); // expected-error{{no matching function for call to 'f3'}}
+ // expected-note@10{{candidate template ignored: invalid explicitly-specified argument for template parameter 'T'}}
+}
+
+// EXPECTED-ERROR: no matching function for call to 'f1'
+// EXPECTED-NOTE: candidate template ignored: we passed a value as our first explicit template parameter, but this candidate expects a type for 'T'
+
+// EXPECTED-ERROR: no matching function for call to 'f1'
+// EXPECTED-NOTE: candidate template ignored: we passed a class template as our first explicit template parameter, but this candidate expects a type for 'T'
+
+// EXPECTED-ERROR: no matching function for call to 'f2'
+// EXPECTED-NOTE: candidate template ignored: we passed a type as our first explicit template parameter, but this candidate expects a value for 'T'
+
+// EXPECTED-ERROR: no matching function for call to 'f2'
+// EXPECTED-NOTE: candidate template ignored: we passed a class template as our first explicit template parameter, but this candidate expects a value for 'T'
+
+// EXPECTED-ERROR: no matching function for call to 'f3'
+// EXPECTED-NOTE: candidate template ignored: we passed a type as our first explicit template parameter, but this candidate expects a class template for 'T'
+
+// EXPECTED-ERROR: no matching function for call to 'f3'
+// EXPECTED-NOTE: candidate template ignored: we passed a value as our first explicit template parameter, but this candidate expects a class template for 'T'
Index: clang/lib/Sema/SemaOverload.cpp
===================================================================
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -6511,7 +6511,7 @@
NamedDecl *ND = Function;
if (auto *SpecInfo = Function->getTemplateSpecializationInfo())
ND = SpecInfo->getTemplate();
-
+
if (ND->getFormalLinkage() == Linkage::InternalLinkage) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_module_mismatched;
@@ -11108,28 +11108,51 @@
return;
}
- case Sema::TDK_InvalidExplicitArguments:
+ case Sema::TDK_InvalidExplicitArguments: {
assert(ParamD && "no parameter found for invalid explicit arguments");
+
+ unsigned index = 1;
+ int parameter_kind = 0;
+ if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(ParamD)) {
+ index += TTP->getIndex();
+ parameter_kind = 0;
+ } else if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(ParamD)) {
+ index += NTTP->getIndex();
+ parameter_kind = 1;
+ } else {
+ index += cast<TemplateTemplateParmDecl>(ParamD)->getIndex();
+ parameter_kind = 2;
+ }
+
+ // QualType CallType = dyn_cast<CallExpr>(Fn)->getType();
+ // auto *FT = dyn_cast<FunctionTemplateDecl>(CallType);
+ // TemplateParameterList *Args = FT->getTemplateParameters();
+ // assert(Args && "We should have a full list of template arguments at this
+ // point"); assert(Args->size() >= index && "The argument list should at
+ // least be as long as the parameter we're indexing");
+
+ int arg_kind = 0;
+ // if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(Args->getParam(index -
+ // 1)))
+ // arg_kind = 0;
+ // else if (auto *NTTP =
+ // dyn_cast<NonTypeTemplateParmDecl>(Args->getParam(index - 1)))
+ // arg_kind = 1;
+ // else
+ // arg_kind = 2;
+
if (ParamD->getDeclName())
S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_explicit_arg_mismatch_named)
- << ParamD->getDeclName();
- else {
- int index = 0;
- if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ParamD))
- index = TTP->getIndex();
- else if (NonTypeTemplateParmDecl *NTTP
- = dyn_cast<NonTypeTemplateParmDecl>(ParamD))
- index = NTTP->getIndex();
- else
- index = cast<TemplateTemplateParmDecl>(ParamD)->getIndex();
+ << ParamD->getDeclName() << arg_kind << index << parameter_kind;
+ else
S.Diag(Templated->getLocation(),
diag::note_ovl_candidate_explicit_arg_mismatch_unnamed)
- << (index + 1);
- }
+ << index;
+
MaybeEmitInheritedConstructorNote(S, Found);
return;
-
+ }
case Sema::TDK_ConstraintsNotSatisfied: {
// Format the template argument list into the argument string.
SmallString<128> TemplateArgString;
@@ -13943,8 +13966,8 @@
Diag(FnDecl->getLocation(),
diag::note_ovl_ambiguous_oper_binary_reversed_self);
// Mark member== const or provide matching != to disallow reversed
- // args. Eg.
- // struct S { bool operator==(const S&); };
+ // args. Eg.
+ // struct S { bool operator==(const S&); };
// S()==S();
if (auto *MD = dyn_cast<CXXMethodDecl>(FnDecl))
if (Op == OverloadedOperatorKind::OO_EqualEqual &&
Index: clang/lib/Frontend/TextDiagnosticPrinter.cpp
===================================================================
--- clang/lib/Frontend/TextDiagnosticPrinter.cpp
+++ clang/lib/Frontend/TextDiagnosticPrinter.cpp
@@ -114,7 +114,7 @@
// Render the diagnostic message into a temporary buffer eagerly. We'll use
// this later as we print out the diagnostic to the terminal.
SmallString<100> OutStr;
- Info.FormatDiagnostic(OutStr);
+ Info.FormatLegacyDiagnostic(OutStr);
llvm::raw_svector_ostream DiagMessageStream(OutStr);
printDiagnosticOptions(DiagMessageStream, Level, Info, *DiagOpts);
Index: clang/lib/Frontend/TextDiagnosticBuffer.cpp
===================================================================
--- clang/lib/Frontend/TextDiagnosticBuffer.cpp
+++ clang/lib/Frontend/TextDiagnosticBuffer.cpp
@@ -26,7 +26,7 @@
DiagnosticConsumer::HandleDiagnostic(Level, Info);
SmallString<100> Buf;
- Info.FormatDiagnostic(Buf);
+ Info.FormatLegacyDiagnostic(Buf);
switch (Level) {
default: llvm_unreachable(
"Diagnostic not handled during diagnostic buffering!");
Index: clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
===================================================================
--- clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
+++ clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
@@ -574,7 +574,7 @@
"Received a diagnostic after we've already started teardown.");
if (IsFinishing) {
SmallString<256> diagnostic;
- Info.FormatDiagnostic(diagnostic);
+ Info.FormatLegacyDiagnostic(diagnostic);
getMetaDiags()->Report(
diag::warn_fe_serialized_diag_failure_during_finalisation)
<< diagnostic;
@@ -594,7 +594,7 @@
// Compute the diagnostic text.
State->diagBuf.clear();
- Info.FormatDiagnostic(State->diagBuf);
+ Info.FormatLegacyDiagnostic(State->diagBuf);
if (Info.getLocation().isInvalid()) {
// Special-case diagnostics with no location. We may not have entered a
Index: clang/lib/Frontend/SARIFDiagnosticPrinter.cpp
===================================================================
--- clang/lib/Frontend/SARIFDiagnosticPrinter.cpp
+++ clang/lib/Frontend/SARIFDiagnosticPrinter.cpp
@@ -58,7 +58,8 @@
// Render the diagnostic message into a temporary buffer eagerly. We'll use
// this later as we add the diagnostic to the SARIF object.
SmallString<100> OutStr;
- Info.FormatDiagnostic(OutStr);
+ Info.FormatSummary(OutStr);
+ Info.FormatSARIFReason(OutStr);
llvm::raw_svector_ostream DiagMessageStream(OutStr);
Index: clang/lib/Frontend/LogDiagnosticPrinter.cpp
===================================================================
--- clang/lib/Frontend/LogDiagnosticPrinter.cpp
+++ clang/lib/Frontend/LogDiagnosticPrinter.cpp
@@ -133,7 +133,7 @@
// Format the message.
SmallString<100> MessageStr;
- Info.FormatDiagnostic(MessageStr);
+ Info.FormatLegacyDiagnostic(MessageStr);
DE.Message = std::string(MessageStr.str());
// Set the location information.
@@ -160,4 +160,3 @@
// Record the diagnostic entry.
Entries.push_back(DE);
}
-
Index: clang/lib/Frontend/ASTUnit.cpp
===================================================================
--- clang/lib/Frontend/ASTUnit.cpp
+++ clang/lib/Frontend/ASTUnit.cpp
@@ -2382,8 +2382,8 @@
FH.RemoveRange = CharSourceRange::getCharRange(BL, EL);
}
- Result.push_back(StoredDiagnostic(SD.Level, SD.ID,
- SD.Message, Loc, Ranges, FixIts));
+ Result.push_back(StoredDiagnostic(SD.Level, SD.ID, SD.Message, SD.Reason,
+ Loc, Ranges, FixIts));
}
Result.swap(Out);
}
Index: clang/lib/Format/TokenAnalyzer.cpp
===================================================================
--- clang/lib/Format/TokenAnalyzer.cpp
+++ clang/lib/Format/TokenAnalyzer.cpp
@@ -44,7 +44,7 @@
if (DiagLevel == DiagnosticsEngine::Fatal) {
Fatal = true;
llvm::SmallVector<char, 128> Message;
- Info.FormatDiagnostic(Message);
+ Info.FormatLegacyDiagnostic(Message);
llvm::errs() << Message << "\n";
}
}
Index: clang/lib/Basic/DiagnosticIDs.cpp
===================================================================
--- clang/lib/Basic/DiagnosticIDs.cpp
+++ clang/lib/Basic/DiagnosticIDs.cpp
@@ -33,7 +33,8 @@
// platforms. See "How To Write Shared Libraries" by Ulrich Drepper.
struct StaticDiagInfoDescriptionStringTable {
#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
- SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
+ SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY, \
+ LEGACY_REASON, SARIF_REASON) \
char ENUM##_desc[sizeof(DESC)];
// clang-format off
#include "clang/Basic/DiagnosticCommonKinds.inc"
@@ -54,7 +55,8 @@
const StaticDiagInfoDescriptionStringTable StaticDiagInfoDescriptions = {
#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
- SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
+ SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY, \
+ LEGACY_REASON, SARIF_REASON) \
DESC,
// clang-format off
#include "clang/Basic/DiagnosticCommonKinds.inc"
@@ -69,7 +71,7 @@
#include "clang/Basic/DiagnosticSemaKinds.inc"
#include "clang/Basic/DiagnosticAnalysisKinds.inc"
#include "clang/Basic/DiagnosticRefactoringKinds.inc"
- // clang-format on
+// clang-format on
#undef DIAG
};
@@ -79,7 +81,8 @@
// StaticDiagInfoRec would have extra padding on 64-bit platforms.
const uint32_t StaticDiagInfoDescriptionOffsets[] = {
#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
- SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
+ SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY, \
+ LEGACY_REASON, SARIF_REASON) \
offsetof(StaticDiagInfoDescriptionStringTable, ENUM##_desc),
// clang-format off
#include "clang/Basic/DiagnosticCommonKinds.inc"
@@ -93,18 +96,158 @@
#include "clang/Basic/DiagnosticCrossTUKinds.inc"
#include "clang/Basic/DiagnosticSemaKinds.inc"
#include "clang/Basic/DiagnosticAnalysisKinds.inc"
+#include "clang/Basic/DiagnosticRefactoringKinds.inc"
+// clang-format on
+#undef DIAG
+};
+
+// Reason.Legacy
+struct StaticDiagInfoUnstructuredReasonStringTable {
+#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
+ SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY, \
+ LEGACY_REASON, SARIF_REASON) \
+ char ENUM##_legacy_reason[sizeof(LEGACY_REASON)];
+ // clang-format off
+#include "clang/Basic/DiagnosticCommonKinds.inc"
+#include "clang/Basic/DiagnosticDriverKinds.inc"
+#include "clang/Basic/DiagnosticFrontendKinds.inc"
+#include "clang/Basic/DiagnosticSerializationKinds.inc"
+#include "clang/Basic/DiagnosticLexKinds.inc"
+#include "clang/Basic/DiagnosticParseKinds.inc"
+#include "clang/Basic/DiagnosticASTKinds.inc"
+#include "clang/Basic/DiagnosticCommentKinds.inc"
+#include "clang/Basic/DiagnosticCrossTUKinds.inc"
+#include "clang/Basic/DiagnosticSemaKinds.inc"
+#include "clang/Basic/DiagnosticAnalysisKinds.inc"
#include "clang/Basic/DiagnosticRefactoringKinds.inc"
// clang-format on
#undef DIAG
};
+const StaticDiagInfoUnstructuredReasonStringTable
+ StaticDiagInfoUnstructuredReasons = {
+#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
+ SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY, \
+ LEGACY_REASON, SARIF_REASON) \
+ LEGACY_REASON,
+// clang-format off
+#include "clang/Basic/DiagnosticCommonKinds.inc"
+#include "clang/Basic/DiagnosticDriverKinds.inc"
+#include "clang/Basic/DiagnosticFrontendKinds.inc"
+#include "clang/Basic/DiagnosticSerializationKinds.inc"
+#include "clang/Basic/DiagnosticLexKinds.inc"
+#include "clang/Basic/DiagnosticParseKinds.inc"
+#include "clang/Basic/DiagnosticASTKinds.inc"
+#include "clang/Basic/DiagnosticCommentKinds.inc"
+#include "clang/Basic/DiagnosticCrossTUKinds.inc"
+#include "clang/Basic/DiagnosticSemaKinds.inc"
+#include "clang/Basic/DiagnosticAnalysisKinds.inc"
+#include "clang/Basic/DiagnosticRefactoringKinds.inc"
+// clang-format on
+#undef DIAG
+};
+
+// Stored separately from StaticDiagInfoRec to pack better. Otherwise,
+// StaticDiagInfoRec would have extra padding on 64-bit platforms.
+const uint32_t StaticDiagInfoUnstructuredReasonOffsets[] = {
+#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
+ SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY, \
+ LEGACY_REASON, SARIF_REASON) \
+ offsetof(StaticDiagInfoUnstructuredReasonStringTable, ENUM##_legacy_reason),
+// clang-format off
+#include "clang/Basic/DiagnosticCommonKinds.inc"
+#include "clang/Basic/DiagnosticDriverKinds.inc"
+#include "clang/Basic/DiagnosticFrontendKinds.inc"
+#include "clang/Basic/DiagnosticSerializationKinds.inc"
+#include "clang/Basic/DiagnosticLexKinds.inc"
+#include "clang/Basic/DiagnosticParseKinds.inc"
+#include "clang/Basic/DiagnosticASTKinds.inc"
+#include "clang/Basic/DiagnosticCommentKinds.inc"
+#include "clang/Basic/DiagnosticCrossTUKinds.inc"
+#include "clang/Basic/DiagnosticSemaKinds.inc"
+#include "clang/Basic/DiagnosticAnalysisKinds.inc"
+#include "clang/Basic/DiagnosticRefactoringKinds.inc"
+// clang-format on
+#undef DIAG
+};
+
+// Reason.SARIF
+struct StaticDiagInfoStructuredReasonStringTable {
+#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
+ SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY, \
+ LEGACY_REASON, SARIF_REASON) \
+ char ENUM##_sarif_reason[sizeof(SARIF_REASON)];
+ // clang-format off
+#include "clang/Basic/DiagnosticCommonKinds.inc"
+#include "clang/Basic/DiagnosticDriverKinds.inc"
+#include "clang/Basic/DiagnosticFrontendKinds.inc"
+#include "clang/Basic/DiagnosticSerializationKinds.inc"
+#include "clang/Basic/DiagnosticLexKinds.inc"
+#include "clang/Basic/DiagnosticParseKinds.inc"
+#include "clang/Basic/DiagnosticASTKinds.inc"
+#include "clang/Basic/DiagnosticCommentKinds.inc"
+#include "clang/Basic/DiagnosticCrossTUKinds.inc"
+#include "clang/Basic/DiagnosticSemaKinds.inc"
+#include "clang/Basic/DiagnosticAnalysisKinds.inc"
+#include "clang/Basic/DiagnosticRefactoringKinds.inc"
+ // clang-format on
+#undef DIAG
+};
+
+const StaticDiagInfoStructuredReasonStringTable
+ StaticDiagInfoStructuredReasons = {
+#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
+ SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY, \
+ LEGACY_REASON, SARIF_REASON) \
+ SARIF_REASON,
+// clang-format off
+#include "clang/Basic/DiagnosticCommonKinds.inc"
+#include "clang/Basic/DiagnosticDriverKinds.inc"
+#include "clang/Basic/DiagnosticFrontendKinds.inc"
+#include "clang/Basic/DiagnosticSerializationKinds.inc"
+#include "clang/Basic/DiagnosticLexKinds.inc"
+#include "clang/Basic/DiagnosticParseKinds.inc"
+#include "clang/Basic/DiagnosticASTKinds.inc"
+#include "clang/Basic/DiagnosticCommentKinds.inc"
+#include "clang/Basic/DiagnosticCrossTUKinds.inc"
+#include "clang/Basic/DiagnosticSemaKinds.inc"
+#include "clang/Basic/DiagnosticAnalysisKinds.inc"
+#include "clang/Basic/DiagnosticRefactoringKinds.inc"
+// clang-format on
+#undef DIAG
+};
+
+// Stored separately from StaticDiagInfoRec to pack better. Otherwise,
+// StaticDiagInfoRec would have extra padding on 64-bit platforms.
+const uint32_t StaticDiagInfoStructuredReasonOffsets[] = {
+#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
+ SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY, \
+ LEGACY_REASON, SARIF_REASON) \
+ offsetof(StaticDiagInfoStructuredReasonStringTable, ENUM##_sarif_reason),
+// clang-format off
+#include "clang/Basic/DiagnosticCommonKinds.inc"
+#include "clang/Basic/DiagnosticDriverKinds.inc"
+#include "clang/Basic/DiagnosticFrontendKinds.inc"
+#include "clang/Basic/DiagnosticSerializationKinds.inc"
+#include "clang/Basic/DiagnosticLexKinds.inc"
+#include "clang/Basic/DiagnosticParseKinds.inc"
+#include "clang/Basic/DiagnosticASTKinds.inc"
+#include "clang/Basic/DiagnosticCommentKinds.inc"
+#include "clang/Basic/DiagnosticCrossTUKinds.inc"
+#include "clang/Basic/DiagnosticSemaKinds.inc"
+#include "clang/Basic/DiagnosticAnalysisKinds.inc"
+#include "clang/Basic/DiagnosticRefactoringKinds.inc"
+// clang-format on
+#undef DIAG
+};
+
// Diagnostic classes.
enum {
- CLASS_NOTE = 0x01,
- CLASS_REMARK = 0x02,
- CLASS_WARNING = 0x03,
- CLASS_EXTENSION = 0x04,
- CLASS_ERROR = 0x05
+ CLASS_NOTE = 0x01,
+ CLASS_REMARK = 0x02,
+ CLASS_WARNING = 0x03,
+ CLASS_EXTENSION = 0x04,
+ CLASS_ERROR = 0x05
};
struct StaticDiagInfoRec {
@@ -121,18 +264,35 @@
uint16_t Deferrable : 1;
uint16_t DescriptionLen;
+ uint16_t UnstructuredReasonLen;
+ uint16_t StructuredReasonLen;
- unsigned getOptionGroupIndex() const {
- return OptionGroupIndex;
- }
+ unsigned getOptionGroupIndex() const { return OptionGroupIndex; }
StringRef getDescription() const {
size_t MyIndex = this - &StaticDiagInfo[0];
uint32_t StringOffset = StaticDiagInfoDescriptionOffsets[MyIndex];
- const char* Table = reinterpret_cast<const char*>(&StaticDiagInfoDescriptions);
+ const char *Table =
+ reinterpret_cast<const char *>(&StaticDiagInfoDescriptions);
return StringRef(&Table[StringOffset], DescriptionLen);
}
+ StringRef getUnstructuredReason() const {
+ size_t MyIndex = this - &StaticDiagInfo[0];
+ uint32_t StringOffset = StaticDiagInfoUnstructuredReasonOffsets[MyIndex];
+ const char *Table =
+ reinterpret_cast<const char *>(&StaticDiagInfoUnstructuredReasons);
+ return StringRef(&Table[StringOffset], UnstructuredReasonLen);
+ }
+
+ StringRef getStructuredReason() const {
+ size_t MyIndex = this - &StaticDiagInfo[0];
+ uint32_t StringOffset = StaticDiagInfoStructuredReasonOffsets[MyIndex];
+ const char *Table =
+ reinterpret_cast<const char *>(&StaticDiagInfoStructuredReasons);
+ return StringRef(&Table[StringOffset], StructuredReasonLen);
+ }
+
diag::Flavor getFlavor() const {
return Class == CLASS_REMARK ? diag::Flavor::Remark
: diag::Flavor::WarningOrError;
@@ -171,7 +331,7 @@
const StaticDiagInfoRec StaticDiagInfo[] = {
// clang-format off
#define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
- SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
+ SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY, LEGACY_REASON, SARIF_REASON) \
{ \
diag::ENUM, \
DEFAULT_SEVERITY, \
@@ -183,7 +343,9 @@
SHOWINSYSMACRO, \
GROUP, \
DEFERRABLE, \
- STR_SIZE(DESC, uint16_t)},
+ STR_SIZE(DESC, uint16_t), \
+ STR_SIZE(LEGACY_REASON, uint16_t), \
+ STR_SIZE(SARIF_REASON, uint16_t)},
#include "clang/Basic/DiagnosticCommonKinds.inc"
#include "clang/Basic/DiagnosticDriverKinds.inc"
#include "clang/Basic/DiagnosticFrontendKinds.inc"
@@ -222,22 +384,22 @@
// memory at all.
unsigned Offset = 0;
unsigned ID = DiagID - DIAG_START_COMMON - 1;
-#define CATEGORY(NAME, PREV) \
- if (DiagID > DIAG_START_##NAME) { \
- Offset += NUM_BUILTIN_##PREV##_DIAGNOSTICS - DIAG_START_##PREV - 1; \
- ID -= DIAG_START_##NAME - DIAG_START_##PREV; \
+#define CATEGORY(NAME, PREV) \
+ if (DiagID > DIAG_START_##NAME) { \
+ Offset += NUM_BUILTIN_##PREV##_DIAGNOSTICS - DIAG_START_##PREV - 1; \
+ ID -= DIAG_START_##NAME - DIAG_START_##PREV; \
}
-CATEGORY(DRIVER, COMMON)
-CATEGORY(FRONTEND, DRIVER)
-CATEGORY(SERIALIZATION, FRONTEND)
-CATEGORY(LEX, SERIALIZATION)
-CATEGORY(PARSE, LEX)
-CATEGORY(AST, PARSE)
-CATEGORY(COMMENT, AST)
-CATEGORY(CROSSTU, COMMENT)
-CATEGORY(SEMA, CROSSTU)
-CATEGORY(ANALYSIS, SEMA)
-CATEGORY(REFACTORING, ANALYSIS)
+ CATEGORY(DRIVER, COMMON)
+ CATEGORY(FRONTEND, DRIVER)
+ CATEGORY(SERIALIZATION, FRONTEND)
+ CATEGORY(LEX, SERIALIZATION)
+ CATEGORY(PARSE, LEX)
+ CATEGORY(AST, PARSE)
+ CATEGORY(COMMENT, AST)
+ CATEGORY(CROSSTU, COMMENT)
+ CATEGORY(SEMA, CROSSTU)
+ CATEGORY(ANALYSIS, SEMA)
+ CATEGORY(REFACTORING, ANALYSIS)
#undef CATEGORY
// Avoid out of bounds reads.
@@ -281,16 +443,14 @@
}
namespace {
- // The diagnostic category names.
- struct StaticDiagCategoryRec {
- const char *NameStr;
- uint8_t NameLen;
+// The diagnostic category names.
+struct StaticDiagCategoryRec {
+ const char *NameStr;
+ uint8_t NameLen;
- StringRef getName() const {
- return StringRef(NameStr, NameLen);
- }
- };
-}
+ StringRef getName() const { return StringRef(NameStr, NameLen); }
+};
+} // namespace
// Unfortunately, the split between DiagnosticIDs and Diagnostic is not
// particularly clean, but for now we just implement this method here so we can
@@ -309,11 +469,10 @@
static const StaticDiagCategoryRec CategoryNameTable[] = {
#define GET_CATEGORY_TABLE
-#define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) },
+#define CATEGORY(X, ENUM) {X, STR_SIZE(X, uint8_t)},
#include "clang/Basic/DiagnosticGroups.inc"
#undef GET_CATEGORY_TABLE
- { nullptr, 0 }
-};
+ {nullptr, 0}};
/// getNumberOfCategories - Return the number of categories
unsigned DiagnosticIDs::getNumberOfCategories() {
@@ -325,12 +484,10 @@
/// invalid.
StringRef DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID) {
if (CategoryID >= getNumberOfCategories())
- return StringRef();
+ return StringRef();
return CategoryNameTable[CategoryID].getName();
}
-
-
DiagnosticIDs::SFINAEResponse
DiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID) {
if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
@@ -357,47 +514,82 @@
//===----------------------------------------------------------------------===//
namespace clang {
- namespace diag {
- class CustomDiagInfo {
- typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc;
- std::vector<DiagDesc> DiagInfo;
- std::map<DiagDesc, unsigned> DiagIDs;
- public:
-
- /// getDescription - Return the description of the specified custom
- /// diagnostic.
- StringRef getDescription(unsigned DiagID) const {
- assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() &&
- "Invalid diagnostic ID");
- return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second;
- }
-
- /// getLevel - Return the level of the specified custom diagnostic.
- DiagnosticIDs::Level getLevel(unsigned DiagID) const {
- assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() &&
- "Invalid diagnostic ID");
- return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first;
- }
-
- unsigned getOrCreateDiagID(DiagnosticIDs::Level L, StringRef Message,
- DiagnosticIDs &Diags) {
- DiagDesc D(L, std::string(Message));
- // Check to see if it already exists.
- std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
- if (I != DiagIDs.end() && I->first == D)
- return I->second;
-
- // If not, assign a new ID.
- unsigned ID = DiagInfo.size()+DIAG_UPPER_LIMIT;
- DiagIDs.insert(std::make_pair(D, ID));
- DiagInfo.push_back(D);
- return ID;
- }
- };
-
- } // end diag namespace
-} // end clang namespace
+namespace diag {
+class CustomDiagInfo {
+ struct DiagDesc {
+ DiagnosticIDs::Level Level;
+ std::string Message;
+ DiagnosticReason Reason;
+
+ // FIXME(spaceship): default when C++20 becomes the default
+ bool operator==(const DiagDesc &Other) const {
+ return std::tie(Level, Message, Reason) ==
+ std::tie(Other.Level, Other.Message, Other.Reason);
+ }
+ bool operator!=(const DiagDesc &Other) const { return !(*this == Other); }
+
+ bool operator<(const DiagDesc &Other) const {
+ return std::tie(Level, Message, Reason) <
+ std::tie(Other.Level, Other.Message, Other.Reason);
+ }
+
+ bool operator>(const DiagDesc &Other) const { return Other < *this; }
+
+ bool operator<=(const DiagDesc &Other) const { return !(Other < *this); }
+
+ bool operator>=(const DiagDesc &Other) const { return !(*this < Other); }
+ };
+ std::vector<DiagDesc> DiagInfo;
+ std::map<DiagDesc, unsigned> DiagIDs;
+
+ bool IsValidDiagnosticID(unsigned DiagID) const {
+ return DiagID - DIAG_UPPER_LIMIT < DiagInfo.size();
+ }
+
+public:
+ /// getDescription - Return the description of the specified custom
+ /// diagnostic.
+ StringRef getDescription(unsigned DiagID) const {
+ assert(IsValidDiagnosticID(DiagID) && "Invalid diagnostic ID");
+ return DiagInfo[DiagID - DIAG_UPPER_LIMIT].Message;
+ }
+
+ StringRef getLegacyReason(unsigned DiagID) const {
+ assert(IsValidDiagnosticID(DiagID) && "Invalid diagnostic ID");
+ return DiagInfo[DiagID - DIAG_UPPER_LIMIT].Reason.Legacy.Value;
+ }
+
+ StringRef getSARIFReason(unsigned DiagID) const {
+ assert(IsValidDiagnosticID(DiagID) && "Invalid diagnostic ID");
+ return DiagInfo[DiagID - DIAG_UPPER_LIMIT].Reason.SARIF;
+ }
+
+ /// getLevel - Return the level of the specified custom diagnostic.
+ DiagnosticIDs::Level getLevel(unsigned DiagID) const {
+ assert(IsValidDiagnosticID(DiagID) && "Invalid diagnostic ID");
+ return DiagInfo[DiagID - DIAG_UPPER_LIMIT].Level;
+ }
+
+ unsigned getOrCreateDiagID(DiagnosticIDs::Level L, StringRef Message,
+ const DiagnosticReason &Reason,
+ DiagnosticIDs &Diags) {
+ DiagDesc D{L, std::string(Message), Reason};
+ // Check to see if it already exists.
+ std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
+ if (I != DiagIDs.end() && I->first == D)
+ return I->second;
+
+ // If not, assign a new ID.
+ unsigned ID = DiagInfo.size() + DIAG_UPPER_LIMIT;
+ DiagIDs.insert(std::make_pair(D, ID));
+ DiagInfo.push_back(D);
+ return ID;
+ }
+};
+
+} // namespace diag
+} // namespace clang
//===----------------------------------------------------------------------===//
// Common Diagnostic implementation
@@ -413,13 +605,13 @@
///
/// \param FormatString A fixed diagnostic format string that will be hashed and
/// mapped to a unique DiagID.
-unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef FormatString) {
+unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef FormatString,
+ const DiagnosticReason &Reason) {
if (!CustomDiagInfo)
CustomDiagInfo.reset(new diag::CustomDiagInfo());
- return CustomDiagInfo->getOrCreateDiagID(L, FormatString, *this);
+ return CustomDiagInfo->getOrCreateDiagID(L, FormatString, Reason, *this);
}
-
/// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic
/// level of the specified diagnostic ID is a Warning or Extension.
/// This only works on builtin diagnostics, not custom ones, and is not legal to
@@ -433,7 +625,7 @@
/// Note.
bool DiagnosticIDs::isBuiltinNote(unsigned DiagID) {
return DiagID < diag::DIAG_UPPER_LIMIT &&
- getBuiltinDiagClass(DiagID) == CLASS_NOTE;
+ getBuiltinDiagClass(DiagID) == CLASS_NOTE;
}
/// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
@@ -442,7 +634,7 @@
/// which case -pedantic enables it) or treated as a warning/error by default.
///
bool DiagnosticIDs::isBuiltinExtensionDiag(unsigned DiagID,
- bool &EnabledByDefault) {
+ bool &EnabledByDefault) {
if (DiagID >= diag::DIAG_UPPER_LIMIT ||
getBuiltinDiagClass(DiagID) != CLASS_EXTENSION)
return false;
@@ -468,6 +660,20 @@
return CustomDiagInfo->getDescription(DiagID);
}
+StringRef DiagnosticIDs::getLegacyReason(unsigned DiagID) const {
+ if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
+ return Info->getUnstructuredReason();
+ assert(CustomDiagInfo && "Invalid CustomDiagInfo");
+ return CustomDiagInfo->getLegacyReason(DiagID);
+}
+
+StringRef DiagnosticIDs::getSARIFReason(unsigned DiagID) const {
+ if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
+ return Info->getStructuredReason();
+ assert(CustomDiagInfo && "Invalid CustomDiagInfo");
+ return CustomDiagInfo->getSARIFReason(DiagID);
+}
+
static DiagnosticIDs::Level toLevel(diag::Severity SV) {
switch (SV) {
case diag::Severity::Ignored:
@@ -497,7 +703,8 @@
}
unsigned DiagClass = getBuiltinDiagClass(DiagID);
- if (DiagClass == CLASS_NOTE) return DiagnosticIDs::Note;
+ if (DiagClass == CLASS_NOTE)
+ return DiagnosticIDs::Note;
return toLevel(getDiagnosticSeverity(DiagID, Loc, Diag));
}
@@ -603,19 +810,19 @@
#undef GET_DIAG_ARRAYS
namespace {
- struct WarningOption {
- uint16_t NameOffset;
- uint16_t Members;
- uint16_t SubGroups;
- StringRef Documentation;
-
- // String is stored with a pascal-style length byte.
- StringRef getName() const {
- return StringRef(DiagGroupNames + NameOffset + 1,
- DiagGroupNames[NameOffset]);
- }
- };
-}
+struct WarningOption {
+ uint16_t NameOffset;
+ uint16_t Members;
+ uint16_t SubGroups;
+ StringRef Documentation;
+
+ // String is stored with a pascal-style length byte.
+ StringRef getName() const {
+ return StringRef(DiagGroupNames + NameOffset + 1,
+ DiagGroupNames[NameOffset]);
+ }
+};
+} // namespace
// Second the table of options, sorted by name for fast binary lookup.
static const WarningOption OptionTable[] = {
@@ -694,15 +901,15 @@
// Add the members of the subgroups.
const int16_t *SubGroups = DiagSubGroups + Group->SubGroups;
for (; *SubGroups != (int16_t)-1; ++SubGroups)
- NotFound &= getDiagnosticsInGroup(Flavor, &OptionTable[(short)*SubGroups],
- Diags);
+ NotFound &=
+ getDiagnosticsInGroup(Flavor, &OptionTable[(short)*SubGroups], Diags);
return NotFound;
}
-bool
-DiagnosticIDs::getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group,
- SmallVectorImpl<diag::kind> &Diags) const {
+bool DiagnosticIDs::getDiagnosticsInGroup(
+ diag::Flavor Flavor, StringRef Group,
+ SmallVectorImpl<diag::kind> &Diags) const {
if (llvm::Optional<diag::Group> G = getGroupForWarningOption(Group))
return ::getDiagnosticsInGroup(
Flavor, &OptionTable[static_cast<unsigned>(*G)], Diags);
@@ -756,8 +963,8 @@
// Figure out the diagnostic level of this message.
unsigned DiagID = Info.getID();
- DiagnosticIDs::Level DiagLevel
- = getDiagnosticLevel(DiagID, Info.getLocation(), Diag);
+ DiagnosticIDs::Level DiagLevel =
+ getDiagnosticLevel(DiagID, Info.getLocation(), Diag);
// Update counts for DiagnosticErrorTrap even if a fatal error occurred
// or diagnostics are suppressed.
@@ -832,7 +1039,8 @@
void DiagnosticIDs::EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const {
Diagnostic Info(&Diag);
- assert(DiagLevel != DiagnosticIDs::Ignored && "Cannot emit ignored diagnostics!");
+ assert(DiagLevel != DiagnosticIDs::Ignored &&
+ "Cannot emit ignored diagnostics!");
Diag.Client->HandleDiagnostic((DiagnosticsEngine::Level)DiagLevel, Info);
if (Diag.Client->IncludeInDiagnosticCounts()) {
Index: clang/lib/Basic/Diagnostic.cpp
===================================================================
--- clang/lib/Basic/Diagnostic.cpp
+++ clang/lib/Basic/Diagnostic.cpp
@@ -788,11 +788,7 @@
}
}
-/// FormatDiagnostic - Format this diagnostic into a string, substituting the
-/// formal arguments into the %0 slots. The result is appended onto the Str
-/// array.
-void Diagnostic::
-FormatDiagnostic(SmallVectorImpl<char> &OutStr) const {
+void Diagnostic::FormatSummary(SmallVectorImpl<char> &OutStr) const {
if (!StoredDiagMessage.empty()) {
OutStr.append(StoredDiagMessage.begin(), StoredDiagMessage.end());
return;
@@ -804,6 +800,21 @@
FormatDiagnostic(Diag.begin(), Diag.end(), OutStr);
}
+void Diagnostic::FormatLegacyReason(SmallVectorImpl<char> &OutStr) const {
+ StringRef Diag = getDiags()->getDiagnosticIDs()->getLegacyReason(getID());
+ FormatDiagnostic(Diag.begin(), Diag.end(), OutStr);
+}
+
+void Diagnostic::FormatSARIFReason(SmallVectorImpl<char> &OutStr) const {
+ StringRef Diag = getDiags()->getDiagnosticIDs()->getSARIFReason(getID());
+ FormatDiagnostic(Diag.begin(), Diag.end(), OutStr);
+}
+
+void Diagnostic::FormatLegacyDiagnostic(SmallVectorImpl<char> &OutStr) const {
+ FormatSummary(OutStr);
+ FormatLegacyReason(OutStr);
+}
+
/// pushEscapedString - Append Str to the diagnostic buffer,
/// escaping non-printable characters and ill-formed code unit sequences.
static void pushEscapedString(StringRef Str, SmallVectorImpl<char> &OutStr) {
@@ -1154,8 +1165,8 @@
}
StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
- StringRef Message)
- : ID(ID), Level(Level), Message(Message) {}
+ StringRef Message, DiagnosticReason Reason)
+ : ID(ID), Level(Level), Message(Message), Reason(std::move(Reason)) {}
StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level,
const Diagnostic &Info)
@@ -1165,20 +1176,20 @@
if (Info.getLocation().isValid())
Loc = FullSourceLoc(Info.getLocation(), Info.getSourceManager());
SmallString<64> Message;
- Info.FormatDiagnostic(Message);
+ Info.FormatSummary(Message);
this->Message.assign(Message.begin(), Message.end());
this->Ranges.assign(Info.getRanges().begin(), Info.getRanges().end());
this->FixIts.assign(Info.getFixItHints().begin(), Info.getFixItHints().end());
}
StoredDiagnostic::StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
- StringRef Message, FullSourceLoc Loc,
+ StringRef Message, DiagnosticReason Reason,
+ FullSourceLoc Loc,
ArrayRef<CharSourceRange> Ranges,
ArrayRef<FixItHint> FixIts)
- : ID(ID), Level(Level), Loc(Loc), Message(Message),
- Ranges(Ranges.begin(), Ranges.end()), FixIts(FixIts.begin(), FixIts.end())
-{
-}
+ : ID(ID), Level(Level), Loc(Loc), Message(Message), Reason(Reason),
+ Ranges(Ranges.begin(), Ranges.end()),
+ FixIts(FixIts.begin(), FixIts.end()) {}
llvm::raw_ostream &clang::operator<<(llvm::raw_ostream &OS,
const StoredDiagnostic &SD) {
Index: clang/include/clang/Frontend/ASTUnit.h
===================================================================
--- clang/include/clang/Frontend/ASTUnit.h
+++ clang/include/clang/Frontend/ASTUnit.h
@@ -99,6 +99,7 @@
unsigned ID;
DiagnosticsEngine::Level Level;
std::string Message;
+ DiagnosticReason Reason;
std::string Filename;
unsigned LocOffset;
std::vector<std::pair<unsigned, unsigned>> Ranges;
Index: clang/include/clang/Basic/PartialDiagnostic.h
===================================================================
--- clang/include/clang/Basic/PartialDiagnostic.h
+++ clang/include/clang/Basic/PartialDiagnostic.h
@@ -170,7 +170,8 @@
// messing with the state of the diagnostics engine.
DiagnosticBuilder DB(Diags.Report(getDiagID()));
Emit(DB);
- Diagnostic(&Diags).FormatDiagnostic(Buf);
+ Diagnostic Info(&Diags);
+ Info.FormatLegacyDiagnostic(Buf);
DB.Clear();
Diags.Clear();
}
Index: clang/include/clang/Basic/DiagnosticSerialization.h
===================================================================
--- clang/include/clang/Basic/DiagnosticSerialization.h
+++ clang/include/clang/Basic/DiagnosticSerialization.h
@@ -15,7 +15,8 @@
namespace diag {
enum {
#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \
- SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
+ SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY, \
+ LEGACY_REASON, SARIF_REASON) \
ENUM,
#define SERIALIZATIONSTART
#include "clang/Basic/DiagnosticSerializationKinds.inc"
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4515,8 +4515,12 @@
"of conflicting types for parameter %0 (%1 of type $ vs. %3 of type $)|"
"%1 and %3 of conflicting types for parameter %0}2,4">;
def note_ovl_candidate_explicit_arg_mismatch_named : Note<
- "candidate template ignored: invalid explicitly-specified argument "
- "for template parameter %0">;
+ "candidate template ignored: ",
+ DiagReason<
+ Legacy<"invalid explicitly-specified argument for template parameter %0">,
+ SARIF<"we passed a %select{type|value|class template}1 as our %ordinal2 "
+ "explicit template parameter, but this candidate expects a "
+ "%select{type|value|class template}3 for template parameter %0">>>;
def note_ovl_candidate_unsatisfied_constraints : Note<
"candidate template ignored: constraints not satisfied%0">;
def note_ovl_candidate_explicit_arg_mismatch_unnamed : Note<
Index: clang/include/clang/Basic/DiagnosticSema.h
===================================================================
--- clang/include/clang/Basic/DiagnosticSema.h
+++ clang/include/clang/Basic/DiagnosticSema.h
@@ -15,7 +15,8 @@
namespace diag {
enum {
#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \
- SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
+ SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY, \
+ LEGACY_REASON, SARIF_REASON) \
ENUM,
#define SEMASTART
#include "clang/Basic/DiagnosticSemaKinds.inc"
Index: clang/include/clang/Basic/DiagnosticRefactoring.h
===================================================================
--- clang/include/clang/Basic/DiagnosticRefactoring.h
+++ clang/include/clang/Basic/DiagnosticRefactoring.h
@@ -15,7 +15,8 @@
namespace diag {
enum {
#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \
- SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
+ SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY, \
+ LEGACY_REASON, SARIF_REASON) \
ENUM,
#define REFACTORINGSTART
#include "clang/Basic/DiagnosticRefactoringKinds.inc"
Index: clang/include/clang/Basic/DiagnosticParse.h
===================================================================
--- clang/include/clang/Basic/DiagnosticParse.h
+++ clang/include/clang/Basic/DiagnosticParse.h
@@ -15,7 +15,8 @@
namespace diag {
enum {
#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \
- SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
+ SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY, \
+ LEGACY_REASON, SARIF_REASON) \
ENUM,
#define PARSESTART
#include "clang/Basic/DiagnosticParseKinds.inc"
Index: clang/include/clang/Basic/DiagnosticLex.h
===================================================================
--- clang/include/clang/Basic/DiagnosticLex.h
+++ clang/include/clang/Basic/DiagnosticLex.h
@@ -15,7 +15,8 @@
namespace diag {
enum {
#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \
- SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
+ SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY, \
+ LEGACY_REASON, SARIF_REASON) \
ENUM,
#define LEXSTART
#include "clang/Basic/DiagnosticLexKinds.inc"
Index: clang/include/clang/Basic/DiagnosticIDs.h
===================================================================
--- clang/include/clang/Basic/DiagnosticIDs.h
+++ clang/include/clang/Basic/DiagnosticIDs.h
@@ -66,9 +66,10 @@
// Get typedefs for common diagnostics.
enum {
-#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, CATEGORY, \
- NOWERROR, SHOWINSYSHEADER, SHOWINSYSMACRO, DEFFERABLE) \
- ENUM,
+#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, CATEGORY, \
+ NOWERROR, SHOWINSYSHEADER, SHOWINSYSMACRO, DEFFERABLE, \
+ LEGACY_REASON, SARIF_REASON) \
+ ENUM,
#define COMMONSTART
#include "clang/Basic/DiagnosticCommonKinds.inc"
NUM_BUILTIN_COMMON_DIAGNOSTICS
@@ -160,6 +161,46 @@
}
};
+struct LegacyR {
+ llvm::StringLiteral Value = "";
+
+ // FIXME(spaceship): default when C++20 becomes the default
+ bool operator==(const LegacyR &Other) const { return Value == Other.Value; }
+ bool operator!=(const LegacyR &Other) const { return !(*this == Other); }
+ bool operator<(const LegacyR &Other) const { return Value < Other.Value; }
+ bool operator>(const LegacyR &Other) const { return Other < *this; }
+ bool operator<=(const LegacyR &Other) const { return !(Other < *this); }
+ bool operator>=(const LegacyR &Other) const { return !(*this < Other); }
+};
+
+struct DiagnosticReason {
+ LegacyR Legacy;
+ llvm::StringLiteral SARIF = "";
+
+ // FIXME(spaceship): default when C++20 becomes the default
+ bool operator==(const DiagnosticReason &Other) const {
+ return Legacy == Other.Legacy && SARIF == Other.SARIF;
+ }
+
+ bool operator!=(const DiagnosticReason &Other) const {
+ return !(*this == Other);
+ }
+
+ bool operator<(const DiagnosticReason &Other) const {
+ return Legacy < Other.Legacy && SARIF < Other.SARIF;
+ }
+
+ bool operator>(const DiagnosticReason &Other) const { return Other < *this; }
+
+ bool operator<=(const DiagnosticReason &Other) const {
+ return !(Other < *this);
+ }
+
+ bool operator>=(const DiagnosticReason &Other) const {
+ return !(*this < Other);
+ }
+};
+
/// Used for handling and querying diagnostic IDs.
///
/// Can be used and shared by multiple Diagnostics for multiple translation units.
@@ -187,7 +228,8 @@
// FIXME: Replace this function with a create-only facilty like
// createCustomDiagIDFromFormatString() to enforce safe usage. At the time of
// writing, nearly all callers of this function were invalid.
- unsigned getCustomDiagID(Level L, StringRef FormatString);
+ unsigned getCustomDiagID(Level L, StringRef FormatString,
+ const DiagnosticReason &Reason = {});
//===--------------------------------------------------------------------===//
// Diagnostic classification and reporting interfaces.
@@ -196,6 +238,12 @@
/// Given a diagnostic ID, return a description of the issue.
StringRef getDescription(unsigned DiagID) const;
+ /// Given a diagnostic ID, return the issue's legacy reason.
+ StringRef getLegacyReason(unsigned DiagID) const;
+
+ /// Given a diagnostic ID, return the issue's SARIF reason.
+ StringRef getSARIFReason(unsigned DiagID) const;
+
/// Return true if the unmapped diagnostic levelof the specified
/// diagnostic ID is a Warning or Extension.
///
Index: clang/include/clang/Basic/DiagnosticFrontend.h
===================================================================
--- clang/include/clang/Basic/DiagnosticFrontend.h
+++ clang/include/clang/Basic/DiagnosticFrontend.h
@@ -15,7 +15,8 @@
namespace diag {
enum {
#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \
- SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
+ SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY, \
+ LEGACY_REASON, SARIF_REASON) \
ENUM,
#define FRONTENDSTART
#include "clang/Basic/DiagnosticFrontendKinds.inc"
Index: clang/include/clang/Basic/DiagnosticDriver.h
===================================================================
--- clang/include/clang/Basic/DiagnosticDriver.h
+++ clang/include/clang/Basic/DiagnosticDriver.h
@@ -15,7 +15,8 @@
namespace diag {
enum {
#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \
- SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
+ SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY, \
+ LEGACY_REASON, SARIF_REASON) \
ENUM,
#define DRIVERSTART
#include "clang/Basic/DiagnosticDriverKinds.inc"
Index: clang/include/clang/Basic/DiagnosticCrossTU.h
===================================================================
--- clang/include/clang/Basic/DiagnosticCrossTU.h
+++ clang/include/clang/Basic/DiagnosticCrossTU.h
@@ -15,7 +15,8 @@
namespace diag {
enum {
#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \
- SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
+ SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY, \
+ LEGACY_REASON, SARIF_REASON) \
ENUM,
#define CROSSTUSTART
#include "clang/Basic/DiagnosticCrossTUKinds.inc"
Index: clang/include/clang/Basic/DiagnosticComment.h
===================================================================
--- clang/include/clang/Basic/DiagnosticComment.h
+++ clang/include/clang/Basic/DiagnosticComment.h
@@ -15,7 +15,8 @@
namespace diag {
enum {
#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \
- SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
+ SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY, \
+ LEGACY_REASON, SARIF_REASON) \
ENUM,
#define COMMENTSTART
#include "clang/Basic/DiagnosticCommentKinds.inc"
Index: clang/include/clang/Basic/DiagnosticAnalysis.h
===================================================================
--- clang/include/clang/Basic/DiagnosticAnalysis.h
+++ clang/include/clang/Basic/DiagnosticAnalysis.h
@@ -15,7 +15,8 @@
namespace diag {
enum {
#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \
- SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
+ SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY, \
+ LEGACY_REASON, SARIF_REASON) \
ENUM,
#define ANALYSISSTART
#include "clang/Basic/DiagnosticAnalysisKinds.inc"
Index: clang/include/clang/Basic/DiagnosticAST.h
===================================================================
--- clang/include/clang/Basic/DiagnosticAST.h
+++ clang/include/clang/Basic/DiagnosticAST.h
@@ -15,7 +15,8 @@
namespace diag {
enum {
#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \
- SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
+ SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY, \
+ LEGACY_REASON, SARIF_REASON) \
ENUM,
#define ASTSTART
#include "clang/Basic/DiagnosticASTKinds.inc"
Index: clang/include/clang/Basic/Diagnostic.td
===================================================================
--- clang/include/clang/Basic/Diagnostic.td
+++ clang/include/clang/Basic/Diagnostic.td
@@ -73,9 +73,33 @@
// This defines all of the named diagnostic groups.
include "DiagnosticGroups.td"
+class Legacy<string value> {
+ string Value = value;
+}
+
+class SARIF<string value> {
+ string Value = value;
+}
+
+class DiagReason<Legacy legacy, SARIF structured = SARIF<legacy.Value>> {
+ // A legacy reason is a reason that is part of Clang's legacy diagnostic model,
+ // but needed to be split from the summary in order to facilitate the existence
+ // of the structured diagnostic (which will have very different text). One may
+ // observe that older versions of Clang's diagnostics are the same as
+ // `Diagnostic.Summary + Diagnostic.Reason.Legacy`. This is intentional, so as
+ // to preserve the legacy diagnostic model for the time being.
+ Legacy Legacy = legacy;
+
+ // The SARIF reason will appear when Clang is asked to emit SARIF diagnostics,
+ // in place of Legacy. Unlike Legacy, which is a fragment of the original
+ // diagnostic from past-Clang, SARIF reasons may have completely different text
+ // to explain the problem, often from the perspective of a user.
+ SARIF SARIF = structured;
+}
+def NO_REASON_YET : DiagReason<Legacy<"">, SARIF<"">>;
// All diagnostics emitted by the compiler are an indirect subclass of this.
-class Diagnostic<string summary, DiagClass DC, Severity defaultmapping> {
+class Diagnostic<string summary, DiagClass DC, Severity defaultmapping, DiagReason reason> {
/// Component is specified by the file with a big let directive.
string Component = ?;
string Summary = summary;
@@ -89,6 +113,7 @@
Severity DefaultSeverity = defaultmapping;
DiagGroup Group;
string CategoryName = "";
+ DiagReason Reason = reason;
}
class SFINAEFailure {
@@ -126,24 +151,24 @@
}
// FIXME: ExtWarn and Extension should also be SFINAEFailure by default.
-class Error<string str> : Diagnostic<str, CLASS_ERROR, SEV_Error>, SFINAEFailure {
+class Error<string str, DiagReason reason = NO_REASON_YET> : Diagnostic<str, CLASS_ERROR, SEV_Error, reason>, SFINAEFailure {
bit ShowInSystemHeader = 1;
}
// Warnings default to on (but can be default-off'd with DefaultIgnore).
// This is used for warnings about questionable code; warnings about
// accepted language extensions should use Extension or ExtWarn below instead.
-class Warning<string str> : Diagnostic<str, CLASS_WARNING, SEV_Warning>;
+class Warning<string str, DiagReason reason = NO_REASON_YET> : Diagnostic<str, CLASS_WARNING, SEV_Warning, reason>;
// Remarks can be turned on with -R flags and provide commentary, e.g. on
// optimizer decisions.
-class Remark<string str> : Diagnostic<str, CLASS_REMARK, SEV_Ignored>;
+class Remark<string str, DiagReason reason = NO_REASON_YET> : Diagnostic<str, CLASS_REMARK, SEV_Ignored, reason>;
// Extensions are warnings about accepted language extensions.
// Extension warnings are default-off but enabled by -pedantic.
-class Extension<string str> : Diagnostic<str, CLASS_EXTENSION, SEV_Ignored>;
+class Extension<string str, DiagReason reason = NO_REASON_YET> : Diagnostic<str, CLASS_EXTENSION, SEV_Ignored, reason>;
// ExtWarns are warnings about accepted language extensions.
// ExtWarn warnings are default-on.
-class ExtWarn<string str> : Diagnostic<str, CLASS_EXTENSION, SEV_Warning>;
+class ExtWarn<string str, DiagReason reason = NO_REASON_YET> : Diagnostic<str, CLASS_EXTENSION, SEV_Warning, reason>;
// Notes can provide supplementary information on errors, warnings, and remarks.
-class Note<string str> : Diagnostic<str, CLASS_NOTE, SEV_Fatal/*ignored*/>;
+class Note<string str, DiagReason reason = NO_REASON_YET> : Diagnostic<str, CLASS_NOTE, SEV_Fatal/*ignored*/, reason>;
class DefaultIgnore { Severity DefaultSeverity = SEV_Ignored; }
Index: clang/include/clang/Basic/Diagnostic.h
===================================================================
--- clang/include/clang/Basic/Diagnostic.h
+++ clang/include/clang/Basic/Diagnostic.h
@@ -1666,11 +1666,29 @@
return DiagObj->DiagStorage.FixItHints;
}
- /// Format this diagnostic into a string, substituting the
+ /// Format the summary into a string, substituting the
/// formal arguments into the %0 slots.
///
/// The result is appended onto the \p OutStr array.
- void FormatDiagnostic(SmallVectorImpl<char> &OutStr) const;
+ void FormatSummary(SmallVectorImpl<char> &OutStr) const;
+
+ /// Format the legacy reason into a string, substituting the formal arguments
+ /// into the %0 slots.
+ ///
+ /// The result is appended onto the \p OutStr array.
+ void FormatLegacyReason(SmallVectorImpl<char> &OutStr) const;
+
+ /// Format the SARIF-based reason into a string, substituting the formal
+ /// arguments into the %0 slots.
+ ///
+ /// The result is appended onto the \p OutStr array.
+ void FormatSARIFReason(SmallVectorImpl<char> &OutStr) const;
+
+ /// Format the legacy diagnostic into a string, substituting the
+ /// formal arguments into the %0 slots.
+ ///
+ /// The result is appended onto the \p OutStr array.
+ void FormatLegacyDiagnostic(SmallVectorImpl<char> &OutStr) const;
/// Format the given format-string into the output buffer using the
/// arguments stored in this diagnostic.
@@ -1687,6 +1705,8 @@
DiagnosticsEngine::Level Level;
FullSourceLoc Loc;
std::string Message;
+ DiagnosticReason Reason;
+
std::vector<CharSourceRange> Ranges;
std::vector<FixItHint> FixIts;
@@ -1694,10 +1714,10 @@
StoredDiagnostic() = default;
StoredDiagnostic(DiagnosticsEngine::Level Level, const Diagnostic &Info);
StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
- StringRef Message);
+ StringRef Message, DiagnosticReason Reason);
StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
- StringRef Message, FullSourceLoc Loc,
- ArrayRef<CharSourceRange> Ranges,
+ StringRef Message, DiagnosticReason Reason,
+ FullSourceLoc Loc, ArrayRef<CharSourceRange> Ranges,
ArrayRef<FixItHint> Fixits);
/// Evaluates true when this object stores a diagnostic.
@@ -1707,6 +1727,7 @@
DiagnosticsEngine::Level getLevel() const { return Level; }
const FullSourceLoc &getLocation() const { return Loc; }
StringRef getMessage() const { return Message; }
+ const DiagnosticReason &getReason() const { return Reason; }
void setLocation(FullSourceLoc Loc) { this->Loc = Loc; }
Index: clang-tools-extra/clangd/Diagnostics.cpp
===================================================================
--- clang-tools-extra/clangd/Diagnostics.cpp
+++ clang-tools-extra/clangd/Diagnostics.cpp
@@ -42,7 +42,8 @@
const char *getDiagnosticCode(unsigned ID) {
switch (ID) {
#define DIAG(ENUM, CLASS, DEFAULT_MAPPING, DESC, GROPU, SFINAE, NOWERROR, \
- SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
+ SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY, \
+ LEGACY_REASON, SARIF_REASON) \
case clang::diag::ENUM: \
return #ENUM;
#include "clang/Basic/DiagnosticASTKinds.inc"
@@ -653,7 +654,7 @@
const clang::Diagnostic &Info,
clangd::DiagBase &D) {
llvm::SmallString<64> Message;
- Info.FormatDiagnostic(Message);
+ Info.FormatLegacyDiagnostic(Message);
D.Message = std::string(Message.str());
D.Severity = DiagLevel;
@@ -781,7 +782,8 @@
}
}
if (Message.empty()) // either !SyntheticMessage, or we failed to make one.
- Info.FormatDiagnostic(Message);
+ Info.FormatSummary(Message);
+ Info.FormatLegacyDiagnostic(Message);
LastDiag->Fixes.push_back(
Fix{std::string(Message.str()), std::move(Edits)});
return true;
Index: clang-tools-extra/clangd/Compiler.cpp
===================================================================
--- clang-tools-extra/clangd/Compiler.cpp
+++ clang-tools-extra/clangd/Compiler.cpp
@@ -21,7 +21,7 @@
const clang::Diagnostic &Info) {
// FIXME: format lazily, in case vlog is off.
llvm::SmallString<64> Message;
- Info.FormatDiagnostic(Message);
+ Info.FormatLegacyDiagnostic(Message);
llvm::SmallString<64> Location;
if (Info.hasSourceManager() && Info.getLocation().isValid()) {
Index: clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
===================================================================
--- clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
+++ clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp
@@ -418,7 +418,7 @@
Context.getLangOpts(), &Context.DiagEngine->getDiagnosticOptions(),
Errors.back());
SmallString<100> Message;
- Info.FormatDiagnostic(Message);
+ Info.FormatLegacyDiagnostic(Message);
FullSourceLoc Loc;
if (Info.getLocation().isValid() && Info.hasSourceManager())
Loc = FullSourceLoc(Info.getLocation(), Info.getSourceManager());
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits