Skip to content

Commit cd50218

Browse files
committed
[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]>
1 parent 269f264 commit cd50218

File tree

9 files changed

+328
-250
lines changed

9 files changed

+328
-250
lines changed

clang/include/clang/Basic/DiagnosticParseKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,8 @@ def err_requires_clause_on_declarator_not_declaring_a_function : Error<
399399
"trailing requires clause can only be used when declaring a function">;
400400
def err_requires_clause_inside_parens : Error<
401401
"trailing requires clause should be placed outside parentheses">;
402+
def err_auto_type_specifier : Error<
403+
"'auto' cannot be combined with a type specifier in C++">;
402404
def ext_auto_storage_class : ExtWarn<
403405
"'auto' storage class specifier is not permitted in C++11, and will not "
404406
"be supported in future releases">, InGroup<DiagGroup<"auto-storage-class">>;

clang/lib/Parse/ParseDecl.cpp

Lines changed: 284 additions & 236 deletions
Large diffs are not rendered by default.

clang/test/CXX/dcl.dcl/dcl.spec/dcl.stc/p2.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77

88
auto int ao; // expected-error {{illegal storage class on file-scoped variable}}
99
#if __cplusplus >= 201103L // C++11 or later
10-
// expected-warning@-2 {{'auto' storage class specifier is not permitted in C++11, and will not be supported in future releases}}
10+
// expected-error@-2 {{'auto' cannot be combined with a type specifier in C++}}
1111
#endif
1212

1313
auto void af(); // expected-error {{illegal storage class on function}}
1414
#if __cplusplus >= 201103L // C++11 or later
15-
// expected-warning@-2 {{'auto' storage class specifier is not permitted in C++11, and will not be supported in future releases}}
15+
// expected-error@-2 {{'auto' cannot be combined with a type specifier in C++}}
1616
#endif
1717

