llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Chen Miao (ChenMiaoi)

<details>
<summary>Changes</summary>

A nested `_Pragma` can produce an `annot_pragma_attribute` token during 
preprocessing. After diagnosing invalid attribute syntax, 
`HandlePragmaAttribute` calls `getIdentifierInfo()` to generate a fix-it 
without checking whether the current token is an annotation. 
`getAttributeSubjectRulesRecoveryPointForToken`, which handles recovery for 
attribute subject rules, has the same problem.

For example, this input enters the attribute syntax error path:

```c
#pragma clang attribute (_Pragma("clang attribute push"))
```

In the following input, the attribute itself is valid, but a nested `_Pragma` 
appears where `apply_to` is expected, entering the attribute subject rule 
recovery path:

```c
#pragma clang attribute push(__attribute__((annotate("test"))), _Pragma("clang 
attribute push"))
```

Before this change, both inputs fail in assertion-enabled builds with:

```text
Assertion `!isAnnotation() &amp;&amp; "getIdentifierInfo() on an annotation 
token!"' failed.
```

Check for annotation tokens before querying identifier information in 
`HandlePragmaAttribute`. Return `None` for annotation tokens in 
`getAttributeSubjectRulesRecoveryPointForToken` so that the existing error 
recovery logic can handle them.

The two inputs now produce the following diagnostics, respectively:

```text
error: expected an attribute that is specified using the GNU, C++11 or 
'__declspec' syntax
error: expected attribute subject set specifier 'apply_to'
```

Fixes #<!-- -->225035

---
Full diff: https://github.com/llvm/llvm-project/pull/228990.diff


2 Files Affected:

- (modified) clang/lib/Parse/ParsePragma.cpp (+7-1) 
- (modified) clang/test/Parser/pragma-attribute.cpp (+7) 


``````````diff
diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp
index f58d2c70b7d98..34a9ed09fec8e 100644
--- a/clang/lib/Parse/ParsePragma.cpp
+++ b/clang/lib/Parse/ParsePragma.cpp
@@ -1870,6 +1870,10 @@ enum class MissingAttributeSubjectRulesRecoveryPoint {
 
 MissingAttributeSubjectRulesRecoveryPoint
 getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) {
+  // Nested `_Pragma` annotations cannot name attribute subject rules.
+  // https://github.com/llvm/llvm-project/issues/225035
+  if (Tok.isAnnotation())
+    return MissingAttributeSubjectRulesRecoveryPoint::None;
   if (const auto *II = Tok.getIdentifierInfo()) {
     if (II->isStr("apply_to"))
       return MissingAttributeSubjectRulesRecoveryPoint::ApplyTo;
@@ -2038,7 +2042,9 @@ void Parser::HandlePragmaAttribute() {
     ParseMicrosoftDeclSpecs(Attrs);
   } else {
     Diag(Tok, diag::err_pragma_attribute_expected_attribute_syntax);
-    if (Tok.getIdentifierInfo()) {
+    // A nested `_Pragma` can produce an annotation token here.
+    // https://github.com/llvm/llvm-project/issues/225035
+    if (!Tok.isAnnotation() && Tok.getIdentifierInfo()) {
       // If we suspect that this is an attribute suggest the use of
       // '__attribute__'.
       if (ParsedAttr::getParsedKind(
diff --git a/clang/test/Parser/pragma-attribute.cpp 
b/clang/test/Parser/pragma-attribute.cpp
index 1f90a8990bb96..78699c06262cd 100644
--- a/clang/test/Parser/pragma-attribute.cpp
+++ b/clang/test/Parser/pragma-attribute.cpp
@@ -180,6 +180,13 @@ _Pragma("clang attribute pop");
 #pragma clang attribute push (annotate("test")) // expected-error {{expected 
an attribute that is specified using the GNU, C++11 or '__declspec' syntax}}
 // expected-note@-1 {{use the GNU '__attribute__' syntax}}
 
+// Nested pragmas must be diagnosed without crashing (GH225035).
+#pragma clang attribute (_Pragma("clang attribute push")) // expected-error 
{{expected an attribute that is specified using the GNU, C++11 or '__declspec' 
syntax}}
+#pragma clang attribute push (_Pragma("clang attribute push")) // 
expected-error {{expected an attribute that is specified using the GNU, C++11 
or '__declspec' syntax}}
+#pragma clang attribute push(__attribute__((annotate("test"))) _Pragma("clang 
attribute push")) // expected-error {{expected ','}}
+#pragma clang attribute push(__attribute__((annotate("test"))), _Pragma("clang 
attribute push")) // expected-error {{expected attribute subject set specifier 
'apply_to'}}
+#pragma clang attribute push(__attribute__((annotate("test"))), apply_to 
_Pragma("clang attribute push")) // expected-error {{expected '='}}
+
 #pragma clang attribute push([[clang::uninitialized]], apply_to = 
variable(is_local))
 #pragma clang attribute pop
 #pragma clang attribute push([[clang::uninitialized]], apply_to = function) // 
expected-error {{attribute 'clang::uninitialized' cannot be applied to 
'function'}}

``````````

</details>


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

Reply via email to