Skip to content

Commit eb5b66d

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 eb5b66d

File tree

10 files changed

+329
-259
lines changed

10 files changed

+329
-259
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: 256 additions & 236 deletions
Large diffs are not rendered by default.

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

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,18 @@
55
// The auto or register specifiers can be applied only to names of objects
66
// declared in a block (6.3) or to function parameters (8.4).
77

8-
auto int ao; // expected-error {{illegal storage class on file-scoped variable}}
8+
auto int ao;
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++}}
11+
#else
12+
// expected-error@-4 {{illegal storage class on file-scoped variable}}
1113
#endif
1214

13-
auto void af(); // expected-error {{illegal storage class on function}}
15+
auto void af();
1416
#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}}
17+
// expected-error@-2 {{'auto' cannot be combined with a type specifier in C++}}
18+
#else
19+
// expected-error@-4 {{illegal storage class on function}}
1620
#endif
1721

1822
register int ro; // expected-error {{illegal storage class on file-scoped variable}}
@@ -25,13 +29,17 @@ register int ro; // expected-error {{illegal storage class on file-scoped variab
2529
register void rf(); // expected-error {{illegal storage class on function}}
2630

2731
struct S {
28-
auto int ao; // expected-error {{storage class specified for a member declaration}}
32+
auto int ao;
2933
#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}}
34+
// expected-error@-2 {{'auto' cannot be combined with a type specifier in C++}}
35+
#else
36+
// expected-error@-4 {{storage class specified for a member declaration}}
3137
#endif
32-
auto void af(); // expected-error {{storage class specified for a member declaration}}
38+
auto void af();
3339
#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}}
40+
// expected-error@-2 {{'auto' cannot be combined with a type specifier in C++}}
41+
#else
42+
// expected-error@-4 {{storage class specified for a member declaration}}
3543
#endif
3644

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

4149
void foo(auto int ap, register int rp) {
4250
#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}}
51+
// expected-error@-2 {{'auto' cannot be combined with a type specifier in C++}}
4452
// expected-error@-3 {{ISO C++17 does not allow 'register' storage class specifier}}
4553
#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}}
54+
// expected-error@-5 {{'auto' cannot be combined with a type specifier in C++}}
4755
// expected-warning@-6 {{'register' storage class specifier is deprecated}}
4856
#endif
4957
auto int abo;
5058
#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}}
59+
// expected-error@-2 {{'auto' cannot be combined with a type specifier in C++}}
5260
#endif
53-
auto void abf(); // expected-error {{illegal storage class on function}}
61+
auto void abf();
5462
#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}}
63+
// expected-error@-2 {{'auto' cannot be combined with a type specifier in C++}}
64+
#else
65+
// expected-error@-4 {{illegal storage class on function}}
5666
#endif
5767

5868
register int rbo;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ 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++}}
6060

6161
static_assert(is_same<decltype(x), int>(), "");
6262
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: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1732,11 +1732,16 @@ 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}}
1736-
// expected-error@-2 {{illegal storage class on function}}
1735+
// since-cxx11-error@-1 {{'auto' cannot be combined with a type specifier in C++}}
1736+
#if __cplusplus < 201103L
1737+
// expected-error@-3 {{illegal storage class on function}}
1738+
#else
1739+
// expected-warning@-5 {{empty parentheses interpreted as a function declaration}}
1740+
// expected-note@-6 {{replace parentheses with an initializer to declare a variable}}
1741+
#endif
17371742
int (i); // #cwg396-i
17381743
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}}
1744+
// since-cxx11-error@-1 {{'auto' cannot be combined with a type specifier in C++}}
17401745
// expected-error@-2 {{redefinition of 'i'}}
17411746
// expected-note@#cwg396-i {{previous definition is here}}
17421747
}
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: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98 -Wc++11-compat %s -std=c++98
33
class C {
44
public:
5-
auto int errx; // expected-error {{storage class specified for a member declaration}}
5+
auto int errx;
66
#if __cplusplus <= 199711L
7-
// expected-warning@-2 {{'auto' storage class specifier is redundant}}
7+
// expected-error@-2 {{storage class specified for a member declaration}}
8+
// expected-warning@-3 {{'auto' storage class specifier is redundant and incompatible with C++11}}
89
#else
9-
// expected-warning@-4 {{'auto' storage class specifier is not permitted in C++11, and will not be supported in future releases}}
10+
// expected-error@-5 {{'auto' cannot be combined with a type specifier in C++}}
1011
#endif
1112
register int erry; // expected-error {{storage class specified for a member declaration}}
1213
extern int errz; // expected-error {{storage class specified for a member declaration}}

clang/test/SemaCXX/static-data-member.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,12 @@ double ABC::a = 1.0;
1313
extern double ABC::b = 1.0; // expected-error {{static data member definition cannot specify a storage class}}
1414
static double ABC::c = 1.0; // expected-error {{'static' can only be specified inside the class definition}}
1515
__private_extern__ double ABC::d = 1.0; // expected-error {{static data member definition cannot specify a storage class}}
16-
auto double ABC::e = 1.0; // expected-error {{static data member definition cannot specify a storage class}}
16+
auto double ABC::e = 1.0;
17+
#if __cplusplus >= 201103L
18+
// expected-error@-2 {{'auto' cannot be combined with a type specifier in C++}}
19+
#else
20+
// expected-error@-4 {{static data member definition cannot specify a storage class}}
21+
#endif
1722
#if __cplusplus < 201703L
1823
register double ABC::f = 1.0; // expected-error {{static data member definition cannot specify a storage class}}
1924
#endif

0 commit comments

Comments
 (0)