From ae9c4a477dcfd1e0071d3f3b0a689f1efce94cd9 Mon Sep 17 00:00:00 2001 From: Aditya Date: Sat, 8 Nov 2025 17:40:00 +0000 Subject: [PATCH] [Sema] Error on 'auto' storage class in C++11 This patch changes the C-style 'auto' storage class specifier from a warning to an error in C++11 and later modes. This was previously allowed as an extension for C compatibility, but it's no longer appropriate for modern C++. Fixes #162473 --- .../clang/Basic/DiagnosticParseKinds.td | 2 ++ clang/lib/Parse/ParseDecl.cpp | 18 +++++++++++++----- clang/test/Parser/cxx-auto-type-specifier.cpp | 13 +++++++++++++ 3 files changed, 28 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 aa0ccb0c05101..d900001c8cde0 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -402,6 +402,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>; diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 5fcb659768655..65ed4db468b65 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -4095,11 +4095,19 @@ 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()); + // auto cannot be combined with a type specifier in C++ (except C23). + if (getLangOpts().CPlusPlus && !getLangOpts().C23) { + if (!PrevSpec) { + PrevSpec = ""; + } + isInvalid = true; + DiagID = diag::err_auto_type_specifier; + } else { + // In C23, 'auto' followed by a type specifier is a storage class 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..d8bce4b7170cf --- /dev/null +++ b/clang/test/Parser/cxx-auto-type-specifier.cpp @@ -0,0 +1,13 @@ +// 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 -x c %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++}} +} + +// c23-no-diagnostics