[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
llvm-ci wrote:
LLVM Buildbot has detected a new failure on builder
`sanitizer-x86_64-linux-bootstrap-msan` running on `sanitizer-buildbot5` while
building `clang` at step 2 "annotate".
Full details are available at:
https://lab.llvm.org/buildbot/#/builders/164/builds/20373
Here is the relevant piece of the build log for the reference
```
Step 2 (annotate) failure: 'python
../sanitizer_buildbot/sanitizers/zorg/buildbot/builders/sanitizers/buildbot_selector.py'
(failure)
...
llvm-lit:
/home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:569:
note: using lld-link:
/home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm_build_msan/bin/lld-link
llvm-lit:
/home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:569:
note: using ld64.lld:
/home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm_build_msan/bin/ld64.lld
llvm-lit:
/home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:569:
note: using wasm-ld:
/home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm_build_msan/bin/wasm-ld
llvm-lit:
/home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:569:
note: using ld.lld:
/home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm_build_msan/bin/ld.lld
llvm-lit:
/home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:569:
note: using lld-link:
/home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm_build_msan/bin/lld-link
llvm-lit:
/home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:569:
note: using ld64.lld:
/home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm_build_msan/bin/ld64.lld
llvm-lit:
/home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:569:
note: using wasm-ld:
/home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm_build_msan/bin/wasm-ld
llvm-lit:
/home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/llvm/utils/lit/lit/main.py:74:
note: The test suite configuration requested an individual test timeout of 0
seconds but a timeout of 900 seconds was requested on the command line. Forcing
timeout to be 900 seconds.
-- Testing: 97983 tests, 64 workers --
Testing: 0.. 10.. 20.. 30.. 40.. 50
FAIL: LLVM :: CodeGen/X86/basic-block-sections-clusters-bb-hash.ll (54160 of
97983)
TEST 'LLVM ::
CodeGen/X86/basic-block-sections-clusters-bb-hash.ll' FAILED
Exit Code: 1
Command Output (stdout):
--
# RUN: at line 11
/home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm_build_msan/bin/llc
/home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/llvm/test/CodeGen/X86/basic-block-sections-clusters-bb-hash.ll
-O0 -mtriple=x86_64-pc-linux -function-sections -filetype=obj
-basic-block-address-map -emit-bb-hash -o
/home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm_build_msan/test/CodeGen/X86/Output/basic-block-sections-clusters-bb-hash.ll.tmp.o
# executed command:
/home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm_build_msan/bin/llc
/home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm-project/llvm/test/CodeGen/X86/basic-block-sections-clusters-bb-hash.ll
-O0 -mtriple=x86_64-pc-linux -function-sections -filetype=obj
-basic-block-address-map -emit-bb-hash -o
/home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm_build_msan/test/CodeGen/X86/Output/basic-block-sections-clusters-bb-hash.ll.tmp.o
# note: command had no output on stdout or stderr
# RUN: at line 16
echo 'v1' >
/home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm_build_msan/test/CodeGen/X86/Output/basic-block-sections-clusters-bb-hash.ll.tmp1
# executed command: echo v1
# note: command had no output on stdout or stderr
# RUN: at line 17
echo 'f foo' >>
/home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm_build_msan/test/CodeGen/X86/Output/basic-block-sections-clusters-bb-hash.ll.tmp1
# executed command: echo 'f foo'
# note: command had no output on stdout or stderr
# RUN: at line 18
echo 'g 0:100,1:100,2:0 1:100,3:100 2:0,3:0 3:100' >>
/home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm_build_msan/test/CodeGen/X86/Output/basic-block-sections-clusters-bb-hash.ll.tmp1
# executed command: echo 'g 0:100,1:100,2:0 1:100,3:100 2:0,3:0 3:100'
# note: command had no output on stdout or stderr
# RUN: at line 22
/home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm_build_msan/bin/llvm-readobj
/home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm_build_msan/test/CodeGen/X86/Output/basic-block-sections-clusters-bb-hash.ll.tmp.o
--bb-addr-map | awk 'BEGIN {printf "h"} /ID: [0-9]+/ {id=$2} /Hash:
0x[0-9A-Fa-f]+/ {gsub(/^0x/, "", $2); hash=$2; printf " %s:%s", id, hash}
END {print ""}' >>
/home/b/sanitizer-x86_64-linux-bootstrap-msan/build/llvm_build_msan/test/CodeGen/X86/Output/basic-block-sectio
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
https://github.com/a-tarasyuk closed https://github.com/llvm/llvm-project/pull/177865 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
https://github.com/a-tarasyuk updated
https://github.com/llvm/llvm-project/pull/177865
>From 886c342fcf9a2a84929f6fb3eb51ea74de5c6b83 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk
Date: Sun, 25 Jan 2026 19:05:45 +0200
Subject: [PATCH 1/6] [Clang] prevent incorrect rejection of auto with
reordered declaration specifiers in C23
---
clang/docs/ReleaseNotes.rst | 1 +
clang/lib/Parse/ParseDecl.cpp | 14 +-
clang/test/Parser/c2x-auto.c | 24 +++-
3 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a734804865c57..47e578448e1e8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -169,6 +169,7 @@ Bug Fixes in This Version
-
- Fix lifetime extension of temporaries in for-range-initializers in
templates. (#GH165182)
+- Fixed incorrect rejection of ``auto`` with reordered declaration specifiers
in C23. (#GH164121)
Bug Fixes to Compiler Builtins
^^
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index f8c49646fcf3f..404f0a312b8bf 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -4093,7 +4093,19 @@ void Parser::ParseDeclarationSpecifiers(
break;
case tok::kw_auto:
if (getLangOpts().CPlusPlus11 || getLangOpts().C23) {
-if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
+auto IsTypeSpecifier = [&]() {
+ if (DS.getTypeSpecWidth() != TypeSpecifierWidth::Unspecified)
+return true;
+
+ unsigned I = 1;
+ while (GetLookAheadToken(I).isOneOf(tok::kw_const, tok::kw_volatile,
+ tok::kw_restrict))
+++I;
+
+ return isKnownToBeTypeSpecifier(GetLookAheadToken(I));
+};
+
+if (IsTypeSpecifier()) {
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
PrevSpec, DiagID, Policy);
if (!isInvalid && !getLangOpts().C23)
diff --git a/clang/test/Parser/c2x-auto.c b/clang/test/Parser/c2x-auto.c
index 7f80b0717ab25..cee670bf7b952 100644
--- a/clang/test/Parser/c2x-auto.c
+++ b/clang/test/Parser/c2x-auto.c
@@ -147,7 +147,7 @@ auto int b1 = 0; // c23-error {{illegal storage class on
file-scoped variable}}
int auto b2 = 0; // c23-error {{cannot combine with previous 'int' declaration
specifier}} \
c17-error {{illegal storage class on file-scoped variable}}
-void f() {
+void t1() {
constexpr auto int c1 = 0; // c23-error {{cannot combine with previous
'auto' declaration specifier}} \
c17-error {{use of undeclared identifier
'constexpr'}}
@@ -157,3 +157,25 @@ void f() {
auto int d1 = 0;
int auto d2 = 0; // c23-error {{cannot combine with previous 'int'
declaration specifier}}
}
+
+void t2() {
+ auto long long a1 = 0;
+ long auto long a2 = 0;
+ long long auto a3 = 0;
+
+ auto const long long b1 = 0;
+ long long const auto b2 = 0;
+ long long auto const b3 = 0;
+}
+
+void t3() {
+ const auto int a1 = 0;
+ auto const int a2 = 0;
+
+ volatile auto int a3 = 0;
+ auto volatile int a4 = 0;
+ auto volatile const int a5 = 0;
+ auto const volatile int a6 = 0;
+
+ auto restrict int a7 = 0; // expected-error {{restrict requires a pointer or
reference ('int' is invalid}}
+}
>From 16e85becd7905f2896892541e76f6f3e7bb1b1b1 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk
Date: Tue, 27 Jan 2026 13:27:10 +0200
Subject: [PATCH 2/6] handle reordered c23 auto with type-specifier qualifiers
---
clang/include/clang/Parse/Parser.h| 8 ++--
clang/lib/Parse/ParseDecl.cpp | 31 ++-
clang/lib/Parse/ParseObjc.cpp | 2 +-
clang/test/AST/ByteCode/constexpr.c | 4 +-
.../dcl.spec.auto/p3-generic-lambda-1y.cpp| 6 +--
clang/test/Parser/c2x-auto.c | 39 ---
clang/test/Sema/c2x-auto.c| 4 +-
clang/test/Sema/constexpr.c | 4 +-
clang/test/SemaCXX/auto-cxx0x.cpp | 2 +-
9 files changed, 71 insertions(+), 29 deletions(-)
diff --git a/clang/include/clang/Parse/Parser.h
b/clang/include/clang/Parse/Parser.h
index cd7dc14701914..1af9a91a76c41 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -2017,7 +2017,7 @@ class Parser : public CodeCompletionHandler {
/// isTypeSpecifierQualifier - Return true if the current token could be the
/// start of a specifier-qualifier-list.
- bool isTypeSpecifierQualifier();
+ bool isTypeSpecifierQualifier(const Token &Tok);
/// isKnownToBeTypeSpecifier - Return true if we know that the specified
token
/// is definitely a type-specifier. Return false if it isn't part of a type
@@ -4335,7 +4335,7 @@ class Parser : public CodeCompletionHandler {
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
github-actions[bot] wrote: # :penguin: Linux x64 Test Results * 87242 tests passed * 1375 tests skipped * 1 test failed ## Failed Tests (click on a test name to see its output) ### lldb-api lldb-api.python_api/run_locker/TestRunLocker.py ``` Script: -- /usr/bin/python3 /home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/test/API/dotest.py -u CXXFLAGS -u CFLAGS --env LLVM_LIBS_DIR=/home/gha/actions-runner/_work/llvm-project/llvm-project/build/./lib --env LLVM_INCLUDE_DIR=/home/gha/actions-runner/_work/llvm-project/llvm-project/build/include --env LLVM_TOOLS_DIR=/home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin --libcxx-include-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/include/c++/v1 --libcxx-include-target-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/include/x86_64-unknown-linux-gnu/c++/v1 --libcxx-library-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/./lib/x86_64-unknown-linux-gnu --arch x86_64 --build-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/lldb-test-build.noindex --lldb-module-cache-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/lldb-test-build.noindex/module-cache-lldb/lldb-api --clang-module-cache-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/lldb-test-build.noindex/module-cache-clang/lldb-api --executable /home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin/lldb --compiler /home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin/clang --dsymutil /home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin/dsymutil --make /usr/bin/gmake --llvm-tools-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/./bin --lldb-obj-root /home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/lldb --lldb-libs-dir /home/gha/actions-runner/_work/llvm-project/llvm-project/build/./lib --cmake-build-type Release /home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/test/API/python_api/run_locker -p TestRunLocker.py -- Exit Code: 1 Command Output (stdout): -- lldb version 23.0.0git (https://github.com/llvm/llvm-project revision 635f7f5adf2cd56968d9f54537a4e22f626d856a) clang revision 635f7f5adf2cd56968d9f54537a4e22f626d856a llvm revision 635f7f5adf2cd56968d9f54537a4e22f626d856a "can't evaluate expressions when the process is running." Skipping the following test categories: msvcstl, dsym, pdb, gmodules, debugserver, objc -- Command Output (stderr): -- Traceback (most recent call last): File "", line 1, in AttributeError: 'NoneType' object has no attribute 'EvaluateExpression' FAIL: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_run_locker (TestRunLocker.TestRunLocker.test_run_locker) Log Files: - /home/gha/actions-runner/_work/llvm-project/llvm-project/build/lldb-test-build.noindex/python_api/run_locker/TestRunLocker/Failure_test_run_locker.log PASS: LLDB (/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang-x86_64) :: test_run_locker_stop_at_entry (TestRunLocker.TestRunLocker.test_run_locker_stop_at_entry) == FAIL: test_run_locker (TestRunLocker.TestRunLocker.test_run_locker) Test that the run locker is set correctly when we launch -- Traceback (most recent call last): File "/home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/packages/Python/lldbsuite/test/decorators.py", line 160, in wrapper return func(*args, **kwargs) ^ File "/home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/test/API/python_api/run_locker/TestRunLocker.py", line 23, in test_run_locker self.runlocker_test(False) File "/home/gha/actions-runner/_work/llvm-project/llvm-project/lldb/test/API/python_api/run_locker/TestRunLocker.py", line 110, in runlocker_test self.assertIn( AssertionError: "can't evaluate expressions when the process is running" not found in '' Config=x86_64-/home/gha/actions-runner/_work/llvm-project/llvm-project/build/bin/clang -- Ran 2 tests in 0.771s FAILED (failures=1) -- ``` If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the `infrastructure` label. https://github.com/llvm/llvm-project/pull/177865 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
https://github.com/a-tarasyuk updated
https://github.com/llvm/llvm-project/pull/177865
>From 886c342fcf9a2a84929f6fb3eb51ea74de5c6b83 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk
Date: Sun, 25 Jan 2026 19:05:45 +0200
Subject: [PATCH 1/6] [Clang] prevent incorrect rejection of auto with
reordered declaration specifiers in C23
---
clang/docs/ReleaseNotes.rst | 1 +
clang/lib/Parse/ParseDecl.cpp | 14 +-
clang/test/Parser/c2x-auto.c | 24 +++-
3 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a734804865c57..47e578448e1e8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -169,6 +169,7 @@ Bug Fixes in This Version
-
- Fix lifetime extension of temporaries in for-range-initializers in
templates. (#GH165182)
+- Fixed incorrect rejection of ``auto`` with reordered declaration specifiers
in C23. (#GH164121)
Bug Fixes to Compiler Builtins
^^
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index f8c49646fcf3f..404f0a312b8bf 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -4093,7 +4093,19 @@ void Parser::ParseDeclarationSpecifiers(
break;
case tok::kw_auto:
if (getLangOpts().CPlusPlus11 || getLangOpts().C23) {
-if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
+auto IsTypeSpecifier = [&]() {
+ if (DS.getTypeSpecWidth() != TypeSpecifierWidth::Unspecified)
+return true;
+
+ unsigned I = 1;
+ while (GetLookAheadToken(I).isOneOf(tok::kw_const, tok::kw_volatile,
+ tok::kw_restrict))
+++I;
+
+ return isKnownToBeTypeSpecifier(GetLookAheadToken(I));
+};
+
+if (IsTypeSpecifier()) {
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
PrevSpec, DiagID, Policy);
if (!isInvalid && !getLangOpts().C23)
diff --git a/clang/test/Parser/c2x-auto.c b/clang/test/Parser/c2x-auto.c
index 7f80b0717ab25..cee670bf7b952 100644
--- a/clang/test/Parser/c2x-auto.c
+++ b/clang/test/Parser/c2x-auto.c
@@ -147,7 +147,7 @@ auto int b1 = 0; // c23-error {{illegal storage class on
file-scoped variable}}
int auto b2 = 0; // c23-error {{cannot combine with previous 'int' declaration
specifier}} \
c17-error {{illegal storage class on file-scoped variable}}
-void f() {
+void t1() {
constexpr auto int c1 = 0; // c23-error {{cannot combine with previous
'auto' declaration specifier}} \
c17-error {{use of undeclared identifier
'constexpr'}}
@@ -157,3 +157,25 @@ void f() {
auto int d1 = 0;
int auto d2 = 0; // c23-error {{cannot combine with previous 'int'
declaration specifier}}
}
+
+void t2() {
+ auto long long a1 = 0;
+ long auto long a2 = 0;
+ long long auto a3 = 0;
+
+ auto const long long b1 = 0;
+ long long const auto b2 = 0;
+ long long auto const b3 = 0;
+}
+
+void t3() {
+ const auto int a1 = 0;
+ auto const int a2 = 0;
+
+ volatile auto int a3 = 0;
+ auto volatile int a4 = 0;
+ auto volatile const int a5 = 0;
+ auto const volatile int a6 = 0;
+
+ auto restrict int a7 = 0; // expected-error {{restrict requires a pointer or
reference ('int' is invalid}}
+}
>From 16e85becd7905f2896892541e76f6f3e7bb1b1b1 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk
Date: Tue, 27 Jan 2026 13:27:10 +0200
Subject: [PATCH 2/6] handle reordered c23 auto with type-specifier qualifiers
---
clang/include/clang/Parse/Parser.h| 8 ++--
clang/lib/Parse/ParseDecl.cpp | 31 ++-
clang/lib/Parse/ParseObjc.cpp | 2 +-
clang/test/AST/ByteCode/constexpr.c | 4 +-
.../dcl.spec.auto/p3-generic-lambda-1y.cpp| 6 +--
clang/test/Parser/c2x-auto.c | 39 ---
clang/test/Sema/c2x-auto.c| 4 +-
clang/test/Sema/constexpr.c | 4 +-
clang/test/SemaCXX/auto-cxx0x.cpp | 2 +-
9 files changed, 71 insertions(+), 29 deletions(-)
diff --git a/clang/include/clang/Parse/Parser.h
b/clang/include/clang/Parse/Parser.h
index cd7dc14701914..1af9a91a76c41 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -2017,7 +2017,7 @@ class Parser : public CodeCompletionHandler {
/// isTypeSpecifierQualifier - Return true if the current token could be the
/// start of a specifier-qualifier-list.
- bool isTypeSpecifierQualifier();
+ bool isTypeSpecifierQualifier(const Token &Tok);
/// isKnownToBeTypeSpecifier - Return true if we know that the specified
token
/// is definitely a type-specifier. Return false if it isn't part of a type
@@ -4335,7 +4335,7 @@ class Parser : public CodeCompletionHandler {
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
https://github.com/a-tarasyuk updated
https://github.com/llvm/llvm-project/pull/177865
>From 886c342fcf9a2a84929f6fb3eb51ea74de5c6b83 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk
Date: Sun, 25 Jan 2026 19:05:45 +0200
Subject: [PATCH 1/6] [Clang] prevent incorrect rejection of auto with
reordered declaration specifiers in C23
---
clang/docs/ReleaseNotes.rst | 1 +
clang/lib/Parse/ParseDecl.cpp | 14 +-
clang/test/Parser/c2x-auto.c | 24 +++-
3 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a734804865c57..47e578448e1e8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -169,6 +169,7 @@ Bug Fixes in This Version
-
- Fix lifetime extension of temporaries in for-range-initializers in
templates. (#GH165182)
+- Fixed incorrect rejection of ``auto`` with reordered declaration specifiers
in C23. (#GH164121)
Bug Fixes to Compiler Builtins
^^
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index f8c49646fcf3f..404f0a312b8bf 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -4093,7 +4093,19 @@ void Parser::ParseDeclarationSpecifiers(
break;
case tok::kw_auto:
if (getLangOpts().CPlusPlus11 || getLangOpts().C23) {
-if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
+auto IsTypeSpecifier = [&]() {
+ if (DS.getTypeSpecWidth() != TypeSpecifierWidth::Unspecified)
+return true;
+
+ unsigned I = 1;
+ while (GetLookAheadToken(I).isOneOf(tok::kw_const, tok::kw_volatile,
+ tok::kw_restrict))
+++I;
+
+ return isKnownToBeTypeSpecifier(GetLookAheadToken(I));
+};
+
+if (IsTypeSpecifier()) {
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
PrevSpec, DiagID, Policy);
if (!isInvalid && !getLangOpts().C23)
diff --git a/clang/test/Parser/c2x-auto.c b/clang/test/Parser/c2x-auto.c
index 7f80b0717ab25..cee670bf7b952 100644
--- a/clang/test/Parser/c2x-auto.c
+++ b/clang/test/Parser/c2x-auto.c
@@ -147,7 +147,7 @@ auto int b1 = 0; // c23-error {{illegal storage class on
file-scoped variable}}
int auto b2 = 0; // c23-error {{cannot combine with previous 'int' declaration
specifier}} \
c17-error {{illegal storage class on file-scoped variable}}
-void f() {
+void t1() {
constexpr auto int c1 = 0; // c23-error {{cannot combine with previous
'auto' declaration specifier}} \
c17-error {{use of undeclared identifier
'constexpr'}}
@@ -157,3 +157,25 @@ void f() {
auto int d1 = 0;
int auto d2 = 0; // c23-error {{cannot combine with previous 'int'
declaration specifier}}
}
+
+void t2() {
+ auto long long a1 = 0;
+ long auto long a2 = 0;
+ long long auto a3 = 0;
+
+ auto const long long b1 = 0;
+ long long const auto b2 = 0;
+ long long auto const b3 = 0;
+}
+
+void t3() {
+ const auto int a1 = 0;
+ auto const int a2 = 0;
+
+ volatile auto int a3 = 0;
+ auto volatile int a4 = 0;
+ auto volatile const int a5 = 0;
+ auto const volatile int a6 = 0;
+
+ auto restrict int a7 = 0; // expected-error {{restrict requires a pointer or
reference ('int' is invalid}}
+}
>From 16e85becd7905f2896892541e76f6f3e7bb1b1b1 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk
Date: Tue, 27 Jan 2026 13:27:10 +0200
Subject: [PATCH 2/6] handle reordered c23 auto with type-specifier qualifiers
---
clang/include/clang/Parse/Parser.h| 8 ++--
clang/lib/Parse/ParseDecl.cpp | 31 ++-
clang/lib/Parse/ParseObjc.cpp | 2 +-
clang/test/AST/ByteCode/constexpr.c | 4 +-
.../dcl.spec.auto/p3-generic-lambda-1y.cpp| 6 +--
clang/test/Parser/c2x-auto.c | 39 ---
clang/test/Sema/c2x-auto.c| 4 +-
clang/test/Sema/constexpr.c | 4 +-
clang/test/SemaCXX/auto-cxx0x.cpp | 2 +-
9 files changed, 71 insertions(+), 29 deletions(-)
diff --git a/clang/include/clang/Parse/Parser.h
b/clang/include/clang/Parse/Parser.h
index cd7dc14701914..1af9a91a76c41 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -2017,7 +2017,7 @@ class Parser : public CodeCompletionHandler {
/// isTypeSpecifierQualifier - Return true if the current token could be the
/// start of a specifier-qualifier-list.
- bool isTypeSpecifierQualifier();
+ bool isTypeSpecifierQualifier(const Token &Tok);
/// isKnownToBeTypeSpecifier - Return true if we know that the specified
token
/// is definitely a type-specifier. Return false if it isn't part of a type
@@ -4335,7 +4335,7 @@ class Parser : public CodeCompletionHandler {
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
https://github.com/Fznamznon approved this pull request. Sorry, for delay. I don't have any concerns anymore. https://github.com/llvm/llvm-project/pull/177865 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
https://github.com/a-tarasyuk updated
https://github.com/llvm/llvm-project/pull/177865
>From 886c342fcf9a2a84929f6fb3eb51ea74de5c6b83 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk
Date: Sun, 25 Jan 2026 19:05:45 +0200
Subject: [PATCH 1/5] [Clang] prevent incorrect rejection of auto with
reordered declaration specifiers in C23
---
clang/docs/ReleaseNotes.rst | 1 +
clang/lib/Parse/ParseDecl.cpp | 14 +-
clang/test/Parser/c2x-auto.c | 24 +++-
3 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a734804865c57..47e578448e1e8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -169,6 +169,7 @@ Bug Fixes in This Version
-
- Fix lifetime extension of temporaries in for-range-initializers in
templates. (#GH165182)
+- Fixed incorrect rejection of ``auto`` with reordered declaration specifiers
in C23. (#GH164121)
Bug Fixes to Compiler Builtins
^^
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index f8c49646fcf3f..404f0a312b8bf 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -4093,7 +4093,19 @@ void Parser::ParseDeclarationSpecifiers(
break;
case tok::kw_auto:
if (getLangOpts().CPlusPlus11 || getLangOpts().C23) {
-if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
+auto IsTypeSpecifier = [&]() {
+ if (DS.getTypeSpecWidth() != TypeSpecifierWidth::Unspecified)
+return true;
+
+ unsigned I = 1;
+ while (GetLookAheadToken(I).isOneOf(tok::kw_const, tok::kw_volatile,
+ tok::kw_restrict))
+++I;
+
+ return isKnownToBeTypeSpecifier(GetLookAheadToken(I));
+};
+
+if (IsTypeSpecifier()) {
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
PrevSpec, DiagID, Policy);
if (!isInvalid && !getLangOpts().C23)
diff --git a/clang/test/Parser/c2x-auto.c b/clang/test/Parser/c2x-auto.c
index 7f80b0717ab25..cee670bf7b952 100644
--- a/clang/test/Parser/c2x-auto.c
+++ b/clang/test/Parser/c2x-auto.c
@@ -147,7 +147,7 @@ auto int b1 = 0; // c23-error {{illegal storage class on
file-scoped variable}}
int auto b2 = 0; // c23-error {{cannot combine with previous 'int' declaration
specifier}} \
c17-error {{illegal storage class on file-scoped variable}}
-void f() {
+void t1() {
constexpr auto int c1 = 0; // c23-error {{cannot combine with previous
'auto' declaration specifier}} \
c17-error {{use of undeclared identifier
'constexpr'}}
@@ -157,3 +157,25 @@ void f() {
auto int d1 = 0;
int auto d2 = 0; // c23-error {{cannot combine with previous 'int'
declaration specifier}}
}
+
+void t2() {
+ auto long long a1 = 0;
+ long auto long a2 = 0;
+ long long auto a3 = 0;
+
+ auto const long long b1 = 0;
+ long long const auto b2 = 0;
+ long long auto const b3 = 0;
+}
+
+void t3() {
+ const auto int a1 = 0;
+ auto const int a2 = 0;
+
+ volatile auto int a3 = 0;
+ auto volatile int a4 = 0;
+ auto volatile const int a5 = 0;
+ auto const volatile int a6 = 0;
+
+ auto restrict int a7 = 0; // expected-error {{restrict requires a pointer or
reference ('int' is invalid}}
+}
>From 16e85becd7905f2896892541e76f6f3e7bb1b1b1 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk
Date: Tue, 27 Jan 2026 13:27:10 +0200
Subject: [PATCH 2/5] handle reordered c23 auto with type-specifier qualifiers
---
clang/include/clang/Parse/Parser.h| 8 ++--
clang/lib/Parse/ParseDecl.cpp | 31 ++-
clang/lib/Parse/ParseObjc.cpp | 2 +-
clang/test/AST/ByteCode/constexpr.c | 4 +-
.../dcl.spec.auto/p3-generic-lambda-1y.cpp| 6 +--
clang/test/Parser/c2x-auto.c | 39 ---
clang/test/Sema/c2x-auto.c| 4 +-
clang/test/Sema/constexpr.c | 4 +-
clang/test/SemaCXX/auto-cxx0x.cpp | 2 +-
9 files changed, 71 insertions(+), 29 deletions(-)
diff --git a/clang/include/clang/Parse/Parser.h
b/clang/include/clang/Parse/Parser.h
index cd7dc14701914..1af9a91a76c41 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -2017,7 +2017,7 @@ class Parser : public CodeCompletionHandler {
/// isTypeSpecifierQualifier - Return true if the current token could be the
/// start of a specifier-qualifier-list.
- bool isTypeSpecifierQualifier();
+ bool isTypeSpecifierQualifier(const Token &Tok);
/// isKnownToBeTypeSpecifier - Return true if we know that the specified
token
/// is definitely a type-specifier. Return false if it isn't part of a type
@@ -4335,7 +4335,7 @@ class Parser : public CodeCompletionHandler {
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
https://github.com/a-tarasyuk updated
https://github.com/llvm/llvm-project/pull/177865
>From 886c342fcf9a2a84929f6fb3eb51ea74de5c6b83 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk
Date: Sun, 25 Jan 2026 19:05:45 +0200
Subject: [PATCH 1/5] [Clang] prevent incorrect rejection of auto with
reordered declaration specifiers in C23
---
clang/docs/ReleaseNotes.rst | 1 +
clang/lib/Parse/ParseDecl.cpp | 14 +-
clang/test/Parser/c2x-auto.c | 24 +++-
3 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a734804865c57..47e578448e1e8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -169,6 +169,7 @@ Bug Fixes in This Version
-
- Fix lifetime extension of temporaries in for-range-initializers in
templates. (#GH165182)
+- Fixed incorrect rejection of ``auto`` with reordered declaration specifiers
in C23. (#GH164121)
Bug Fixes to Compiler Builtins
^^
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index f8c49646fcf3f..404f0a312b8bf 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -4093,7 +4093,19 @@ void Parser::ParseDeclarationSpecifiers(
break;
case tok::kw_auto:
if (getLangOpts().CPlusPlus11 || getLangOpts().C23) {
-if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
+auto IsTypeSpecifier = [&]() {
+ if (DS.getTypeSpecWidth() != TypeSpecifierWidth::Unspecified)
+return true;
+
+ unsigned I = 1;
+ while (GetLookAheadToken(I).isOneOf(tok::kw_const, tok::kw_volatile,
+ tok::kw_restrict))
+++I;
+
+ return isKnownToBeTypeSpecifier(GetLookAheadToken(I));
+};
+
+if (IsTypeSpecifier()) {
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
PrevSpec, DiagID, Policy);
if (!isInvalid && !getLangOpts().C23)
diff --git a/clang/test/Parser/c2x-auto.c b/clang/test/Parser/c2x-auto.c
index 7f80b0717ab25..cee670bf7b952 100644
--- a/clang/test/Parser/c2x-auto.c
+++ b/clang/test/Parser/c2x-auto.c
@@ -147,7 +147,7 @@ auto int b1 = 0; // c23-error {{illegal storage class on
file-scoped variable}}
int auto b2 = 0; // c23-error {{cannot combine with previous 'int' declaration
specifier}} \
c17-error {{illegal storage class on file-scoped variable}}
-void f() {
+void t1() {
constexpr auto int c1 = 0; // c23-error {{cannot combine with previous
'auto' declaration specifier}} \
c17-error {{use of undeclared identifier
'constexpr'}}
@@ -157,3 +157,25 @@ void f() {
auto int d1 = 0;
int auto d2 = 0; // c23-error {{cannot combine with previous 'int'
declaration specifier}}
}
+
+void t2() {
+ auto long long a1 = 0;
+ long auto long a2 = 0;
+ long long auto a3 = 0;
+
+ auto const long long b1 = 0;
+ long long const auto b2 = 0;
+ long long auto const b3 = 0;
+}
+
+void t3() {
+ const auto int a1 = 0;
+ auto const int a2 = 0;
+
+ volatile auto int a3 = 0;
+ auto volatile int a4 = 0;
+ auto volatile const int a5 = 0;
+ auto const volatile int a6 = 0;
+
+ auto restrict int a7 = 0; // expected-error {{restrict requires a pointer or
reference ('int' is invalid}}
+}
>From 16e85becd7905f2896892541e76f6f3e7bb1b1b1 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk
Date: Tue, 27 Jan 2026 13:27:10 +0200
Subject: [PATCH 2/5] handle reordered c23 auto with type-specifier qualifiers
---
clang/include/clang/Parse/Parser.h| 8 ++--
clang/lib/Parse/ParseDecl.cpp | 31 ++-
clang/lib/Parse/ParseObjc.cpp | 2 +-
clang/test/AST/ByteCode/constexpr.c | 4 +-
.../dcl.spec.auto/p3-generic-lambda-1y.cpp| 6 +--
clang/test/Parser/c2x-auto.c | 39 ---
clang/test/Sema/c2x-auto.c| 4 +-
clang/test/Sema/constexpr.c | 4 +-
clang/test/SemaCXX/auto-cxx0x.cpp | 2 +-
9 files changed, 71 insertions(+), 29 deletions(-)
diff --git a/clang/include/clang/Parse/Parser.h
b/clang/include/clang/Parse/Parser.h
index cd7dc14701914..1af9a91a76c41 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -2017,7 +2017,7 @@ class Parser : public CodeCompletionHandler {
/// isTypeSpecifierQualifier - Return true if the current token could be the
/// start of a specifier-qualifier-list.
- bool isTypeSpecifierQualifier();
+ bool isTypeSpecifierQualifier(const Token &Tok);
/// isKnownToBeTypeSpecifier - Return true if we know that the specified
token
/// is definitely a type-specifier. Return false if it isn't part of a type
@@ -4335,7 +4335,7 @@ class Parser : public CodeCompletionHandler {
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
@@ -4093,7 +4093,26 @@ void Parser::ParseDeclarationSpecifiers(
break;
case tok::kw_auto:
if (getLangOpts().CPlusPlus11 || getLangOpts().C23) {
-if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
+auto MayBeTypeSpecifier = [&]() {
+ if (getLangOpts().C23 && DS.hasTypeSpecifier() &&
+ DS.getTypeSpecType() != DeclSpec::TST_auto &&
+ DS.getConstexprSpecifier() == ConstexprSpecKind::Unspecified)
+return true;
+
+ unsigned I = 1;
+ while (true) {
a-tarasyuk wrote:
@AaronBallman, when you have a moment, could you please take a look at the
latest changes?
https://github.com/llvm/llvm-project/pull/177865
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
https://github.com/a-tarasyuk updated https://github.com/llvm/llvm-project/pull/177865 503 Service Unavailable No server is available to handle this request. ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
https://github.com/a-tarasyuk updated
https://github.com/llvm/llvm-project/pull/177865
>From 886c342fcf9a2a84929f6fb3eb51ea74de5c6b83 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk
Date: Sun, 25 Jan 2026 19:05:45 +0200
Subject: [PATCH 1/4] [Clang] prevent incorrect rejection of auto with
reordered declaration specifiers in C23
---
clang/docs/ReleaseNotes.rst | 1 +
clang/lib/Parse/ParseDecl.cpp | 14 +-
clang/test/Parser/c2x-auto.c | 24 +++-
3 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a734804865c57..47e578448e1e8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -169,6 +169,7 @@ Bug Fixes in This Version
-
- Fix lifetime extension of temporaries in for-range-initializers in
templates. (#GH165182)
+- Fixed incorrect rejection of ``auto`` with reordered declaration specifiers
in C23. (#GH164121)
Bug Fixes to Compiler Builtins
^^
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index f8c49646fcf3f..404f0a312b8bf 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -4093,7 +4093,19 @@ void Parser::ParseDeclarationSpecifiers(
break;
case tok::kw_auto:
if (getLangOpts().CPlusPlus11 || getLangOpts().C23) {
-if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
+auto IsTypeSpecifier = [&]() {
+ if (DS.getTypeSpecWidth() != TypeSpecifierWidth::Unspecified)
+return true;
+
+ unsigned I = 1;
+ while (GetLookAheadToken(I).isOneOf(tok::kw_const, tok::kw_volatile,
+ tok::kw_restrict))
+++I;
+
+ return isKnownToBeTypeSpecifier(GetLookAheadToken(I));
+};
+
+if (IsTypeSpecifier()) {
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
PrevSpec, DiagID, Policy);
if (!isInvalid && !getLangOpts().C23)
diff --git a/clang/test/Parser/c2x-auto.c b/clang/test/Parser/c2x-auto.c
index 7f80b0717ab25..cee670bf7b952 100644
--- a/clang/test/Parser/c2x-auto.c
+++ b/clang/test/Parser/c2x-auto.c
@@ -147,7 +147,7 @@ auto int b1 = 0; // c23-error {{illegal storage class on
file-scoped variable}}
int auto b2 = 0; // c23-error {{cannot combine with previous 'int' declaration
specifier}} \
c17-error {{illegal storage class on file-scoped variable}}
-void f() {
+void t1() {
constexpr auto int c1 = 0; // c23-error {{cannot combine with previous
'auto' declaration specifier}} \
c17-error {{use of undeclared identifier
'constexpr'}}
@@ -157,3 +157,25 @@ void f() {
auto int d1 = 0;
int auto d2 = 0; // c23-error {{cannot combine with previous 'int'
declaration specifier}}
}
+
+void t2() {
+ auto long long a1 = 0;
+ long auto long a2 = 0;
+ long long auto a3 = 0;
+
+ auto const long long b1 = 0;
+ long long const auto b2 = 0;
+ long long auto const b3 = 0;
+}
+
+void t3() {
+ const auto int a1 = 0;
+ auto const int a2 = 0;
+
+ volatile auto int a3 = 0;
+ auto volatile int a4 = 0;
+ auto volatile const int a5 = 0;
+ auto const volatile int a6 = 0;
+
+ auto restrict int a7 = 0; // expected-error {{restrict requires a pointer or
reference ('int' is invalid}}
+}
>From 16e85becd7905f2896892541e76f6f3e7bb1b1b1 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk
Date: Tue, 27 Jan 2026 13:27:10 +0200
Subject: [PATCH 2/4] handle reordered c23 auto with type-specifier qualifiers
---
clang/include/clang/Parse/Parser.h| 8 ++--
clang/lib/Parse/ParseDecl.cpp | 31 ++-
clang/lib/Parse/ParseObjc.cpp | 2 +-
clang/test/AST/ByteCode/constexpr.c | 4 +-
.../dcl.spec.auto/p3-generic-lambda-1y.cpp| 6 +--
clang/test/Parser/c2x-auto.c | 39 ---
clang/test/Sema/c2x-auto.c| 4 +-
clang/test/Sema/constexpr.c | 4 +-
clang/test/SemaCXX/auto-cxx0x.cpp | 2 +-
9 files changed, 71 insertions(+), 29 deletions(-)
diff --git a/clang/include/clang/Parse/Parser.h
b/clang/include/clang/Parse/Parser.h
index cd7dc14701914..1af9a91a76c41 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -2017,7 +2017,7 @@ class Parser : public CodeCompletionHandler {
/// isTypeSpecifierQualifier - Return true if the current token could be the
/// start of a specifier-qualifier-list.
- bool isTypeSpecifierQualifier();
+ bool isTypeSpecifierQualifier(const Token &Tok);
/// isKnownToBeTypeSpecifier - Return true if we know that the specified
token
/// is definitely a type-specifier. Return false if it isn't part of a type
@@ -4335,7 +4335,7 @@ class Parser : public CodeCompletionHandler {
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
https://github.com/a-tarasyuk updated
https://github.com/llvm/llvm-project/pull/177865
>From 886c342fcf9a2a84929f6fb3eb51ea74de5c6b83 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk
Date: Sun, 25 Jan 2026 19:05:45 +0200
Subject: [PATCH 1/4] [Clang] prevent incorrect rejection of auto with
reordered declaration specifiers in C23
---
clang/docs/ReleaseNotes.rst | 1 +
clang/lib/Parse/ParseDecl.cpp | 14 +-
clang/test/Parser/c2x-auto.c | 24 +++-
3 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a734804865c57..47e578448e1e8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -169,6 +169,7 @@ Bug Fixes in This Version
-
- Fix lifetime extension of temporaries in for-range-initializers in
templates. (#GH165182)
+- Fixed incorrect rejection of ``auto`` with reordered declaration specifiers
in C23. (#GH164121)
Bug Fixes to Compiler Builtins
^^
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index f8c49646fcf3f..404f0a312b8bf 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -4093,7 +4093,19 @@ void Parser::ParseDeclarationSpecifiers(
break;
case tok::kw_auto:
if (getLangOpts().CPlusPlus11 || getLangOpts().C23) {
-if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
+auto IsTypeSpecifier = [&]() {
+ if (DS.getTypeSpecWidth() != TypeSpecifierWidth::Unspecified)
+return true;
+
+ unsigned I = 1;
+ while (GetLookAheadToken(I).isOneOf(tok::kw_const, tok::kw_volatile,
+ tok::kw_restrict))
+++I;
+
+ return isKnownToBeTypeSpecifier(GetLookAheadToken(I));
+};
+
+if (IsTypeSpecifier()) {
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
PrevSpec, DiagID, Policy);
if (!isInvalid && !getLangOpts().C23)
diff --git a/clang/test/Parser/c2x-auto.c b/clang/test/Parser/c2x-auto.c
index 7f80b0717ab25..cee670bf7b952 100644
--- a/clang/test/Parser/c2x-auto.c
+++ b/clang/test/Parser/c2x-auto.c
@@ -147,7 +147,7 @@ auto int b1 = 0; // c23-error {{illegal storage class on
file-scoped variable}}
int auto b2 = 0; // c23-error {{cannot combine with previous 'int' declaration
specifier}} \
c17-error {{illegal storage class on file-scoped variable}}
-void f() {
+void t1() {
constexpr auto int c1 = 0; // c23-error {{cannot combine with previous
'auto' declaration specifier}} \
c17-error {{use of undeclared identifier
'constexpr'}}
@@ -157,3 +157,25 @@ void f() {
auto int d1 = 0;
int auto d2 = 0; // c23-error {{cannot combine with previous 'int'
declaration specifier}}
}
+
+void t2() {
+ auto long long a1 = 0;
+ long auto long a2 = 0;
+ long long auto a3 = 0;
+
+ auto const long long b1 = 0;
+ long long const auto b2 = 0;
+ long long auto const b3 = 0;
+}
+
+void t3() {
+ const auto int a1 = 0;
+ auto const int a2 = 0;
+
+ volatile auto int a3 = 0;
+ auto volatile int a4 = 0;
+ auto volatile const int a5 = 0;
+ auto const volatile int a6 = 0;
+
+ auto restrict int a7 = 0; // expected-error {{restrict requires a pointer or
reference ('int' is invalid}}
+}
>From 16e85becd7905f2896892541e76f6f3e7bb1b1b1 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk
Date: Tue, 27 Jan 2026 13:27:10 +0200
Subject: [PATCH 2/4] handle reordered c23 auto with type-specifier qualifiers
---
clang/include/clang/Parse/Parser.h| 8 ++--
clang/lib/Parse/ParseDecl.cpp | 31 ++-
clang/lib/Parse/ParseObjc.cpp | 2 +-
clang/test/AST/ByteCode/constexpr.c | 4 +-
.../dcl.spec.auto/p3-generic-lambda-1y.cpp| 6 +--
clang/test/Parser/c2x-auto.c | 39 ---
clang/test/Sema/c2x-auto.c| 4 +-
clang/test/Sema/constexpr.c | 4 +-
clang/test/SemaCXX/auto-cxx0x.cpp | 2 +-
9 files changed, 71 insertions(+), 29 deletions(-)
diff --git a/clang/include/clang/Parse/Parser.h
b/clang/include/clang/Parse/Parser.h
index cd7dc14701914..1af9a91a76c41 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -2017,7 +2017,7 @@ class Parser : public CodeCompletionHandler {
/// isTypeSpecifierQualifier - Return true if the current token could be the
/// start of a specifier-qualifier-list.
- bool isTypeSpecifierQualifier();
+ bool isTypeSpecifierQualifier(const Token &Tok);
/// isKnownToBeTypeSpecifier - Return true if we know that the specified
token
/// is definitely a type-specifier. Return false if it isn't part of a type
@@ -4335,7 +4335,7 @@ class Parser : public CodeCompletionHandler {
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
https://github.com/a-tarasyuk updated
https://github.com/llvm/llvm-project/pull/177865
>From 886c342fcf9a2a84929f6fb3eb51ea74de5c6b83 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk
Date: Sun, 25 Jan 2026 19:05:45 +0200
Subject: [PATCH 1/4] [Clang] prevent incorrect rejection of auto with
reordered declaration specifiers in C23
---
clang/docs/ReleaseNotes.rst | 1 +
clang/lib/Parse/ParseDecl.cpp | 14 +-
clang/test/Parser/c2x-auto.c | 24 +++-
3 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a734804865c57..47e578448e1e8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -169,6 +169,7 @@ Bug Fixes in This Version
-
- Fix lifetime extension of temporaries in for-range-initializers in
templates. (#GH165182)
+- Fixed incorrect rejection of ``auto`` with reordered declaration specifiers
in C23. (#GH164121)
Bug Fixes to Compiler Builtins
^^
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index f8c49646fcf3f..404f0a312b8bf 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -4093,7 +4093,19 @@ void Parser::ParseDeclarationSpecifiers(
break;
case tok::kw_auto:
if (getLangOpts().CPlusPlus11 || getLangOpts().C23) {
-if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
+auto IsTypeSpecifier = [&]() {
+ if (DS.getTypeSpecWidth() != TypeSpecifierWidth::Unspecified)
+return true;
+
+ unsigned I = 1;
+ while (GetLookAheadToken(I).isOneOf(tok::kw_const, tok::kw_volatile,
+ tok::kw_restrict))
+++I;
+
+ return isKnownToBeTypeSpecifier(GetLookAheadToken(I));
+};
+
+if (IsTypeSpecifier()) {
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
PrevSpec, DiagID, Policy);
if (!isInvalid && !getLangOpts().C23)
diff --git a/clang/test/Parser/c2x-auto.c b/clang/test/Parser/c2x-auto.c
index 7f80b0717ab25..cee670bf7b952 100644
--- a/clang/test/Parser/c2x-auto.c
+++ b/clang/test/Parser/c2x-auto.c
@@ -147,7 +147,7 @@ auto int b1 = 0; // c23-error {{illegal storage class on
file-scoped variable}}
int auto b2 = 0; // c23-error {{cannot combine with previous 'int' declaration
specifier}} \
c17-error {{illegal storage class on file-scoped variable}}
-void f() {
+void t1() {
constexpr auto int c1 = 0; // c23-error {{cannot combine with previous
'auto' declaration specifier}} \
c17-error {{use of undeclared identifier
'constexpr'}}
@@ -157,3 +157,25 @@ void f() {
auto int d1 = 0;
int auto d2 = 0; // c23-error {{cannot combine with previous 'int'
declaration specifier}}
}
+
+void t2() {
+ auto long long a1 = 0;
+ long auto long a2 = 0;
+ long long auto a3 = 0;
+
+ auto const long long b1 = 0;
+ long long const auto b2 = 0;
+ long long auto const b3 = 0;
+}
+
+void t3() {
+ const auto int a1 = 0;
+ auto const int a2 = 0;
+
+ volatile auto int a3 = 0;
+ auto volatile int a4 = 0;
+ auto volatile const int a5 = 0;
+ auto const volatile int a6 = 0;
+
+ auto restrict int a7 = 0; // expected-error {{restrict requires a pointer or
reference ('int' is invalid}}
+}
>From 16e85becd7905f2896892541e76f6f3e7bb1b1b1 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk
Date: Tue, 27 Jan 2026 13:27:10 +0200
Subject: [PATCH 2/4] handle reordered c23 auto with type-specifier qualifiers
---
clang/include/clang/Parse/Parser.h| 8 ++--
clang/lib/Parse/ParseDecl.cpp | 31 ++-
clang/lib/Parse/ParseObjc.cpp | 2 +-
clang/test/AST/ByteCode/constexpr.c | 4 +-
.../dcl.spec.auto/p3-generic-lambda-1y.cpp| 6 +--
clang/test/Parser/c2x-auto.c | 39 ---
clang/test/Sema/c2x-auto.c| 4 +-
clang/test/Sema/constexpr.c | 4 +-
clang/test/SemaCXX/auto-cxx0x.cpp | 2 +-
9 files changed, 71 insertions(+), 29 deletions(-)
diff --git a/clang/include/clang/Parse/Parser.h
b/clang/include/clang/Parse/Parser.h
index cd7dc14701914..1af9a91a76c41 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -2017,7 +2017,7 @@ class Parser : public CodeCompletionHandler {
/// isTypeSpecifierQualifier - Return true if the current token could be the
/// start of a specifier-qualifier-list.
- bool isTypeSpecifierQualifier();
+ bool isTypeSpecifierQualifier(const Token &Tok);
/// isKnownToBeTypeSpecifier - Return true if we know that the specified
token
/// is definitely a type-specifier. Return false if it isn't part of a type
@@ -4335,7 +4335,7 @@ class Parser : public CodeCompletionHandler {
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
@@ -4093,7 +4093,26 @@ void Parser::ParseDeclarationSpecifiers(
break;
case tok::kw_auto:
if (getLangOpts().CPlusPlus11 || getLangOpts().C23) {
-if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
+auto MayBeTypeSpecifier = [&]() {
+ if (getLangOpts().C23 && DS.hasTypeSpecifier() &&
+ DS.getTypeSpecType() != DeclSpec::TST_auto &&
+ DS.getConstexprSpecifier() == ConstexprSpecKind::Unspecified)
a-tarasyuk wrote:
What I noticed is that emitting the `previous` diagnostic assumes the specifier
was parsed earlier, but that isn’t always guaranteed. Since we don’t verify
this when choosing the diagnostic, the result can be misleading. Using a more
general `invalid use of '%0' with '%1'` diagnostic may be safer...
https://github.com/llvm/llvm-project/pull/177865
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
@@ -4093,7 +4093,26 @@ void Parser::ParseDeclarationSpecifiers(
break;
case tok::kw_auto:
if (getLangOpts().CPlusPlus11 || getLangOpts().C23) {
-if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
+auto MayBeTypeSpecifier = [&]() {
+ if (getLangOpts().C23 && DS.hasTypeSpecifier() &&
+ DS.getTypeSpecType() != DeclSpec::TST_auto &&
+ DS.getConstexprSpecifier() == ConstexprSpecKind::Unspecified)
a-tarasyuk wrote:
@AaronBallman, thanks for the feedback. The current implementation doesn’t
handle auto-ordering. In cases like:
```cpp
void f() {
constexpr [/*1*/|int|] [|/*2*/auto]] c2 = 0;
}
```
the code path sets the `TypeSpecType` (as a result, diagnostics can differ)
https://github.com/llvm/llvm-project/blob/10afcd405ed44e69c25f7239e94b93e6368a5043/clang/lib/Parse/ParseDecl.cpp#L4103-L4104
instead of
https://github.com/llvm/llvm-project/blob/10afcd405ed44e69c25f7239e94b93e6368a5043/clang/lib/Parse/ParseDecl.cpp#L4097-L4101
which leads to different diagnostics and, in some cases, odd results. I believe
that’s incorrect, so I removed the `DS.getConstexprSpecifier() ==
ConstexprSpecKind::Unspecified` check. For example, in the following code, the
diagnostic should point to `constexpr`, not at `int`:
```cpp
void f() {
constexpr int auto c2 = 0;
}
```
because this code is accepted
```cpp
void f() {
int auto c2 = 0;
}
```
WDYT?
https://github.com/llvm/llvm-project/pull/177865
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
@@ -4093,7 +4093,26 @@ void Parser::ParseDeclarationSpecifiers(
break;
case tok::kw_auto:
if (getLangOpts().CPlusPlus11 || getLangOpts().C23) {
-if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
+auto MayBeTypeSpecifier = [&]() {
+ if (getLangOpts().C23 && DS.hasTypeSpecifier() &&
+ DS.getTypeSpecType() != DeclSpec::TST_auto &&
+ DS.getConstexprSpecifier() == ConstexprSpecKind::Unspecified)
+return true;
+
+ unsigned I = 1;
+ while (true) {
a-tarasyuk wrote:
@AaronBallman I think this should apply only in C23 mode, so I’ve added that
restriction., thanks
https://github.com/llvm/llvm-project/pull/177865
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
https://github.com/a-tarasyuk updated
https://github.com/llvm/llvm-project/pull/177865
>From 886c342fcf9a2a84929f6fb3eb51ea74de5c6b83 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk
Date: Sun, 25 Jan 2026 19:05:45 +0200
Subject: [PATCH 1/4] [Clang] prevent incorrect rejection of auto with
reordered declaration specifiers in C23
---
clang/docs/ReleaseNotes.rst | 1 +
clang/lib/Parse/ParseDecl.cpp | 14 +-
clang/test/Parser/c2x-auto.c | 24 +++-
3 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a734804865c57..47e578448e1e8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -169,6 +169,7 @@ Bug Fixes in This Version
-
- Fix lifetime extension of temporaries in for-range-initializers in
templates. (#GH165182)
+- Fixed incorrect rejection of ``auto`` with reordered declaration specifiers
in C23. (#GH164121)
Bug Fixes to Compiler Builtins
^^
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index f8c49646fcf3f..404f0a312b8bf 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -4093,7 +4093,19 @@ void Parser::ParseDeclarationSpecifiers(
break;
case tok::kw_auto:
if (getLangOpts().CPlusPlus11 || getLangOpts().C23) {
-if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
+auto IsTypeSpecifier = [&]() {
+ if (DS.getTypeSpecWidth() != TypeSpecifierWidth::Unspecified)
+return true;
+
+ unsigned I = 1;
+ while (GetLookAheadToken(I).isOneOf(tok::kw_const, tok::kw_volatile,
+ tok::kw_restrict))
+++I;
+
+ return isKnownToBeTypeSpecifier(GetLookAheadToken(I));
+};
+
+if (IsTypeSpecifier()) {
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
PrevSpec, DiagID, Policy);
if (!isInvalid && !getLangOpts().C23)
diff --git a/clang/test/Parser/c2x-auto.c b/clang/test/Parser/c2x-auto.c
index 7f80b0717ab25..cee670bf7b952 100644
--- a/clang/test/Parser/c2x-auto.c
+++ b/clang/test/Parser/c2x-auto.c
@@ -147,7 +147,7 @@ auto int b1 = 0; // c23-error {{illegal storage class on
file-scoped variable}}
int auto b2 = 0; // c23-error {{cannot combine with previous 'int' declaration
specifier}} \
c17-error {{illegal storage class on file-scoped variable}}
-void f() {
+void t1() {
constexpr auto int c1 = 0; // c23-error {{cannot combine with previous
'auto' declaration specifier}} \
c17-error {{use of undeclared identifier
'constexpr'}}
@@ -157,3 +157,25 @@ void f() {
auto int d1 = 0;
int auto d2 = 0; // c23-error {{cannot combine with previous 'int'
declaration specifier}}
}
+
+void t2() {
+ auto long long a1 = 0;
+ long auto long a2 = 0;
+ long long auto a3 = 0;
+
+ auto const long long b1 = 0;
+ long long const auto b2 = 0;
+ long long auto const b3 = 0;
+}
+
+void t3() {
+ const auto int a1 = 0;
+ auto const int a2 = 0;
+
+ volatile auto int a3 = 0;
+ auto volatile int a4 = 0;
+ auto volatile const int a5 = 0;
+ auto const volatile int a6 = 0;
+
+ auto restrict int a7 = 0; // expected-error {{restrict requires a pointer or
reference ('int' is invalid}}
+}
>From 16e85becd7905f2896892541e76f6f3e7bb1b1b1 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk
Date: Tue, 27 Jan 2026 13:27:10 +0200
Subject: [PATCH 2/4] handle reordered c23 auto with type-specifier qualifiers
---
clang/include/clang/Parse/Parser.h| 8 ++--
clang/lib/Parse/ParseDecl.cpp | 31 ++-
clang/lib/Parse/ParseObjc.cpp | 2 +-
clang/test/AST/ByteCode/constexpr.c | 4 +-
.../dcl.spec.auto/p3-generic-lambda-1y.cpp| 6 +--
clang/test/Parser/c2x-auto.c | 39 ---
clang/test/Sema/c2x-auto.c| 4 +-
clang/test/Sema/constexpr.c | 4 +-
clang/test/SemaCXX/auto-cxx0x.cpp | 2 +-
9 files changed, 71 insertions(+), 29 deletions(-)
diff --git a/clang/include/clang/Parse/Parser.h
b/clang/include/clang/Parse/Parser.h
index cd7dc14701914..1af9a91a76c41 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -2017,7 +2017,7 @@ class Parser : public CodeCompletionHandler {
/// isTypeSpecifierQualifier - Return true if the current token could be the
/// start of a specifier-qualifier-list.
- bool isTypeSpecifierQualifier();
+ bool isTypeSpecifierQualifier(const Token &Tok);
/// isKnownToBeTypeSpecifier - Return true if we know that the specified
token
/// is definitely a type-specifier. Return false if it isn't part of a type
@@ -4335,7 +4335,7 @@ class Parser : public CodeCompletionHandler {
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
@@ -4093,7 +4093,26 @@ void Parser::ParseDeclarationSpecifiers(
break;
case tok::kw_auto:
if (getLangOpts().CPlusPlus11 || getLangOpts().C23) {
-if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
+auto MayBeTypeSpecifier = [&]() {
+ if (getLangOpts().C23 && DS.hasTypeSpecifier() &&
+ DS.getTypeSpecType() != DeclSpec::TST_auto &&
+ DS.getConstexprSpecifier() == ConstexprSpecKind::Unspecified)
AaronBallman wrote:
Can you help me understand why we need to check for `constexpr` explicitly?
https://github.com/llvm/llvm-project/pull/177865
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
https://github.com/AaronBallman commented: The test behavior now looks correct to me, though I had some questions https://github.com/llvm/llvm-project/pull/177865 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
https://github.com/AaronBallman edited https://github.com/llvm/llvm-project/pull/177865 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
@@ -4093,7 +4093,26 @@ void Parser::ParseDeclarationSpecifiers(
break;
case tok::kw_auto:
if (getLangOpts().CPlusPlus11 || getLangOpts().C23) {
-if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
+auto MayBeTypeSpecifier = [&]() {
+ if (getLangOpts().C23 && DS.hasTypeSpecifier() &&
+ DS.getTypeSpecType() != DeclSpec::TST_auto &&
+ DS.getConstexprSpecifier() == ConstexprSpecKind::Unspecified)
+return true;
+
+ unsigned I = 1;
+ while (true) {
AaronBallman wrote:
Outside of C23 mode, do we need to do this lookahead? e.g., should the code
path for C++ remain the same as it was before?
https://github.com/llvm/llvm-project/pull/177865
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
https://github.com/a-tarasyuk updated
https://github.com/llvm/llvm-project/pull/177865
>From 886c342fcf9a2a84929f6fb3eb51ea74de5c6b83 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk
Date: Sun, 25 Jan 2026 19:05:45 +0200
Subject: [PATCH 1/3] [Clang] prevent incorrect rejection of auto with
reordered declaration specifiers in C23
---
clang/docs/ReleaseNotes.rst | 1 +
clang/lib/Parse/ParseDecl.cpp | 14 +-
clang/test/Parser/c2x-auto.c | 24 +++-
3 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a734804865c57..47e578448e1e8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -169,6 +169,7 @@ Bug Fixes in This Version
-
- Fix lifetime extension of temporaries in for-range-initializers in
templates. (#GH165182)
+- Fixed incorrect rejection of ``auto`` with reordered declaration specifiers
in C23. (#GH164121)
Bug Fixes to Compiler Builtins
^^
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index f8c49646fcf3f..404f0a312b8bf 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -4093,7 +4093,19 @@ void Parser::ParseDeclarationSpecifiers(
break;
case tok::kw_auto:
if (getLangOpts().CPlusPlus11 || getLangOpts().C23) {
-if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
+auto IsTypeSpecifier = [&]() {
+ if (DS.getTypeSpecWidth() != TypeSpecifierWidth::Unspecified)
+return true;
+
+ unsigned I = 1;
+ while (GetLookAheadToken(I).isOneOf(tok::kw_const, tok::kw_volatile,
+ tok::kw_restrict))
+++I;
+
+ return isKnownToBeTypeSpecifier(GetLookAheadToken(I));
+};
+
+if (IsTypeSpecifier()) {
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
PrevSpec, DiagID, Policy);
if (!isInvalid && !getLangOpts().C23)
diff --git a/clang/test/Parser/c2x-auto.c b/clang/test/Parser/c2x-auto.c
index 7f80b0717ab25..cee670bf7b952 100644
--- a/clang/test/Parser/c2x-auto.c
+++ b/clang/test/Parser/c2x-auto.c
@@ -147,7 +147,7 @@ auto int b1 = 0; // c23-error {{illegal storage class on
file-scoped variable}}
int auto b2 = 0; // c23-error {{cannot combine with previous 'int' declaration
specifier}} \
c17-error {{illegal storage class on file-scoped variable}}
-void f() {
+void t1() {
constexpr auto int c1 = 0; // c23-error {{cannot combine with previous
'auto' declaration specifier}} \
c17-error {{use of undeclared identifier
'constexpr'}}
@@ -157,3 +157,25 @@ void f() {
auto int d1 = 0;
int auto d2 = 0; // c23-error {{cannot combine with previous 'int'
declaration specifier}}
}
+
+void t2() {
+ auto long long a1 = 0;
+ long auto long a2 = 0;
+ long long auto a3 = 0;
+
+ auto const long long b1 = 0;
+ long long const auto b2 = 0;
+ long long auto const b3 = 0;
+}
+
+void t3() {
+ const auto int a1 = 0;
+ auto const int a2 = 0;
+
+ volatile auto int a3 = 0;
+ auto volatile int a4 = 0;
+ auto volatile const int a5 = 0;
+ auto const volatile int a6 = 0;
+
+ auto restrict int a7 = 0; // expected-error {{restrict requires a pointer or
reference ('int' is invalid}}
+}
>From 16e85becd7905f2896892541e76f6f3e7bb1b1b1 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk
Date: Tue, 27 Jan 2026 13:27:10 +0200
Subject: [PATCH 2/3] handle reordered c23 auto with type-specifier qualifiers
---
clang/include/clang/Parse/Parser.h| 8 ++--
clang/lib/Parse/ParseDecl.cpp | 31 ++-
clang/lib/Parse/ParseObjc.cpp | 2 +-
clang/test/AST/ByteCode/constexpr.c | 4 +-
.../dcl.spec.auto/p3-generic-lambda-1y.cpp| 6 +--
clang/test/Parser/c2x-auto.c | 39 ---
clang/test/Sema/c2x-auto.c| 4 +-
clang/test/Sema/constexpr.c | 4 +-
clang/test/SemaCXX/auto-cxx0x.cpp | 2 +-
9 files changed, 71 insertions(+), 29 deletions(-)
diff --git a/clang/include/clang/Parse/Parser.h
b/clang/include/clang/Parse/Parser.h
index cd7dc14701914..1af9a91a76c41 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -2017,7 +2017,7 @@ class Parser : public CodeCompletionHandler {
/// isTypeSpecifierQualifier - Return true if the current token could be the
/// start of a specifier-qualifier-list.
- bool isTypeSpecifierQualifier();
+ bool isTypeSpecifierQualifier(const Token &Tok);
/// isKnownToBeTypeSpecifier - Return true if we know that the specified
token
/// is definitely a type-specifier. Return false if it isn't part of a type
@@ -4335,7 +4335,7 @@ class Parser : public CodeCompletionHandler {
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
@@ -39,7 +39,9 @@ constexpr auto Ulong = 1L;
constexpr auto CompoundLiteral = (int){13};
constexpr auto DoubleCast = (double)(1 / 3);
constexpr auto String = "this is a string"; // both-error {{constexpr pointer
initializer is not null}}
-constexpr signed auto Long = 1L; // both-error {{'auto' cannot be signed or
unsigned}}
+// both-error@+2 {{cannot combine with previous 'auto' declaration specifier}}
+// both-error@+1 {{illegal storage class on file-scoped variable}}
AaronBallman wrote:
The "cannot combine" diagnostic is unfortunate because what is the "previous"
auto declaration specifier? I think the original diagnostic behavior was a bit
better, though the "illegal storage class on file-scoped variable" is
reasonable to emit as well.
https://github.com/llvm/llvm-project/pull/177865
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
@@ -4093,7 +4093,30 @@ void Parser::ParseDeclarationSpecifiers(
break;
case tok::kw_auto:
if (getLangOpts().CPlusPlus11 || getLangOpts().C23) {
-if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
+auto IsTypeSpecifier = [&]() {
+ if (DS.hasTypeSpecifier() &&
+ DS.getTypeSpecType() != DeclSpec::TST_auto)
+return true;
+
+ unsigned I = 1;
+ while (true) {
+const Token &T = GetLookAheadToken(I);
+if (isKnownToBeTypeSpecifier(T))
+ return true;
+
+if (T.isOneOf(tok::kw_typeof, tok::kw_typeof_unqual,
+ tok::kw__Atomic) &&
+GetLookAheadToken(I + 1).is(tok::l_paren))
+ return true;
AaronBallman wrote:
What happens with code like:
```
void func() {
signed int _Atomic auto i = 12; // Accept due to valid but useless storage
class specifier
}
signed int _Atomic auto j = 12; // Reject due to invalid storage class specifier
```
https://github.com/llvm/llvm-project/pull/177865
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
@@ -63,12 +63,10 @@ int main()
auto l = [](auto
(*)(auto)) { }; //expected-error{{'auto' not allowed}}
//FIXME: These diagnostics might need some work.
-auto l2 = [](char auto::*pm) { }; //expected-error{{cannot combine with
previous}}\
- expected-error{{'pm' does not point
into a class}}
+auto l2 = [](char auto::*pm) { }; // expected-error {{'pm' does not point
into a class}} \
+ expected-warning {{'auto' storage
class specifier is not permitted in C++11, and will not be supported in future
releases}}
AaronBallman wrote:
The new diagnostic here is incorrect, isn't it? It's not complaining about
`auto l2` which would be almost like a storage class specifier use, it's
complaining about `auto::*pm`, right? Neither the old nor the new diagnostic is
particularly helpful, so I suppose this one is a wash.
https://github.com/llvm/llvm-project/pull/177865
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
https://github.com/AaronBallman edited https://github.com/llvm/llvm-project/pull/177865 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
@@ -137,23 +137,74 @@ constexpr auto int a1 = 0; // c23-error {{illegal storage
class on file-scoped v
c17-error {{illegal storage class on file-scoped
variable}} \
c17-error {{unknown type name 'constexpr'}}
-constexpr int auto a2 = 0; // c23-error {{cannot combine with previous 'int'
declaration specifier}} \
+constexpr int auto a2 = 0; // c23-error {{cannot combine with previous 'auto'
declaration specifier}} \
+ c23-error {{illegal storage class on file-scoped
variable}} \
c17-error {{illegal storage class on file-scoped
variable}} \
c17-error {{unknown type name 'constexpr'}}
auto int b1 = 0; // c23-error {{illegal storage class on file-scoped
variable}} \
c17-error {{illegal storage class on file-scoped variable}}
-int auto b2 = 0; // c23-error {{cannot combine with previous 'int' declaration
specifier}} \
+int auto b2 = 0; // c23-error {{illegal storage class on file-scoped
variable}} \
c17-error {{illegal storage class on file-scoped variable}}
-void f() {
+long auto long i = 0; // c23-error {{illegal storage class on file-scoped
variable}} \
+ c17-error {{illegal storage class on file-scoped
variable}}
+
+void t1() {
constexpr auto int c1 = 0; // c23-error {{cannot combine with previous
'auto' declaration specifier}} \
c17-error {{use of undeclared identifier
'constexpr'}}
- constexpr int auto c2 = 0; // c23-error {{cannot combine with previous 'int'
declaration specifier}} \
+ constexpr int auto c2 = 0; // c23-error {{cannot combine with previous
'auto' declaration specifier}} \
c17-error {{use of undeclared identifier
'constexpr'}}
auto int d1 = 0;
- int auto d2 = 0; // c23-error {{cannot combine with previous 'int'
declaration specifier}}
+ int auto d2 = 0;
+}
+
+void t2() {
+ auto long long a1 = 0;
+ long auto long a2 = 0;
+ long long auto a3 = 0;
+
+ auto const long long b1 = 0;
+ long long const auto b2 = 0;
+ long long auto const b3 = 0;
+}
+
+void t3() {
+ const auto int a1 = 0;
+ auto const int a2 = 0;
+
+ volatile auto int a3 = 0;
+ auto volatile int a4 = 0;
+ auto volatile const int a5 = 0;
+ auto const volatile int a6 = 0;
+
+ auto restrict int a7 = 0; // expected-error {{restrict requires a pointer
or reference ('int' is invalid)}}
+}
+
+void t4() {
+ static long auto long s1 = 0; // c23-error {{cannot combine with previous
'static' declaration specifier}} \
+ c17-error {{cannot combine with previous
'static' declaration specifier}}
+ extern long auto long e2; // c23-error {{cannot combine with previous
'extern' declaration specifier}} \
+ c17-error {{cannot combine with previous
'extern' declaration specifier}}
+}
+
+void t5(void) {
+ const long auto long unsigned volatile _Atomic int x = 0;
AaronBallman wrote:
This would be a good test case for global scope to ensure that `auto` is still
rejected as a storage class specifier there.
https://github.com/llvm/llvm-project/pull/177865
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
https://github.com/AaronBallman commented: Based on the diagnostic behavior, I'm not certain this is quite right still. I think the previous diagnostic behavior was generally better in a number of places. WDYT? https://github.com/llvm/llvm-project/pull/177865 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
@@ -137,23 +137,74 @@ constexpr auto int a1 = 0; // c23-error {{illegal storage
class on file-scoped v
c17-error {{illegal storage class on file-scoped
variable}} \
c17-error {{unknown type name 'constexpr'}}
-constexpr int auto a2 = 0; // c23-error {{cannot combine with previous 'int'
declaration specifier}} \
+constexpr int auto a2 = 0; // c23-error {{cannot combine with previous 'auto'
declaration specifier}} \
AaronBallman wrote:
The "cannot combine" diagnostic here is harder to understand because there's no
"previous" auto specifier.
https://github.com/llvm/llvm-project/pull/177865
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
https://github.com/a-tarasyuk updated
https://github.com/llvm/llvm-project/pull/177865
>From 886c342fcf9a2a84929f6fb3eb51ea74de5c6b83 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk
Date: Sun, 25 Jan 2026 19:05:45 +0200
Subject: [PATCH 1/2] [Clang] prevent incorrect rejection of auto with
reordered declaration specifiers in C23
---
clang/docs/ReleaseNotes.rst | 1 +
clang/lib/Parse/ParseDecl.cpp | 14 +-
clang/test/Parser/c2x-auto.c | 24 +++-
3 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a734804865c57..47e578448e1e8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -169,6 +169,7 @@ Bug Fixes in This Version
-
- Fix lifetime extension of temporaries in for-range-initializers in
templates. (#GH165182)
+- Fixed incorrect rejection of ``auto`` with reordered declaration specifiers
in C23. (#GH164121)
Bug Fixes to Compiler Builtins
^^
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index f8c49646fcf3f..404f0a312b8bf 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -4093,7 +4093,19 @@ void Parser::ParseDeclarationSpecifiers(
break;
case tok::kw_auto:
if (getLangOpts().CPlusPlus11 || getLangOpts().C23) {
-if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
+auto IsTypeSpecifier = [&]() {
+ if (DS.getTypeSpecWidth() != TypeSpecifierWidth::Unspecified)
+return true;
+
+ unsigned I = 1;
+ while (GetLookAheadToken(I).isOneOf(tok::kw_const, tok::kw_volatile,
+ tok::kw_restrict))
+++I;
+
+ return isKnownToBeTypeSpecifier(GetLookAheadToken(I));
+};
+
+if (IsTypeSpecifier()) {
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
PrevSpec, DiagID, Policy);
if (!isInvalid && !getLangOpts().C23)
diff --git a/clang/test/Parser/c2x-auto.c b/clang/test/Parser/c2x-auto.c
index 7f80b0717ab25..cee670bf7b952 100644
--- a/clang/test/Parser/c2x-auto.c
+++ b/clang/test/Parser/c2x-auto.c
@@ -147,7 +147,7 @@ auto int b1 = 0; // c23-error {{illegal storage class on
file-scoped variable}}
int auto b2 = 0; // c23-error {{cannot combine with previous 'int' declaration
specifier}} \
c17-error {{illegal storage class on file-scoped variable}}
-void f() {
+void t1() {
constexpr auto int c1 = 0; // c23-error {{cannot combine with previous
'auto' declaration specifier}} \
c17-error {{use of undeclared identifier
'constexpr'}}
@@ -157,3 +157,25 @@ void f() {
auto int d1 = 0;
int auto d2 = 0; // c23-error {{cannot combine with previous 'int'
declaration specifier}}
}
+
+void t2() {
+ auto long long a1 = 0;
+ long auto long a2 = 0;
+ long long auto a3 = 0;
+
+ auto const long long b1 = 0;
+ long long const auto b2 = 0;
+ long long auto const b3 = 0;
+}
+
+void t3() {
+ const auto int a1 = 0;
+ auto const int a2 = 0;
+
+ volatile auto int a3 = 0;
+ auto volatile int a4 = 0;
+ auto volatile const int a5 = 0;
+ auto const volatile int a6 = 0;
+
+ auto restrict int a7 = 0; // expected-error {{restrict requires a pointer or
reference ('int' is invalid}}
+}
>From 16e85becd7905f2896892541e76f6f3e7bb1b1b1 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk
Date: Tue, 27 Jan 2026 13:27:10 +0200
Subject: [PATCH 2/2] handle reordered c23 auto with type-specifier qualifiers
---
clang/include/clang/Parse/Parser.h| 8 ++--
clang/lib/Parse/ParseDecl.cpp | 31 ++-
clang/lib/Parse/ParseObjc.cpp | 2 +-
clang/test/AST/ByteCode/constexpr.c | 4 +-
.../dcl.spec.auto/p3-generic-lambda-1y.cpp| 6 +--
clang/test/Parser/c2x-auto.c | 39 ---
clang/test/Sema/c2x-auto.c| 4 +-
clang/test/Sema/constexpr.c | 4 +-
clang/test/SemaCXX/auto-cxx0x.cpp | 2 +-
9 files changed, 71 insertions(+), 29 deletions(-)
diff --git a/clang/include/clang/Parse/Parser.h
b/clang/include/clang/Parse/Parser.h
index cd7dc14701914..1af9a91a76c41 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -2017,7 +2017,7 @@ class Parser : public CodeCompletionHandler {
/// isTypeSpecifierQualifier - Return true if the current token could be the
/// start of a specifier-qualifier-list.
- bool isTypeSpecifierQualifier();
+ bool isTypeSpecifierQualifier(const Token &Tok);
/// isKnownToBeTypeSpecifier - Return true if we know that the specified
token
/// is definitely a type-specifier. Return false if it isn't part of a type
@@ -4335,7 +4335,7 @@ class Parser : public CodeCompletionHandler {
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
a-tarasyuk wrote: @cor3ntin @AaronBallman Thank you for your feedback. I have updated the logic to use `isTypeSpecifierQualifier()`, with exception handling for the `_Atomic(` and `typeof(` forms. I am unsure whether `isKnownToBeTypeSpecifier()` should be extended for `_Atomic` or `typeof`, since it is unclear if it should recognize only the keyword or the keyword followed by `(`. https://github.com/llvm/llvm-project/pull/177865 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
https://github.com/a-tarasyuk updated
https://github.com/llvm/llvm-project/pull/177865
>From 886c342fcf9a2a84929f6fb3eb51ea74de5c6b83 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk
Date: Sun, 25 Jan 2026 19:05:45 +0200
Subject: [PATCH 1/2] [Clang] prevent incorrect rejection of auto with
reordered declaration specifiers in C23
---
clang/docs/ReleaseNotes.rst | 1 +
clang/lib/Parse/ParseDecl.cpp | 14 +-
clang/test/Parser/c2x-auto.c | 24 +++-
3 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a734804865c57..47e578448e1e8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -169,6 +169,7 @@ Bug Fixes in This Version
-
- Fix lifetime extension of temporaries in for-range-initializers in
templates. (#GH165182)
+- Fixed incorrect rejection of ``auto`` with reordered declaration specifiers
in C23. (#GH164121)
Bug Fixes to Compiler Builtins
^^
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index f8c49646fcf3f..404f0a312b8bf 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -4093,7 +4093,19 @@ void Parser::ParseDeclarationSpecifiers(
break;
case tok::kw_auto:
if (getLangOpts().CPlusPlus11 || getLangOpts().C23) {
-if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
+auto IsTypeSpecifier = [&]() {
+ if (DS.getTypeSpecWidth() != TypeSpecifierWidth::Unspecified)
+return true;
+
+ unsigned I = 1;
+ while (GetLookAheadToken(I).isOneOf(tok::kw_const, tok::kw_volatile,
+ tok::kw_restrict))
+++I;
+
+ return isKnownToBeTypeSpecifier(GetLookAheadToken(I));
+};
+
+if (IsTypeSpecifier()) {
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
PrevSpec, DiagID, Policy);
if (!isInvalid && !getLangOpts().C23)
diff --git a/clang/test/Parser/c2x-auto.c b/clang/test/Parser/c2x-auto.c
index 7f80b0717ab25..cee670bf7b952 100644
--- a/clang/test/Parser/c2x-auto.c
+++ b/clang/test/Parser/c2x-auto.c
@@ -147,7 +147,7 @@ auto int b1 = 0; // c23-error {{illegal storage class on
file-scoped variable}}
int auto b2 = 0; // c23-error {{cannot combine with previous 'int' declaration
specifier}} \
c17-error {{illegal storage class on file-scoped variable}}
-void f() {
+void t1() {
constexpr auto int c1 = 0; // c23-error {{cannot combine with previous
'auto' declaration specifier}} \
c17-error {{use of undeclared identifier
'constexpr'}}
@@ -157,3 +157,25 @@ void f() {
auto int d1 = 0;
int auto d2 = 0; // c23-error {{cannot combine with previous 'int'
declaration specifier}}
}
+
+void t2() {
+ auto long long a1 = 0;
+ long auto long a2 = 0;
+ long long auto a3 = 0;
+
+ auto const long long b1 = 0;
+ long long const auto b2 = 0;
+ long long auto const b3 = 0;
+}
+
+void t3() {
+ const auto int a1 = 0;
+ auto const int a2 = 0;
+
+ volatile auto int a3 = 0;
+ auto volatile int a4 = 0;
+ auto volatile const int a5 = 0;
+ auto const volatile int a6 = 0;
+
+ auto restrict int a7 = 0; // expected-error {{restrict requires a pointer or
reference ('int' is invalid}}
+}
>From 16e85becd7905f2896892541e76f6f3e7bb1b1b1 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk
Date: Tue, 27 Jan 2026 13:27:10 +0200
Subject: [PATCH 2/2] handle reordered c23 auto with type-specifier qualifiers
---
clang/include/clang/Parse/Parser.h| 8 ++--
clang/lib/Parse/ParseDecl.cpp | 31 ++-
clang/lib/Parse/ParseObjc.cpp | 2 +-
clang/test/AST/ByteCode/constexpr.c | 4 +-
.../dcl.spec.auto/p3-generic-lambda-1y.cpp| 6 +--
clang/test/Parser/c2x-auto.c | 39 ---
clang/test/Sema/c2x-auto.c| 4 +-
clang/test/Sema/constexpr.c | 4 +-
clang/test/SemaCXX/auto-cxx0x.cpp | 2 +-
9 files changed, 71 insertions(+), 29 deletions(-)
diff --git a/clang/include/clang/Parse/Parser.h
b/clang/include/clang/Parse/Parser.h
index cd7dc14701914..1af9a91a76c41 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -2017,7 +2017,7 @@ class Parser : public CodeCompletionHandler {
/// isTypeSpecifierQualifier - Return true if the current token could be the
/// start of a specifier-qualifier-list.
- bool isTypeSpecifierQualifier();
+ bool isTypeSpecifierQualifier(const Token &Tok);
/// isKnownToBeTypeSpecifier - Return true if we know that the specified
token
/// is definitely a type-specifier. Return false if it isn't part of a type
@@ -4335,7 +4335,7 @@ class Parser : public CodeCompletionHandler {
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
AaronBallman wrote:
> I am not sure this is the right approach.
>
> * There are many more qualifiers (`_Atomic` for example, but look at
> `isTypeSpecifierQualifier` for more of the complexity)
>
>
> I would like @AaronBallman to help us clarify the C23 rules. In particular as
> @Fznamznon mention, it is odd that `long auto long` would be allowed,
> although GCC accepts it. Is that a defect?
>
> The tests should probably check if the behavior is consistent with
> static/extern
It depends on whether `auto` is being used as a storage class specifier or not.
If it's being used as a storage class specifier, then the way the grammar falls
out you can do crazy things like [`const long auto long unsigned volatile
_Atomic i =12;`](https://godbolt.org/z/TKscPjfhq)
```
long auto long i = 12; // Diagnosed as an invalid use of a storage class
specifier
void func() {
long auto long l1 = 12; // Okay, should be accepted
static long auto long l2 = 12; // Diagnosed as a duplicate storage class
specifier
}
```
https://github.com/llvm/llvm-project/pull/177865
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
https://github.com/cor3ntin commented: I am not sure this is the right approach. - There are many more qualifiers (`_Atomic` for example, but look at `isTypeSpecifierQualifier` for more of the complexity) I would like @AaronBallman to help us clarify the C23 rules. In particular as @Fznamznon mention, it is odd that `long auto long` would be allowed, although GCC accepts it. Is that a defect? The tests should probably check if the behavior is consistent with static/extern https://github.com/llvm/llvm-project/pull/177865 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
llvmbot wrote:
@llvm/pr-subscribers-clang
Author: Oleksandr Tarasiuk (a-tarasyuk)
Changes
Fixes #164121
---
This patch addresses the issue where `auto` was incorrectly rejected with
reordered declaration specifiers in C23.
---
Full diff: https://github.com/llvm/llvm-project/pull/177865.diff
3 Files Affected:
- (modified) clang/docs/ReleaseNotes.rst (+1)
- (modified) clang/lib/Parse/ParseDecl.cpp (+13-1)
- (modified) clang/test/Parser/c2x-auto.c (+23-1)
``diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a734804865c57..47e578448e1e8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -169,6 +169,7 @@ Bug Fixes in This Version
-
- Fix lifetime extension of temporaries in for-range-initializers in
templates. (#GH165182)
+- Fixed incorrect rejection of ``auto`` with reordered declaration specifiers
in C23. (#GH164121)
Bug Fixes to Compiler Builtins
^^
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index f8c49646fcf3f..404f0a312b8bf 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -4093,7 +4093,19 @@ void Parser::ParseDeclarationSpecifiers(
break;
case tok::kw_auto:
if (getLangOpts().CPlusPlus11 || getLangOpts().C23) {
-if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
+auto IsTypeSpecifier = [&]() {
+ if (DS.getTypeSpecWidth() != TypeSpecifierWidth::Unspecified)
+return true;
+
+ unsigned I = 1;
+ while (GetLookAheadToken(I).isOneOf(tok::kw_const, tok::kw_volatile,
+ tok::kw_restrict))
+++I;
+
+ return isKnownToBeTypeSpecifier(GetLookAheadToken(I));
+};
+
+if (IsTypeSpecifier()) {
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
PrevSpec, DiagID, Policy);
if (!isInvalid && !getLangOpts().C23)
diff --git a/clang/test/Parser/c2x-auto.c b/clang/test/Parser/c2x-auto.c
index 7f80b0717ab25..cee670bf7b952 100644
--- a/clang/test/Parser/c2x-auto.c
+++ b/clang/test/Parser/c2x-auto.c
@@ -147,7 +147,7 @@ auto int b1 = 0; // c23-error {{illegal storage class on
file-scoped variable}}
int auto b2 = 0; // c23-error {{cannot combine with previous 'int' declaration
specifier}} \
c17-error {{illegal storage class on file-scoped variable}}
-void f() {
+void t1() {
constexpr auto int c1 = 0; // c23-error {{cannot combine with previous
'auto' declaration specifier}} \
c17-error {{use of undeclared identifier
'constexpr'}}
@@ -157,3 +157,25 @@ void f() {
auto int d1 = 0;
int auto d2 = 0; // c23-error {{cannot combine with previous 'int'
declaration specifier}}
}
+
+void t2() {
+ auto long long a1 = 0;
+ long auto long a2 = 0;
+ long long auto a3 = 0;
+
+ auto const long long b1 = 0;
+ long long const auto b2 = 0;
+ long long auto const b3 = 0;
+}
+
+void t3() {
+ const auto int a1 = 0;
+ auto const int a2 = 0;
+
+ volatile auto int a3 = 0;
+ auto volatile int a4 = 0;
+ auto volatile const int a5 = 0;
+ auto const volatile int a6 = 0;
+
+ auto restrict int a7 = 0; // expected-error {{restrict requires a pointer or
reference ('int' is invalid}}
+}
``
https://github.com/llvm/llvm-project/pull/177865
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] prevent incorrect rejection of auto with reordered declaration specifiers in C23 (PR #177865)
https://github.com/a-tarasyuk created
https://github.com/llvm/llvm-project/pull/177865
Fixes #164121
---
This patch addresses the issue where `auto` was incorrectly rejected with
reordered declaration specifiers in C23.
>From 886c342fcf9a2a84929f6fb3eb51ea74de5c6b83 Mon Sep 17 00:00:00 2001
From: Oleksandr Tarasiuk
Date: Sun, 25 Jan 2026 19:05:45 +0200
Subject: [PATCH] [Clang] prevent incorrect rejection of auto with reordered
declaration specifiers in C23
---
clang/docs/ReleaseNotes.rst | 1 +
clang/lib/Parse/ParseDecl.cpp | 14 +-
clang/test/Parser/c2x-auto.c | 24 +++-
3 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index a734804865c57..47e578448e1e8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -169,6 +169,7 @@ Bug Fixes in This Version
-
- Fix lifetime extension of temporaries in for-range-initializers in
templates. (#GH165182)
+- Fixed incorrect rejection of ``auto`` with reordered declaration specifiers
in C23. (#GH164121)
Bug Fixes to Compiler Builtins
^^
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index f8c49646fcf3f..404f0a312b8bf 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -4093,7 +4093,19 @@ void Parser::ParseDeclarationSpecifiers(
break;
case tok::kw_auto:
if (getLangOpts().CPlusPlus11 || getLangOpts().C23) {
-if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
+auto IsTypeSpecifier = [&]() {
+ if (DS.getTypeSpecWidth() != TypeSpecifierWidth::Unspecified)
+return true;
+
+ unsigned I = 1;
+ while (GetLookAheadToken(I).isOneOf(tok::kw_const, tok::kw_volatile,
+ tok::kw_restrict))
+++I;
+
+ return isKnownToBeTypeSpecifier(GetLookAheadToken(I));
+};
+
+if (IsTypeSpecifier()) {
isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
PrevSpec, DiagID, Policy);
if (!isInvalid && !getLangOpts().C23)
diff --git a/clang/test/Parser/c2x-auto.c b/clang/test/Parser/c2x-auto.c
index 7f80b0717ab25..cee670bf7b952 100644
--- a/clang/test/Parser/c2x-auto.c
+++ b/clang/test/Parser/c2x-auto.c
@@ -147,7 +147,7 @@ auto int b1 = 0; // c23-error {{illegal storage class on
file-scoped variable}}
int auto b2 = 0; // c23-error {{cannot combine with previous 'int' declaration
specifier}} \
c17-error {{illegal storage class on file-scoped variable}}
-void f() {
+void t1() {
constexpr auto int c1 = 0; // c23-error {{cannot combine with previous
'auto' declaration specifier}} \
c17-error {{use of undeclared identifier
'constexpr'}}
@@ -157,3 +157,25 @@ void f() {
auto int d1 = 0;
int auto d2 = 0; // c23-error {{cannot combine with previous 'int'
declaration specifier}}
}
+
+void t2() {
+ auto long long a1 = 0;
+ long auto long a2 = 0;
+ long long auto a3 = 0;
+
+ auto const long long b1 = 0;
+ long long const auto b2 = 0;
+ long long auto const b3 = 0;
+}
+
+void t3() {
+ const auto int a1 = 0;
+ auto const int a2 = 0;
+
+ volatile auto int a3 = 0;
+ auto volatile int a4 = 0;
+ auto volatile const int a5 = 0;
+ auto const volatile int a6 = 0;
+
+ auto restrict int a7 = 0; // expected-error {{restrict requires a pointer or
reference ('int' is invalid}}
+}
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
