llvm-project/clang/test/SemaCXX/c99-variable-length-array.cpp
David Blaikie aee4925507 Recommit: Compress formatting of array type names (int [4] -> int[4])
Based on post-commit review discussion on
2bd84938470bf2e337801faafb8a67710f46429d with Richard Smith.

Other uses of forcing HasEmptyPlaceHolder to false seem OK to me -
they're all around pointer/reference types where the pointer/reference
token will appear at the rightmost side of the left side of the type
name, so they make nested types (eg: the "int" in "int *") behave as
though there is a non-empty placeholder (because the "*" is essentially
the placeholder as far as the "int" is concerned).

This was originally committed in 277623f4d5a672d707390e2c3eaf30a9eb4b075c

Reverted in f9ad1d1c775a8e264bebc15d75e0c6e5c20eefc7 due to breakages
outside of clang - lldb seems to have some strange/strong dependence on
"char [N]" versus "char[N]" when printing strings (not due to that name
appearing in DWARF, but probably due to using clang to stringify type
names) that'll need to be addressed, plus a few other odds and ends in
other subprojects (clang-tools-extra, compiler-rt, etc).
2021-10-21 11:34:43 -07:00

168 lines
4.8 KiB
C++

// RUN: %clang_cc1 -fsyntax-only -verify -Wvla-extension %s
struct NonPOD {
NonPOD();
};
struct NonPOD2 {
NonPOD np;
};
struct POD {
int x;
int y;
};
// expected-note@* 1+{{read of non-const variable}}
// expected-note@* 1+{{function parameter}}
// expected-note@* 1+{{declared here}}
// We allow VLAs of POD types, only.
void vla(int N) {
int array1[N]; // expected-warning{{variable length arrays are a C99 feature}}
POD array2[N]; // expected-warning{{variable length arrays are a C99 feature}}
NonPOD array3[N]; // expected-warning{{variable length arrays are a C99 feature}}
NonPOD2 array4[N][3]; // expected-warning{{variable length arrays are a C99 feature}}
}
/// Warn about VLAs in templates.
template<typename T>
void vla_in_template(int N, T t) {
int array1[N]; // expected-warning{{variable length arrays are a C99 feature}}
}
struct HasConstantValue {
static const unsigned int value = 2;
};
struct HasNonConstantValue {
static unsigned int value;
};
template<typename T>
void vla_in_template(T t) {
int array2[T::value]; // expected-warning{{variable length arrays are a C99 feature}}
}
template void vla_in_template<HasConstantValue>(HasConstantValue);
template void vla_in_template<HasNonConstantValue>(HasNonConstantValue); // expected-note{{instantiation of}}
template<typename T> struct X0 { };
// Cannot use any variably-modified type with a template parameter or
// argument.
void inst_with_vla(int N) {
int array[N]; // expected-warning{{variable length arrays are a C99 feature}}
X0<__typeof__(array)> x0a; // expected-error{{variably modified type 'typeof (array)' (aka 'int[N]') cannot be used as a template argument}}
}
template<typename T>
struct X1 {
template<int (&Array)[T::value]> // expected-error{{non-type template parameter of variably modified type 'int (&)[HasNonConstantValue::value]'}} \
// expected-warning{{variable length arrays are a C99 feature}}
struct Inner {
};
};
X1<HasConstantValue> x1a;
X1<HasNonConstantValue> x1b; // expected-note{{in instantiation of}}
// Template argument deduction does not allow deducing a size from a VLA.
// FIXME: This diagnostic should make it clear that the two 'N's are different entities!
template<typename T, unsigned N>
void accept_array(T (&array)[N]); // expected-note{{candidate template ignored: could not match 'T[N]' against 'int[N]'}}
void test_accept_array(int N) {
int array[N]; // expected-warning{{variable length arrays are a C99 feature}}
accept_array(array); // expected-error{{no matching function for call to 'accept_array'}}
}
// Variably-modified types cannot be used in local classes.
void local_classes(int N) {
struct X {
int size;
int array[N]; // expected-error{{fields must have a constant size: 'variable length array in structure' extension will never be supported}} \
// expected-error{{reference to local variable 'N' declared in enclosing function 'local_classes'}} \
// expected-warning{{variable length arrays are a C99 feature}}
};
}
namespace PR7206 {
void f(int x) {
struct edge_info {
float left;
float right;
};
struct edge_info edgeInfo[x]; // expected-warning{{variable length arrays are a C99 feature}}
}
}
namespace rdar8020206 {
template<typename T>
void f(int i) {
const unsigned value = i;
int array[value * i]; // expected-warning 2{{variable length arrays are a C99 feature}} expected-note 2{{initializer of 'value' is not a constant}}
}
template void f<int>(int); // expected-note{{instantiation of}}
}
namespace rdar8021385 {
typedef int my_int;
struct A { typedef int my_int; };
template<typename T>
struct B {
typedef typename T::my_int my_int;
void f0() {
int M = 4;
my_int a[M]; // expected-warning{{variable length arrays are a C99 feature}}
}
};
B<A> a;
}
namespace PR8209 {
void f(int n) {
typedef int vla_type[n]; // expected-warning{{variable length arrays are a C99 feature}}
(void)new vla_type; // expected-error{{variably}}
}
}
namespace rdar8733881 { // rdar://8733881
static const int k_cVal3 = (int)(1000*0.2f);
int f() {
// Ok, fold to a constant size array as an extension.
char rgch[k_cVal3] = {0};
}
}
namespace PR11744 {
template<typename T> int f(int n) {
T arr[3][n]; // expected-warning 3 {{variable length arrays are a C99 feature}}
return 3;
}
int test = f<int>(0); // expected-note {{instantiation of}}
}
namespace pr18633 {
struct A1 {
static const int sz;
static const int sz2;
};
const int A1::sz2 = 11;
template<typename T>
void func () {
int arr[A1::sz]; // expected-warning{{variable length arrays are a C99 feature}} expected-note {{initializer of 'sz' is unknown}}
}
template<typename T>
void func2 () {
int arr[A1::sz2];
}
const int A1::sz = 12;
void func2() {
func<int>();
func2<int>();
}
}