https://github.com/0bVdnt created https://github.com/llvm/llvm-project/pull/176252
Diagnose duplicate [[maybe_unused]], [[noreturn]], and [[fallthrough]] attributes as required by the C++17 standard (attribute shall appear at most once in each attribute-list). - [X] Tested locally Fixes #176136 >From ef82c3b97bf7fb4d9043ff0d7c45a2289fb0c1b2 Mon Sep 17 00:00:00 2001 From: Vedant Neve <[email protected]> Date: Thu, 15 Jan 2026 21:38:36 +0000 Subject: [PATCH] [Clang] Warn on duplicate standard attributes without arguments Fixes #176136 --- clang/lib/Sema/SemaDeclAttr.cpp | 11 +++++++++++ clang/lib/Sema/SemaStmtAttr.cpp | 13 +++++++++++++ clang/test/SemaCXX/cxx17-duplicate-attrs.cpp | 19 +++++++++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 clang/test/SemaCXX/cxx17-duplicate-attrs.cpp diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index d762bcd789bf5..d770d513f108a 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -2099,6 +2099,12 @@ static void handleStandardNoReturnAttr(Sema &S, Decl *D, const ParsedAttr &A) { S.getSourceManager().isInSystemMacro(A.getLoc()))) S.Diag(A.getLoc(), diag::warn_deprecated_noreturn_spelling) << A.getRange(); + // Check for duplicate attribute - warn if already applied. + if (D->hasAttr<CXX11NoReturnAttr>()) { + S.Diag(A.getLoc(), diag::warn_duplicate_attribute_exact) << A; + return; + } + D->addAttr(::new (S.Context) CXX11NoReturnAttr(S.Context, A)); } @@ -2230,6 +2236,11 @@ static void handleUnusedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!S.getLangOpts().CPlusPlus17 && IsCXX17Attr) S.Diag(AL.getLoc(), diag::ext_cxx17_attr) << AL; + // Check for duplicate attribute - warn if already applied. + if (D->hasAttr<UnusedAttr>()) { + S.Diag(AL.getLoc(), diag::warn_duplicate_attribute_exact) << AL; + return; + } D->addAttr(::new (S.Context) UnusedAttr(S.Context, AL)); } diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp index 27fd5563cc40e..c440ec3fe7735 100644 --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -16,6 +16,7 @@ #include "clang/Sema/DelayedDiagnostic.h" #include "clang/Sema/ParsedAttr.h" #include "clang/Sema/ScopeInfo.h" +#include "llvm/ADT/SmallPtrSet.h" #include <optional> using namespace clang; @@ -740,7 +741,19 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &A, void Sema::ProcessStmtAttributes(Stmt *S, const ParsedAttributes &InAttrs, SmallVectorImpl<const Attr *> &OutAttrs) { + // Track standard attributes without arguments to detect duplicates. + llvm::SmallPtrSet<const IdentifierInfo *, 8> SeenStdAttrs; + for (const ParsedAttr &AL : InAttrs) { + // Check for duplicate standard attributes without arguments. + if (AL.isStandardAttributeSyntax() && !AL.getScopeName() && + AL.getNumArgs() == 0 && AL.getAttrName()) { + if (!SeenStdAttrs.insert(AL.getAttrName()).second) { + Diag(AL.getLoc(), diag::warn_duplicate_attribute_exact) << AL; + continue; + } + } + if (const Attr *A = ProcessStmtAttribute(*this, S, AL, InAttrs.Range)) OutAttrs.push_back(A); } diff --git a/clang/test/SemaCXX/cxx17-duplicate-attrs.cpp b/clang/test/SemaCXX/cxx17-duplicate-attrs.cpp new file mode 100644 index 0000000000000..67bea30e30f35 --- /dev/null +++ b/clang/test/SemaCXX/cxx17-duplicate-attrs.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s + +int foo([[maybe_unused, maybe_unused]] int a) { // expected-warning {{attribute 'maybe_unused' is already applied}} + return 1; +} + +[[noreturn, noreturn]] void g() { // expected-warning {{attribute 'noreturn' is already applied}} + __builtin_unreachable(); +} + +int h(int n) { + switch (n) { + case 1: + [[fallthrough, fallthrough]]; // expected-warning {{attribute 'fallthrough' is already applied}} + case 2: + return 1; + } + return 0; +} \ No newline at end of file _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
