callee in constant evaluation. We previously made a deep copy of function parameters of class type when passing them, resulting in the destructor for the parameter applying to the original argument value, ignoring any modifications made in the function body. This also meant that the 'this' pointer of the function parameter could be observed changing between the caller and the callee. This change completely reimplements how we model function parameters during constant evaluation. We now model them roughly as if they were variables living in the caller, albeit with an artificially reduced scope that covers only the duration of the function call, instead of modeling them as temporaries in the caller that we partially "reparent" into the callee at the point of the call. This brings some minor diagnostic improvements, as well as significantly reduced stack usage during constant evaluation.
168 lines
4.8 KiB
C++
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>();
|
|
}
|
|
}
|