Author: Oleksandr Tarasiuk
Date: 2026-02-26T23:48:53+02:00
New Revision: c5f40ef7fe7f1fa616d28b46334cf60579d4893c

URL: 
https://github.com/llvm/llvm-project/commit/c5f40ef7fe7f1fa616d28b46334cf60579d4893c
DIFF: 
https://github.com/llvm/llvm-project/commit/c5f40ef7fe7f1fa616d28b46334cf60579d4893c.diff

LOG: [Clang] fix crash parsing forbidden attribute args in pragma attributes 
(#182362)

Fixes #182122

--- 

This patch resolves a crash when parsing `#pragma clang attribute`
arguments for attributes that forbid arguments. The root cause is that
the `#pragma` attribute path doesn't pass `EndLoc` to


https://github.com/llvm/llvm-project/blob/413cafa4624eb37e586e266f44abd64896e1c598/clang/lib/Parse/ParsePragma.cpp#L1982-L1985

unlike the normal attribute parsing flow


https://github.com/llvm/llvm-project/blob/413cafa4624eb37e586e266f44abd64896e1c598/clang/lib/Parse/ParseDeclCXX.cpp#L4706

Without `EndLoc`, argument parsing cannot update the parsed end token


https://github.com/llvm/llvm-project/blob/413cafa4624eb37e586e266f44abd64896e1c598/clang/lib/Parse/ParseDecl.cpp#L621-L622

and `fix-it` gets an invalid end location


https://github.com/llvm/llvm-project/blob/0dafeb97a4687c29f5182fa0239c7fa39ee23091/clang/lib/Parse/ParseDeclCXX.cpp#L4537

This change makes the pragma path pass `EndLoc` the same way as the
regular flow does, preventing the crash and preserving valid fix-it
ranges.

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/Parse/ParseDeclCXX.cpp
    clang/lib/Parse/ParsePragma.cpp
    clang/test/FixIt/fixit-pragma-attribute.cpp
    clang/test/Parser/pragma-attribute.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 3c533f5595346..88023779e4bb7 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -299,6 +299,7 @@ Bug Fixes in This Version
 - Fixed an assertion failure when evaluating ``_Countof`` on invalid 
``void``-typed operands. (#GH180893)
 - Fixed an assertion failure in the serialized diagnostic printer when it is 
destroyed without calling ``finish()``. (#GH140433)
 - Fixed an assertion failure caused by error recovery while extending a nested 
name specifier with results from ordinary lookup. (#GH181470)
+- Fixed a crash when parsing ``#pragma clang attribute`` arguments for 
attributes that forbid arguments. (#GH182122)
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

diff  --git a/clang/lib/Parse/ParseDeclCXX.cpp 
b/clang/lib/Parse/ParseDeclCXX.cpp
index 9117a725843d9..274c354d59808 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -4532,9 +4532,10 @@ bool Parser::ParseCXX11AttributeArgs(
       // The attribute parsed successfully, but was not allowed to have any
       // arguments. It doesn't matter whether any were provided -- the
       // presence of the argument list (even if empty) is diagnosed.
-      Diag(LParenLoc, diag::err_cxx11_attribute_forbids_arguments)
-          << AttrName
-          << FixItHint::CreateRemoval(SourceRange(LParenLoc, *EndLoc));
+      auto D = Diag(LParenLoc, diag::err_cxx11_attribute_forbids_arguments)
+               << AttrName;
+      if (EndLoc)
+        D << FixItHint::CreateRemoval(SourceRange(LParenLoc, *EndLoc));
       Attr.setInvalid(true);
     }
   }

diff  --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp
index def2817c930b2..734d095d74cdf 100644
--- a/clang/lib/Parse/ParsePragma.cpp
+++ b/clang/lib/Parse/ParsePragma.cpp
@@ -1982,7 +1982,8 @@ void Parser::HandlePragmaAttribute() {
   if ((Tok.is(tok::l_square) && NextToken().is(tok::l_square)) ||
       Tok.isRegularKeywordAttribute()) {
     // Parse the CXX11 style attribute.
-    ParseCXX11AttributeSpecifier(Attrs);
+    SourceLocation EndLoc = Tok.getLocation();
+    ParseCXX11AttributeSpecifier(Attrs, &EndLoc);
   } else if (Tok.is(tok::kw___attribute)) {
     ConsumeToken();
     if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,

diff  --git a/clang/test/FixIt/fixit-pragma-attribute.cpp 
b/clang/test/FixIt/fixit-pragma-attribute.cpp
index ad233ef067915..3824e45d8fca5 100644
--- a/clang/test/FixIt/fixit-pragma-attribute.cpp
+++ b/clang/test/FixIt/fixit-pragma-attribute.cpp
@@ -84,3 +84,10 @@
 
 #pragma clang attribute push (__attribute__((objc_externally_retained)), 
apply_to)
 // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:82-[[@LINE-1]]:82}:" = any(function, 
variable(unless(is_parameter)))"
+
+int x;
+#pragma clang attribute push ([[noreturn (x))
+// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:42-[[@LINE-1]]:45}:""
+
+#pragma clang attribute push([[noreturn (x)]], apply_to = function)
+// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:41-[[@LINE-1]]:44}:""

diff  --git a/clang/test/Parser/pragma-attribute.cpp 
b/clang/test/Parser/pragma-attribute.cpp
index eaf1a775c1c88..da1b3f3170428 100644
--- a/clang/test/Parser/pragma-attribute.cpp
+++ b/clang/test/Parser/pragma-attribute.cpp
@@ -217,3 +217,10 @@ _Pragma("clang attribute pop");
 #pragma clang attribute push (__attribute__((disable_tail_calls,)), apply_to = 
function) // expected-error {{expected identifier that represents an attribute 
name}}
 
 #pragma clang attribute push ([[clang::disable_tail_calls, noreturn]]) // 
expected-error {{expected ','}}
+
+int x;
+#pragma clang attribute push([[noreturn (x)]], apply_to = function) // 
expected-error {{attribute 'noreturn' cannot have an argument list}}
+
+#pragma clang attribute push ([[noreturn (x)) // expected-error {{attribute 
'noreturn' cannot have an argument list}} \
+                                              // expected-error {{expected 
']'}} \
+                                              // expected-error {{expected 
']'}}


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to