llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Matthias Görgens (matthiasgoergens) <details> <summary>Changes</summary> 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. --- Full diff: https://github.com/llvm/llvm-project/pull/214523.diff 3 Files Affected: - (modified) clang/lib/Sema/SemaDeclAttr.cpp (+4-6) - (added) clang/test/Sema/gh212467.c (+16) - (added) clang/test/SemaCXX/gh212467.cpp (+23) ``````````diff 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/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); 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(); `````````` </details> https://github.com/llvm/llvm-project/pull/214523 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
