https://github.com/osamakader created 
https://github.com/llvm/llvm-project/pull/166004

Fixes #164273

>From 46b862ac21d19e7f4be0398035d39b827825e6c6 Mon Sep 17 00:00:00 2001
From: Osama Abdelkader <[email protected]>
Date: Sat, 1 Nov 2025 19:53:55 +0200
Subject: [PATCH] [clang] Reject 'auto' storage class with type specifier in
 C++

Previously, clang allowed 'auto int x = 1;' in C++ as an extension
(for C compatibility), emitting only a warning. This was confusing
since 'auto' in C++11+ is a type specifier, not a storage class.

This patch:
- Adds a new error diagnostic 'err_auto_type_specifier'
- Updates the parser to emit an error (instead of warning) when 'auto'
  is used as a storage class with a type specifier in C++ mode
- Preserves C23 behavior where 'auto int' is valid
- Adds comprehensive tests

Fixes #164273

Signed-off-by: Osama Abdelkader <[email protected]>
---
 .../clang/Basic/DiagnosticParseKinds.td       |  2 ++
 clang/lib/Parse/ParseDecl.cpp                 | 16 ++++++----
 clang/test/Parser/cxx-auto-type-specifier.cpp | 29 +++++++++++++++++++
 3 files changed, 42 insertions(+), 5 deletions(-)
 create mode 100644 clang/test/Parser/cxx-auto-type-specifier.cpp

diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td 
b/clang/include/clang/Basic/DiagnosticParseKinds.td
index e5e071f43fa75..baf91b107b8c4 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -399,6 +399,8 @@ def 
err_requires_clause_on_declarator_not_declaring_a_function : Error<
   "trailing requires clause can only be used when declaring a function">;
 def err_requires_clause_inside_parens : Error<
   "trailing requires clause should be placed outside parentheses">;
+def err_auto_type_specifier : Error<
+  "'auto' cannot be combined with a type specifier in C++">;
 def ext_auto_storage_class : ExtWarn<
   "'auto' storage class specifier is not permitted in C++11, and will not "
   "be supported in future releases">, InGroup<DiagGroup<"auto-storage-class">>;
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 7e4a164e34eda..0044201b459b3 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -4095,11 +4095,17 @@ void Parser::ParseDeclarationSpecifiers(
     case tok::kw_auto:
       if (getLangOpts().CPlusPlus11 || getLangOpts().C23) {
         if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {
-          isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,
-                                             PrevSpec, DiagID, Policy);
-          if (!isInvalid && !getLangOpts().C23)
-            Diag(Tok, diag::ext_auto_storage_class)
-              << FixItHint::CreateRemoval(DS.getStorageClassSpecLoc());
+          // In C++ (not C23), 'auto' cannot be combined with a type specifier.
+          if (getLangOpts().CPlusPlus && !getLangOpts().C23) {
+            isInvalid = true;
+            if (!PrevSpec)
+              PrevSpec = "";
+            DiagID = diag::err_auto_type_specifier;
+          } else {
+            // C23 allows 'auto' as storage class with type specifier.
+            isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, 
Loc,
+                                               PrevSpec, DiagID, Policy);
+          }
         } else
           isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec,
                                          DiagID, Policy);
diff --git a/clang/test/Parser/cxx-auto-type-specifier.cpp 
b/clang/test/Parser/cxx-auto-type-specifier.cpp
new file mode 100644
index 0000000000000..7a1291b08f7d3
--- /dev/null
+++ b/clang/test/Parser/cxx-auto-type-specifier.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++23 %s
+// RUN: %clang_cc1 -fsyntax-only -verify=c23 -std=c23 %s
+
+// Test that 'auto' cannot be combined with a type specifier in C++.
+void f() {
+  auto int x = 1;        // expected-error {{'auto' cannot be combined with a 
type specifier in C++}}
+  auto char c = 'a';    // expected-error {{'auto' cannot be combined with a 
type specifier in C++}}
+  auto float f = 1.0f;  // expected-error {{'auto' cannot be combined with a 
type specifier in C++}}
+  auto double d = 1.0;   // expected-error {{'auto' cannot be combined with a 
type specifier in C++}}
+  auto long l = 1L;     // expected-error {{'auto' cannot be combined with a 
type specifier in C++}}
+}
+
+// Test that 'auto' as a storage class with type specifier is still allowed in 
C23.
+void g() {
+  auto int x = 1;  // c23-no-diagnostics
+  auto char c = 'a';  // c23-no-diagnostics
+}
+
+// Test that regular 'auto' (type deduction) still works in C++.
+void h() {
+  auto x = 1;      // expected-no-diagnostics
+  auto y = 2.0;   // expected-no-diagnostics
+  auto z = 'c';   // expected-no-diagnostics
+}
+

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

Reply via email to