[clang] [Clang][Parser] Reject unbalanced unknown attribute arguments (PR #220259)

via cfe-commits cfe-commits at lists.llvm.org
Sun Sep 6 03:07:55 PDT 2026


https://github.com/nehaGautam07 updated https://github.com/llvm/llvm-project/pull/220259

>From a68ba345063247506807acaf2990ba1fc4aa749e Mon Sep 17 00:00:00 2001
From: neharaj <neharajgautam07 at gmail.com>
Date: Sat, 5 Sep 2026 11:52:10 +0000
Subject: [PATCH] [Clang][Parser] Reject unbalanced unknown attribute arguments

---
 clang/include/clang/Parse/Parser.h               | 4 +++-
 clang/lib/Parse/ParseDeclCXX.cpp                 | 5 ++++-
 clang/lib/Parse/Parser.cpp                       | 6 ++++++
 clang/test/Parser/cxx11-unbalanced-attr-args.cpp | 7 +++++++
 4 files changed, 20 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/Parser/cxx11-unbalanced-attr-args.cpp

diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index ae91153e34e3a..4a1b330fc995e 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -570,7 +570,9 @@ class Parser : public CodeCompletionHandler {
     StopAtSemi = 1 << 0, ///< Stop skipping at semicolon
     /// Stop skipping at specified token, but don't skip the token itself
     StopBeforeMatch = 1 << 1,
-    StopAtCodeCompletion = 1 << 2 ///< Stop at code completion
+    StopAtCodeCompletion = 1 << 2, ///< Stop at code completion
+    /// Do not swallow an unmatched ')', ']', or '}'.
+    StopAtUnbalanced = 1 << 3
   };
 
   friend constexpr SkipUntilFlags operator|(SkipUntilFlags L,
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index d701cbaa43bdd..0e67f83f76b3b 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -4581,7 +4581,10 @@ bool Parser::ParseCXX11AttributeArgs(
                     ScopeName, AttrName, getTargetInfo(), getLangOpts())) {
     // Eat the left paren, then skip to the ending right paren.
     ConsumeParen();
-    SkipUntil(tok::r_paren);
+    if (!SkipUntil(tok::r_paren, StopAtUnbalanced)) {
+      Diag(Tok, diag::err_expected) << tok::r_paren;
+      SkipUntil(tok::r_paren, StopAtSemi);
+    }
     return false;
   }
 
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index 84059a41238cc..c67bb8503735c 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -394,16 +394,22 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, SkipUntilFlags Flags) {
     case tok::r_paren:
       if (ParenCount && !isFirstTokenSkipped)
         return false;  // Matches something.
+      if (HasFlagsSet(Flags, StopAtUnbalanced))
+        return false;
       ConsumeParen();
       break;
     case tok::r_square:
       if (BracketCount && !isFirstTokenSkipped)
         return false;  // Matches something.
+      if (HasFlagsSet(Flags, StopAtUnbalanced))
+        return false;
       ConsumeBracket();
       break;
     case tok::r_brace:
       if (BraceCount && !isFirstTokenSkipped)
         return false;  // Matches something.
+      if (HasFlagsSet(Flags, StopAtUnbalanced))
+        return false;
       ConsumeBrace();
       break;
 
diff --git a/clang/test/Parser/cxx11-unbalanced-attr-args.cpp b/clang/test/Parser/cxx11-unbalanced-attr-args.cpp
new file mode 100644
index 0000000000000..ba132bca19c72
--- /dev/null
+++ b/clang/test/Parser/cxx11-unbalanced-attr-args.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -x c -std=c23 %s
+
+[[X1(])]]; // expected-error {{expected ')'}} expected-warning {{unknown attribute 'X1' ignored}}
+[[X1(})]]; // expected-error {{expected ')'}} expected-warning {{unknown attribute 'X1' ignored}}
+[[X1]]; // expected-warning {{unknown attribute 'X1' ignored}}
+[[X1()]]; // expected-warning {{unknown attribute 'X1' ignored}}
\ No newline at end of file



More information about the cfe-commits mailing list