https://github.com/rajin-khan created
https://github.com/llvm/llvm-project/pull/224844
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.
>From 2b006ba37d7822b6e6e6e7ae7abb11b973fcbcb5 Mon Sep 17 00:00:00 2001
From: Rajin Khan <[email protected]>
Date: Sat, 19 Sep 2026 22:48:04 +0600
Subject: [PATCH] [clang] Fix invalid decltype annotation range
Use the last cached token location when recovering an invalid decltype
specifier so the annotation range satisfies the preprocessor cache invariant.
Fixes #165246
---
clang/lib/Parse/ParseDeclCXX.cpp | 2 ++
clang/test/Parser/decltype-crash.cpp | 4 ++++
2 files changed, 6 insertions(+)
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp
index 1eeb0d21b68d7b..dade5ab3c9e823 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 af4622df5e54aa..d91229b3a66924 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@-1 {{expected '(' after 'decltype'}}
// expected-error@-2 {{expected unqualified-id}}
+
+int decltype {}
+// expected-error@-1 {{expected '(' after 'decltype'}}
+// expected-error@-2 {{expected unqualified-id}}
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits