https://github.com/matthiasgoergens created https://github.com/llvm/llvm-project/pull/214523
Fixes llvm/llvm-project#212467. ## Cause `mergeErrorAttr` used `AttributeCommonInfo::getNormalizedFullName()` to decide whether a new diagnostic attribute was an error or a warning. Contrary to the helper's assertion, a C++11 namespaced GNU spelling produces `gnu::warning` or `gnu::error`, rather than the unqualified string. ## Trigger (how the bug manifests) Reproduced on current main (2026-08-03): an assertions build from the unmodified base exits 134 (assertion abort in `SemaDeclAttr.cpp`) when two `[[gnu::warning]]` attributes are placed on one declaration. Even a release Clang rejects identical C23 attributes as incompatible, so the bug also changes non-asserting-build semantics — not merely a debug-build crash. ## Fix Construct the generated `ErrorAttr` first and use its semantic `isError()` and `isWarning()` predicates. These deliberately group GNU, C++11, and C23 spellings of the same attribute while retaining the existing same-kind, differing-message, and error-versus-warning merge behaviour. A second commit adds a C23 regression test. ## Verification - The unmodified compiler exits 134 at the reported assertion; the patched compiler accepts the same declaration. - The C++ regression covers duplicate warning and error attributes, differing messages, an incompatible error/warning pair, and both orders of mixed GNU and C++11 syntax. The added C23 regression covers both diagnostic kinds and both mixed GNU/C23 orders. - Both focused tests pass in a fresh current-main assertions build. The patched compiler also accepts the release-build C23 negative control without diagnostics. - All 3,059 tests in `clang/test/Sema`, `clang/test/SemaCXX`, and `clang/test/Frontend` pass, apart from the suite's supported skips and expected failure. - `git diff --check` passes. - Independent adversarial review checked all six generated spellings, incompatible attributes, redeclarations, inheritance, allocation lifetime, and diagnostic preservation, and found no blocker. From f52384556fa99e42f4b87fc98f392a05c8c03bb7 Mon Sep 17 00:00:00 2001 From: Matthias Goergens <[email protected]> Date: Sun, 2 Aug 2026 23:04:40 +0800 Subject: [PATCH 1/2] [clang][Sema] Merge GNU diagnostic attributes by semantic spelling Namespaced GNU attributes retain their gnu:: prefix in the normalised full name, so comparing that string with error or warning asserts when duplicate C++11 attributes are merged. Construct the attribute first and use its generated semantic spelling predicates, which group all supported spellings of each diagnostic attribute. --- clang/lib/Sema/SemaDeclAttr.cpp | 10 ++++------ clang/test/SemaCXX/gh212467.cpp | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 clang/test/SemaCXX/gh212467.cpp diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 0645f99492433..09ee3988baf3e 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -4056,12 +4056,10 @@ static void handleInitPriorityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { ErrorAttr *Sema::mergeErrorAttr(Decl *D, const AttributeCommonInfo &CI, StringRef NewUserDiagnostic) { + auto *NewAttr = ::new (Context) ErrorAttr(Context, CI, NewUserDiagnostic); if (const auto *EA = D->getAttr<ErrorAttr>()) { - std::string NewAttr = CI.getNormalizedFullName(); - assert((NewAttr == "error" || NewAttr == "warning") && - "unexpected normalized full name"); - bool Match = (EA->isError() && NewAttr == "error") || - (EA->isWarning() && NewAttr == "warning"); + bool Match = (EA->isError() && NewAttr->isError()) || + (EA->isWarning() && NewAttr->isWarning()); if (!Match) { Diag(EA->getLocation(), diag::err_attributes_are_not_compatible) << CI << EA @@ -4076,7 +4074,7 @@ ErrorAttr *Sema::mergeErrorAttr(Decl *D, const AttributeCommonInfo &CI, } D->dropAttr<ErrorAttr>(); } - return ::new (Context) ErrorAttr(Context, CI, NewUserDiagnostic); + return NewAttr; } FormatAttr *Sema::mergeFormatAttr(Decl *D, const AttributeCommonInfo &CI, diff --git a/clang/test/SemaCXX/gh212467.cpp b/clang/test/SemaCXX/gh212467.cpp new file mode 100644 index 0000000000000..38c760f55a084 --- /dev/null +++ b/clang/test/SemaCXX/gh212467.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +[[gnu::warning("same")]] +[[gnu::warning("same")]] +void same_warning(); + +[[gnu::warning("one")]] // expected-note {{previous attribute is here}} +[[gnu::warning("two")]] // expected-warning {{attribute 'gnu::warning' is already applied with different arguments}} +void different_warning(); + +[[gnu::error("same")]] +[[gnu::error("same")]] +void same_error(); + +[[gnu::error("one")]] // expected-error {{'gnu::warning' and 'gnu::error' attributes are not compatible}} +[[gnu::warning("two")]] // expected-note {{conflicting attribute is here}} +void conflicting(); + +[[gnu::warning("same")]] +__attribute__((warning("same"))) void mixed_syntax(); + +__attribute__((warning("same"))) +[[gnu::warning("same")]] void reverse_mixed_syntax(); From 3b9ca3672544ff9351cdc19d71df747bd2e64933 Mon Sep 17 00:00:00 2001 From: Matthias Goergens <[email protected]> Date: Mon, 3 Aug 2026 03:00:49 +0800 Subject: [PATCH 2/2] [clang][Sema] Test C23 GNU diagnostic attribute merging --- clang/test/Sema/gh212467.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 clang/test/Sema/gh212467.c diff --git a/clang/test/Sema/gh212467.c b/clang/test/Sema/gh212467.c new file mode 100644 index 0000000000000..c57d87f13a2db --- /dev/null +++ b/clang/test/Sema/gh212467.c @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -std=c23 -fsyntax-only -verify %s +// expected-no-diagnostics + +[[gnu::warning("same")]] +[[gnu::warning("same")]] +void same_warning(void); + +[[gnu::error("same")]] +[[gnu::error("same")]] +void same_error(void); + +[[gnu::warning("same")]] +__attribute__((warning("same"))) void mixed_warning(void); + +__attribute__((error("same"))) +[[gnu::error("same")]] void reverse_mixed_error(void); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