1818
register int ro; // expected-error {{illegal storage class on file-scoped variable}}
@@ -27,11 +27,11 @@ register void rf(); // expected-error {{illegal storage class on function}}
2727
struct S {
2828
auto int ao; // expected-error {{storage class specified for a member declaration}}
2929
#if __cplusplus >= 201103L // C++11 or later
30-
// expected-warning@-2 {{'auto' storage class specifier is not permitted in C++11, and will not be supported in future releases}}
30+
// expected-error@-2 {{'auto' cannot be combined with a type specifier in C++}}
3131
#endif
3232
auto void af(); // expected-error {{storage class specified for a member declaration}}
3333
#if __cplusplus >= 201103L // C++11 or later
34-
// expected-warning@-2 {{'auto' storage class specifier is not permitted in C++11, and will not be supported in future releases}}
34+
// expected-error@-2 {{'auto' cannot be combined with a type specifier in C++}}
3535
#endif
3636

3737
register int ro; // expected-error {{storage class specified for a member declaration}}
@@ -40,19 +40,19 @@ struct S {
4040

4141
void foo(auto int ap, register int rp) {
4242
#if __cplusplus >= 201703L
43-
// expected-warning@-2 {{'auto' storage class specifier is not permitted in C++11, and will not be supported in future releases}}
43+
// expected-error@-2 {{'auto' cannot be combined with a type specifier in C++}}
4444
// expected-error@-3 {{ISO C++17 does not allow 'register' storage class specifier}}
4545
#elif __cplusplus >= 201103L
46-
// expected-warning@-5 {{'auto' storage class specifier is not permitted in C++11, and will not be supported in future releases}}
46+
// expected-error@-5 {{'auto' cannot be combined with a type specifier in C++}}
4747
// expected-warning@-6 {{'register' storage class specifier is deprecated}}
4848
#endif
4949
auto int abo;
5050
#if __cplusplus >= 201103L // C++11 or later
51-
// expected-warning@-2 {{'auto' storage class specifier is not permitted in C++11, and will not be supported in future releases}}
51+
// expected-error@-2 {{'auto' cannot be combined with a type specifier in C++}}
5252
#endif
5353
auto void abf(); // expected-error {{illegal storage class on function}}
5454
#if __cplusplus >= 201103L // C++11 or later
55-
// expected-warning@-2 {{'auto' storage class specifier is not permitted in C++11, and will not be supported in future releases}}
55+
// expected-error@-2 {{'auto' cannot be combined with a type specifier in C++}}
5656
#endif
5757

5858
register int rbo;

clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-1y.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ namespace p3_example {
5656
auto x = 5;
5757
const auto *v = &x, u = 6;
5858
static auto y = 0.0;
59-
auto int r; // expected-warning {{storage class}} expected-error {{file-scope}}
59+
auto int r; // expected-error {{'auto' cannot be combined with a type specifier in C++}} \
60+
expected-error {{illegal storage class on file-scoped variable}}
6061

6162
static_assert(is_same<decltype(x), int>(), "");
6263
static_assert(is_same<decltype(v), const int*>(), "");

clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,12 @@ void p3example() {
4242
static auto y = 0.0;
4343
// In C++98: 'auto' storage class specifier is redundant and incompatible with C++0x
4444
// In C++0x: 'auto' storage class specifier is not permitted in C++0x, and will not be supported in future releases
45-
auto int r; // expected-warning {{'auto' storage class specifier}}
45+
auto int r;
46+
#if __cplusplus >= 201103L
47+
// expected-error@-2 {{'auto' cannot be combined with a type specifier in C++}}
48+
#else
49+
// expected-warning@-4 {{'auto' storage class specifier}}
50+
#endif
4651

4752
same<__typeof(x), int> xHasTypeInt;
4853
same<__typeof(v), const int*> vHasTypeConstIntPtr;

clang/test/CXX/drs/cwg3xx.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1732,11 +1732,11 @@ namespace cwg395 { // cwg395: 3.0
17321732
namespace cwg396 { // cwg396: 3.0
17331733
void f() {
17341734
auto int a();
1735-
// since-cxx11-error@-1 {{'auto' storage class specifier is not permitted in C++11, and will not be supported in future releases}}
1735+
// since-cxx11-error@-1 {{'auto' cannot be combined with a type specifier in C++}}
17361736
// expected-error@-2 {{illegal storage class on function}}
17371737
int (i); // #cwg396-i
17381738
auto int (i);
1739-
// since-cxx11-error@-1 {{'auto' storage class specifier is not permitted in C++11, and will not be supported in future releases}}
1739+
// since-cxx11-error@-1 {{'auto' cannot be combined with a type specifier in C++}}
17401740
// expected-error@-2 {{redefinition of 'i'}}
17411741
// expected-note@#cwg396-i {{previous definition is here}}
17421742
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
2+
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 %s
3+
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 %s
4+
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s
5+
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++23 %s
6+
7+
// Test that 'auto' cannot be combined with a type specifier in C++.
8+
void f() {
9+
auto int x = 1; // expected-error {{'auto' cannot be combined with a type specifier in C++}}
10+
auto char c = 'a'; // expected-error {{'auto' cannot be combined with a type specifier in C++}}
11+
auto float f = 1.0f; // expected-error {{'auto' cannot be combined with a type specifier in C++}}
12+
auto double d = 1.0; // expected-error {{'auto' cannot be combined with a type specifier in C++}}
13+
auto long l = 1L; // expected-error {{'auto' cannot be combined with a type specifier in C++}}
14+
}
15+
16+
// Test that regular 'auto' (type deduction) still works in C++.
17+
void h() {
18+
auto x = 1;
19+
auto y = 2.0;
20+
auto z = 'c';
21+
}
22+

clang/test/SemaCXX/auto-cxx0x.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
22
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1y
33
void f() {
4-
auto int a; // expected-warning {{'auto' storage class specifier is not permitted in C++11, and will not be supported in future releases}}
4+
auto int a; // expected-error {{'auto' cannot be combined with a type specifier in C++}}
55
int auto b; // expected-error{{cannot combine with previous 'int' declaration specifier}}
66
}
77

clang/test/SemaCXX/class.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ class C {
66
#if __cplusplus <= 199711L
77
// expected-warning@-2 {{'auto' storage class specifier is redundant}}
88
#else
9-
// expected-warning@-4 {{'auto' storage class specifier is not permitted in C++11, and will not be supported in future releases}}
9+
// cxx11-error@-4 {{'auto' cannot be combined with a type specifier in C++}}
1010
#endif
1111
register int erry; // expected-error {{storage class specified for a member declaration}}
1212
extern int errz; // expected-error {{storage class specified for a member declaration}}

0 commit comments

Comments
 (0)