https://github.com/qiyao updated https://github.com/llvm/llvm-project/pull/203520
>From 7bf6b93489cf436055479c1dd8818dff293e4571 Mon Sep 17 00:00:00 2001 From: Yao Qi <[email protected]> Date: Fri, 5 Jun 2026 14:59:19 +0100 Subject: [PATCH 1/2] [clang] Honor ShowLevel for diagnostics without a source location When lldb evaluates expression and gets error, it prints double `error: ` as below, ``` (lldb) expression v1::withImplicitTag(Simple{.mem = 6}) note: Ran expression as 'C++11'. error: error: Multiple internal symbols found for 'v1' ``` The first `error:` is from lldb and the second `error:` is from clang's diagnostic. LLDB's `ClangDiagnosticManagerAdapter` sets `ShowLevel=false`, so that its own rendering layer (`RenderDiagnosticDetails`) can add the severity prefix with color. However, clang still adds "error:" in the output buffer means the guard is missing. `TextDiagnosticPrinter::HandleDiagnostic` has two paths: one for diagnostics with a valid source location (delegating to `TextDiagnostic::emitDiagnostic`) and a simpler path for diagnostics without one. The with-location path already guarded `printDiagnosticLevel` behind `DiagOpts.ShowLevel`; the no-location path called it unconditionally. Add a parameterized unit test covering `ShowLevel=true` and `ShowLevel=false` for no-location diagnostics to prevent regression. --- clang/lib/Frontend/TextDiagnosticPrinter.cpp | 3 ++- .../unittests/Frontend/TextDiagnosticTest.cpp | 26 +++++++++++++++++++ .../diagnostics/TestExprDiagnostics.py | 2 +- .../Shell/Expr/TestObjCxxEnumConflict.test | 4 +-- 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/clang/lib/Frontend/TextDiagnosticPrinter.cpp b/clang/lib/Frontend/TextDiagnosticPrinter.cpp index 83fd70e5f99f9..475f11e36977c 100644 --- a/clang/lib/Frontend/TextDiagnosticPrinter.cpp +++ b/clang/lib/Frontend/TextDiagnosticPrinter.cpp @@ -133,7 +133,8 @@ void TextDiagnosticPrinter::HandleDiagnostic(DiagnosticsEngine::Level Level, // diagnostics in a context that lacks language options, a source manager, or // other infrastructure necessary when emitting more rich diagnostics. if (!Info.getLocation().isValid()) { - TextDiagnostic::printDiagnosticLevel(OS, Level, DiagOpts.ShowColors); + if (DiagOpts.ShowLevel) + TextDiagnostic::printDiagnosticLevel(OS, Level, DiagOpts.ShowColors); TextDiagnostic::printDiagnosticMessage( OS, /*IsSupplemental=*/Level == DiagnosticsEngine::Note, DiagMessageStream.str(), OS.tell() - StartOfLocationInfo, diff --git a/clang/unittests/Frontend/TextDiagnosticTest.cpp b/clang/unittests/Frontend/TextDiagnosticTest.cpp index 622dbc5883067..20ab54379c7a4 100644 --- a/clang/unittests/Frontend/TextDiagnosticTest.cpp +++ b/clang/unittests/Frontend/TextDiagnosticTest.cpp @@ -10,6 +10,7 @@ #include "clang/Basic/FileManager.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceManager.h" +#include "clang/Frontend/TextDiagnosticPrinter.h" #include "llvm/Support/SmallVectorMemoryBuffer.h" #include "gtest/gtest.h" @@ -95,4 +96,29 @@ TEST(TextDiagnostic, ShowLine) { EXPECT_EQ("main.cpp:1: warning: message\n", PrintDiag(DiagOpts, Loc)); } +// Parameterized fixture for ShowLevel tests: bool param = ShowLevel value. +struct ShowLevelNoLocationTest : public ::testing::TestWithParam<bool> {}; + +TEST_P(ShowLevelNoLocationTest, LevelPrefixRespected) { + bool ShowLevel = GetParam(); + DiagnosticOptions DiagOpts; + DiagOpts.ShowLevel = ShowLevel; + std::string Output; + llvm::raw_string_ostream OS(Output); + TextDiagnosticPrinter Printer(OS, DiagOpts); + DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts, &Printer, + /*ShouldOwnClient=*/false); + // Report without a SourceLocation, exercises the no-location path in + // TextDiagnosticPrinter::HandleDiagnostic. + unsigned ID = Diags.getCustomDiagID(DiagnosticsEngine::Error, "%0"); + Diags.Report(ID) << "message"; + if (ShowLevel) + EXPECT_EQ(Output, "error: message\n"); + else + EXPECT_EQ(Output, "message\n"); +} + +INSTANTIATE_TEST_SUITE_P(ShowLevelNoLocation, ShowLevelNoLocationTest, + ::testing::Bool()); + } // anonymous namespace diff --git a/lldb/test/API/commands/expression/diagnostics/TestExprDiagnostics.py b/lldb/test/API/commands/expression/diagnostics/TestExprDiagnostics.py index 1f87a6918bb21..03851924aba45 100644 --- a/lldb/test/API/commands/expression/diagnostics/TestExprDiagnostics.py +++ b/lldb/test/API/commands/expression/diagnostics/TestExprDiagnostics.py @@ -140,7 +140,7 @@ def test_source_and_caret_printing(self): """ 1 | foo(1, 2) | ^~~ -note: candidate function not viable: requires single argument 'x', but 2 arguments were provided +candidate function not viable: requires single argument 'x', but 2 arguments were provided """, value.GetError().GetCString(), ) diff --git a/lldb/test/Shell/Expr/TestObjCxxEnumConflict.test b/lldb/test/Shell/Expr/TestObjCxxEnumConflict.test index cf1f2c67e3880..2cbe13280a6b6 100644 --- a/lldb/test/Shell/Expr/TestObjCxxEnumConflict.test +++ b/lldb/test/Shell/Expr/TestObjCxxEnumConflict.test @@ -50,5 +50,5 @@ expression -l objective-c -- (MyInt)5 # CHECK: error: reference to 'MyInt' is ambiguous # CHECK: error: reference to 'MyInt' is ambiguous -# CHECK: note: note: candidate found by name lookup is 'MyInt' -# CHECK: note: note: candidate found by name lookup is 'MyInt' +# CHECK: note: candidate found by name lookup is 'MyInt' +# CHECK: note: candidate found by name lookup is 'MyInt' >From 204bcb8fa84e7cca743b205876ea8a714d650abd Mon Sep 17 00:00:00 2001 From: Yao Qi <[email protected]> Date: Fri, 12 Jun 2026 16:54:16 +0100 Subject: [PATCH 2/2] Update clang/unittests/Frontend/TextDiagnosticTest.cpp Co-authored-by: Michael Buch <[email protected]> --- clang/unittests/Frontend/TextDiagnosticTest.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clang/unittests/Frontend/TextDiagnosticTest.cpp b/clang/unittests/Frontend/TextDiagnosticTest.cpp index 20ab54379c7a4..d99d3aef4caa2 100644 --- a/clang/unittests/Frontend/TextDiagnosticTest.cpp +++ b/clang/unittests/Frontend/TextDiagnosticTest.cpp @@ -96,8 +96,7 @@ TEST(TextDiagnostic, ShowLine) { EXPECT_EQ("main.cpp:1: warning: message\n", PrintDiag(DiagOpts, Loc)); } -// Parameterized fixture for ShowLevel tests: bool param = ShowLevel value. -struct ShowLevelNoLocationTest : public ::testing::TestWithParam<bool> {}; +struct ShowLevelNoLocationTest : public ::testing::TestWithParam<bool /* ShowLevel */> {}; TEST_P(ShowLevelNoLocationTest, LevelPrefixRespected) { bool ShowLevel = GetParam(); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
