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

Reply via email to