[clang] [clang] Fix crash on invalid decltype specifier (PR #224844)

via cfe-commits cfe-commits at lists.llvm.org
Sat Sep 19 09:49:42 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Rajin Khan (rajin-khan)

<details>
<summary>Changes</summary>

Fixes #<!-- -->165246.

When recovery sees `decltype` without an opening parenthesis while token backtracking is active, `ParseDecltypeSpecifier` returns the token's start location. `AnnotatePreviousCachedTokens` requires the annotation end to match the last location of the most recently cached token, so malformed input such as `int decltype {}` trips its assertion.

Use the last cached token location for an invalid decltype specifier after rewinding the lookahead token. This is the same recovery pattern used by the adjacent pack indexing annotation path.

The existing `decltype-crash.cpp` test now covers the brace form from the report.

Testing:

- `clang++ -cc1 -fsyntax-only -verify -std=c++11 clang/test/Parser/decltype-crash.cpp`
- `clang++ -cc1 -fsyntax-only -verify -std=c++20 clang/test/Parser/decltype-crash.cpp`
- `git diff --check`

The focused verification commands used Apple Clang 21.0.0. The assertion-specific path was reviewed against the current preprocessor cache invariant; this checkout does not contain a locally built assertions-enabled Clang.


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


2 Files Affected:

- (modified) clang/lib/Parse/ParseDeclCXX.cpp (+2) 
- (modified) clang/test/Parser/decltype-crash.cpp (+4) 


``````````diff
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 1eeb0d21b68d7..dade5ab3c9e82 100644
--- a/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/clang/lib/Parse/ParseDeclCXX.cpp
@@ -1110,6 +1110,8 @@ void Parser::AnnotateExistingDecltypeSpecifier(const DeclSpec &DS,
   // make sure we have a token we can turn into an annotation token
   if (PP.isBacktrackEnabled()) {
     PP.RevertCachedTokens(1);
+    if (DS.getTypeSpecType() == TST_error)
+      EndLoc = PP.getLastCachedTokenLocation();
   } else
     PP.EnterToken(Tok, /*IsReinject*/ true);
 
diff --git a/clang/test/Parser/decltype-crash.cpp b/clang/test/Parser/decltype-crash.cpp
index af4622df5e54a..d91229b3a6692 100644
--- a/clang/test/Parser/decltype-crash.cpp
+++ b/clang/test/Parser/decltype-crash.cpp
@@ -13,3 +13,7 @@ int decltype = 0;
 int *decltype = 0;
 // expected-error at -1 {{expected '(' after 'decltype'}}
 // expected-error at -2 {{expected unqualified-id}}
+
+int decltype {}
+// expected-error at -1 {{expected '(' after 'decltype'}}
+// expected-error at -2 {{expected unqualified-id}}

``````````

</details>


https://github.com/llvm/llvm-project/pull/224844


More information about the cfe-commits mailing list