Skip to content

Commit aefff77

Browse files
authored
[clang] Migrate DR tests to static_assert (#88611)
This patch touches a number of tests that run in C++98 mode that have been using array size as a context that requires a constant expression, replacing it with a `static_assert` backported via a macro. This reduces noise in expected directives that comes from diagnostics around VLAs. This patch also showcases that DR tests would benefit from folding in constant expressions in C++98 mode, but I'm not sure it's even on the table. If it is, I'd be happy to prepare a PR for that, and rebase this PR on top of it. CC @AaronBallman
1 parent 4082a75 commit aefff77

File tree

8 files changed

+117
-95
lines changed

8 files changed

+117
-95
lines changed

clang/test/CXX/drs/dr0xx.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors -triple %itanium_abi_triple
66
// RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors -triple %itanium_abi_triple
77

8+
#if __cplusplus == 199711L
9+
#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
10+
// cxx98-error@-1 {{variadic macros are a C99 feature}}
11+
#endif
12+
813
namespace cwg1 { // cwg1: no
914
namespace X { extern "C" void cwg1_f(int a = 1); }
1015
namespace Y { extern "C" void cwg1_f(int a = 1); }
@@ -897,7 +902,7 @@ namespace cwg54 { // cwg54: 2.8
897902

898903
namespace cwg55 { // cwg55: yes
899904
enum E { e = 5 };
900-
int test[(e + 1 == 6) ? 1 : -1];
905+
static_assert(e + 1 == 6, "");
901906
}
902907

903908
namespace cwg56 { // cwg56: yes
@@ -1163,10 +1168,9 @@ namespace cwg75 { // cwg75: yes
11631168

11641169
namespace cwg76 { // cwg76: yes
11651170
const volatile int n = 1;
1166-
int arr[n]; // #cwg76-vla
1167-
// expected-error@#cwg76-vla {{variable length arrays in C++ are a Clang extension}}
1168-
// expected-note@#cwg76-vla {{read of volatile-qualified type 'const volatile int' is not allowed in a constant expression}}
1169-
// expected-error@#cwg76-vla {{variable length array declaration not allowed at file scope}}
1171+
static_assert(n, "");
1172+
// expected-error@-1 {{static assertion expression is not an integral constant expression}}
1173+
// expected-note@-2 {{read of volatile-qualified type 'const volatile int' is not allowed in a constant expression}}
11701174
}
11711175

11721176
namespace cwg77 { // cwg77: yes

clang/test/CXX/drs/dr16xx.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,9 @@ namespace cwg1645 { // cwg1645: 3.9
153153

154154
namespace cwg1652 { // cwg1652: 3.6
155155
int a, b;
156-
int arr[&a + 1 == &b ? 1 : 2];
157-
// expected-error@-1 {{variable length arrays in C++ are a Clang extension}}
156+
static_assert(&a + 1 == &b, "");
157+
// expected-error@-1 {{static assertion expression is not an integral constant expression}}
158158
// expected-note@-2 {{comparison against pointer '&a + 1' that points past the end of a complete object has unspecified value}}
159-
// expected-error@-3 {{variable length array declaration not allowed at file scope}}
160159
}
161160

162161
namespace cwg1653 { // cwg1653: 4 c++17

clang/test/CXX/drs/dr1xx.cpp

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@
55
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
66
// RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx17 -fexceptions -fcxx-exceptions -pedantic-errors
77

8+
#if __cplusplus == 199711L
9+
#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
10+
// cxx98-error@-1 {{variadic macros are a C99 feature}}
11+
#endif
12+
13+
#if __cplusplus == 199711L
14+
#define __enable_constant_folding(x) (__builtin_constant_p(x) ? (x) : (x))
15+
#else
16+
#define __enable_constant_folding
17+
#endif
18+
819
namespace cwg100 { // cwg100: yes
920
template<const char (*)[4]> struct A {}; // #cwg100-A
1021
template<const char (&)[4]> struct B {}; // #cwg100-B
@@ -736,22 +747,16 @@ namespace cwg147 { // cwg147: yes
736747

737748
namespace cwg148 { // cwg148: yes
738749
struct A { int A::*p; };
739-
int check1[__is_pod(int(A::*)) ? 1 : -1];
740-
int check2[__is_pod(A) ? 1 : -1];
750+
static_assert(__is_pod(int(A::*)), "");
751+
static_assert(__is_pod(A), "");
741752
}
742753

743754
// cwg149: na
744755

745756
namespace cwg151 { // cwg151: 3.1
746757
struct X {};
747758
typedef int X::*p;
748-
#if __cplusplus < 201103L
749-
#define fold(x) (__builtin_constant_p(0) ? (x) : (x))
750-
#else
751-
#define fold
752-
#endif
753-
int check[fold(p() == 0) ? 1 : -1];
754-
#undef fold
759+
static_assert(__enable_constant_folding(p() == 0), "");
755760
}
756761

757762
namespace cwg152 { // cwg152: yes
@@ -956,42 +961,42 @@ namespace cwg171 {
956961

957962
namespace cwg172 { // cwg172: yes
958963
enum { zero };
959-
int check1[-1 < zero ? 1 : -1];
964+
static_assert(-1 < zero, "");
960965

961966
enum { x = -1, y = (unsigned int)-1 };
962-
int check2[sizeof(x) > sizeof(int) ? 1 : -1];
967+
static_assert(sizeof(x) > sizeof(int), "");
963968

964969
enum { a = (unsigned int)-1 / 2 };
965-
int check3a[sizeof(a) == sizeof(int) ? 1 : -1];
966-
int check3b[-a < 0 ? 1 : -1];
970+
static_assert(sizeof(a) == sizeof(int), "");
971+
static_assert(-a < 0, "");
967972

968973
enum { b = (unsigned int)-1 / 2 + 1 };
969-
int check4a[sizeof(b) == sizeof(unsigned int) ? 1 : -1];
970-
int check4b[-b > 0 ? 1 : -1];
974+
static_assert(sizeof(b) == sizeof(unsigned int), "");
975+
static_assert(-b > 0, "");
971976

972977
enum { c = (unsigned long)-1 / 2 };
973-
int check5a[sizeof(c) == sizeof(long) ? 1 : -1];
974-
int check5b[-c < 0 ? 1 : -1];
978+
static_assert(sizeof(c) == sizeof(long), "");
979+
static_assert(-c < 0, "");
975980

976981
enum { d = (unsigned long)-1 / 2 + 1 };
977-
int check6a[sizeof(d) == sizeof(unsigned long) ? 1 : -1];
978-
int check6b[-d > 0 ? 1 : -1];
982+
static_assert(sizeof(d) == sizeof(unsigned long), "");
983+
static_assert(-d > 0, "");
979984

980985
enum { e = (unsigned long long)-1 / 2 };
981986
// cxx98-error@-1 {{'long long' is a C++11 extension}}
982-
int check7a[sizeof(e) == sizeof(long) ? 1 : -1];
983-
int check7b[-e < 0 ? 1 : -1];
987+
static_assert(sizeof(e) == sizeof(long), "");
988+
static_assert(-e < 0, "");
984989

985990
enum { f = (unsigned long long)-1 / 2 + 1 };
986991
// cxx98-error@-1 {{'long long' is a C++11 extension}}
987-
int check8a[sizeof(f) == sizeof(unsigned long) ? 1 : -1];
988-
int check8b[-f > 0 ? 1 : -1];
992+
static_assert(sizeof(f) == sizeof(unsigned long), "");
993+
static_assert(-f > 0, "");
989994
}
990995

991996
namespace cwg173 { // cwg173: yes
992-
int check[('0' + 1 == '1' && '0' + 2 == '2' && '0' + 3 == '3' &&
993-
'0' + 4 == '4' && '0' + 5 == '5' && '0' + 6 == '6' &&
994-
'0' + 7 == '7' && '0' + 8 == '8' && '0' + 9 == '9') ? 1 : -1];
997+
static_assert('0' + 1 == '1' && '0' + 2 == '2' && '0' + 3 == '3' &&
998+
'0' + 4 == '4' && '0' + 5 == '5' && '0' + 6 == '6' &&
999+
'0' + 7 == '7' && '0' + 8 == '8' && '0' + 9 == '9', "");
9951000
}
9961001

9971002
// cwg174: sup 1012
@@ -1070,7 +1075,7 @@ namespace cwg177 { // cwg177: yes
10701075
}
10711076

10721077
namespace cwg178 { // cwg178: yes
1073-
int check[int() == 0 ? 1 : -1];
1078+
static_assert(int() == 0, "");
10741079
#if __cplusplus >= 201103L
10751080
static_assert(int{} == 0, "");
10761081
struct S { int a, b; };
@@ -1180,7 +1185,7 @@ namespace cwg187 { // cwg187: sup 481
11801185

11811186
namespace cwg188 { // cwg188: yes
11821187
char c[10];
1183-
int check[sizeof(0, c) == 10 ? 1 : -1];
1188+
static_assert(sizeof(0, c) == 10, "");
11841189
}
11851190

11861191
// cwg190 FIXME: add codegen test for tbaa

clang/test/CXX/drs/dr2xx.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,15 @@
1010
typedef __SIZE_TYPE__ size_t;
1111
// cxx98-error@-1 0-1 {{'long long' is a C++11 extension}}
1212

13-
#if __cplusplus < 201103L
14-
#define fold(x) (__builtin_constant_p(x) ? (x) : (x))
13+
#if __cplusplus == 199711L
14+
#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
15+
// cxx98-error@-1 {{variadic macros are a C99 feature}}
16+
#endif
17+
18+
#if __cplusplus == 199711L
19+
#define __enable_constant_folding(x) (__builtin_constant_p(x) ? (x) : (x))
1520
#else
16-
#define fold
21+
#define __enable_constant_folding
1722
#endif
1823

1924
namespace cwg200 { // cwg200: dup 214
@@ -31,7 +36,7 @@ namespace cwg200 { // cwg200: dup 214
3136
namespace cwg202 { // cwg202: 3.1
3237
template<typename T> T f();
3338
template<int (*g)()> struct X {
34-
int arr[fold(g == &f<int>) ? 1 : -1];
39+
static_assert(__enable_constant_folding(g == &f<int>), "");
3540
};
3641
template struct X<f>;
3742
}
@@ -1024,7 +1029,7 @@ namespace cwg275 { // cwg275: no
10241029
namespace cwg277 { // cwg277: 3.1
10251030
typedef int *intp;
10261031
int *p = intp();
1027-
int a[fold(intp() ? -1 : 1)];
1032+
static_assert(__enable_constant_folding(!intp()), "");
10281033
}
10291034

10301035
namespace cwg280 { // cwg280: 2.9

clang/test/CXX/drs/dr3xx.cpp

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@
55
// RUN: %clang_cc1 -std=c++11 -verify=expected,cxx98-14,cxx98-17,cxx98-20,cxx11-14,since-cxx11 -triple %itanium_abi_triple %s -fexceptions -fcxx-exceptions -pedantic-errors
66
// RUN: %clang_cc1 -std=c++98 -verify=expected,cxx98-14,cxx98-17,cxx98-20,cxx98 -triple %itanium_abi_triple %s -fexceptions -fcxx-exceptions -pedantic-errors
77

8+
#if __cplusplus == 199711L
9+
#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
10+
// cxx98-error@-1 {{variadic macros are a C99 feature}}
11+
#endif
12+
13+
#if __cplusplus == 199711L
14+
#define __enable_constant_folding(x) (__builtin_constant_p(x) ? (x) : (x))
15+
#else
16+
#define __enable_constant_folding
17+
#endif
18+
819
namespace cwg300 { // cwg300: yes
920
template<typename R, typename A> void f(R (&)(A)) {}
1021
int g(int);
@@ -396,7 +407,7 @@ namespace cwg324 { // cwg324: 3.6
396407

397408
namespace cwg326 { // cwg326: 3.1
398409
struct S {};
399-
int test[__is_trivially_constructible(S, const S&) ? 1 : -1];
410+
static_assert(__is_trivially_constructible(S, const S&), "");
400411
}
401412

402413
namespace cwg327 { // cwg327: dup 538
@@ -653,7 +664,7 @@ namespace cwg339 { // cwg339: 2.8
653664

654665
template<typename T> A<sizeof(f(T()))> make_A();
655666

656-
int a[conv_int<char>::value ? 1 : -1];
667+
static_assert(conv_int<char>::value, "");
657668
bool b = conv_int2<char>(A<1>());
658669
A<1> c = make_A<char>();
659670
}
@@ -1099,21 +1110,14 @@ namespace cwg364 { // cwg364: yes
10991110
#endif
11001111

11011112
namespace cwg367 { // cwg367: yes
1102-
// FIXME: These diagnostics are terrible. Don't diagnose an ill-formed global
1103-
// array as being a VLA!
1104-
int a[true ? throw 0 : 4];
1105-
// expected-error@-1 {{variable length arrays in C++ are a Clang extension}}
1106-
// expected-error@-2 {{variable length array declaration not allowed at file scope}}
1107-
int b[true ? 4 : throw 0];
1108-
// cxx98-error@-1 {{variable length arrays in C++ are a Clang extension}}
1109-
// cxx98-error@-2 {{variable length array folded to constant array as an extension}}
1110-
int c[true ? *new int : 4];
1111-
// expected-error@-1 {{variable length arrays in C++ are a Clang extension}}
1113+
static_assert(__enable_constant_folding(true ? throw 0 : 4), "");
1114+
// expected-error@-1 {{expression is not an integral constant expression}}
1115+
static_assert(__enable_constant_folding(true ? 4 : throw 0), "");
1116+
static_assert(__enable_constant_folding(true ? *new int : 4), "");
1117+
// expected-error@-1 {{expression is not an integral constant expression}}
11121118
// expected-note@-2 {{read of uninitialized object is not allowed in a constant expression}}
1113-
// expected-error@-3 {{variable length array declaration not allowed at file scope}}
1114-
int d[true ? 4 : *new int];
1115-
// cxx98-error@-1 {{variable length arrays in C++ are a Clang extension}}
1116-
// cxx98-error@-2 {{variable length array folded to constant array as an extension}}
1119+
static_assert(__enable_constant_folding(true ? 4 : *new int), "");
1120+
11171121
}
11181122

11191123
namespace cwg368 { // cwg368: 3.6
@@ -1325,7 +1329,7 @@ namespace cwg383 { // cwg383: yes
13251329
struct B { ~B(); };
13261330
union C { C &operator=(const C&); };
13271331
union D { ~D(); };
1328-
int check[(__is_pod(A) || __is_pod(B) || __is_pod(C) || __is_pod(D)) ? -1 : 1];
1332+
static_assert(!__is_pod(A) && !__is_pod(B) && !__is_pod(C) && !__is_pod(D), "");
13291333
}
13301334

13311335
namespace cwg384 { // cwg384: yes

0 commit comments

Comments
 (0)