Files
clang-p2996/clang/test/CodeGenCXX/cxx11-initializer-aggregate.cpp
Nikita Popov d74212987b [ConstantFold] Remove unnecessary bounded index restriction
The fold for merging a GEP of GEP into a single GEP currently bails
if doing so would result in notional overindexing. The justification
given in the comment above this check is dangerously incorrect: GEPs
with notional overindexing are perfectly fine, and if some code
treats them incorrectly, then that code is broken, not the GEP.
Such a GEP might legally appear in source IR, so only preventing
its creation cannot be sufficient. (The constant folder also ends
up canonicalizing the GEP to remove the notional overindexing, but
that's neither here nor there.)

This check dates back to
bd4fef4a89,
and as far as I can tell the original issue this was trying to
patch around has since been resolved.

Differential Revision: https://reviews.llvm.org/D116587
2022-01-04 15:23:09 +01:00

174 lines
6.6 KiB
C++

// RUN: %clang_cc1 -std=c++11 -S -emit-llvm -o - %s -triple x86_64-linux-gnu | FileCheck %s
// RUN: %clang_cc1 -std=c++17 -S -emit-llvm -o - %s -triple x86_64-linux-gnu | FileCheck %s
struct A { int a, b; int f(); };
namespace NonAggregateCopyInAggregateInit { // PR32044
struct A { constexpr A(int n) : x(n), y() {} int x, y; } extern a;
// CHECK-DAG: @_ZN31NonAggregateCopyInAggregateInit1bE ={{.*}} global %{{.*}} { %[[A:.*]]* @_ZN31NonAggregateCopyInAggregateInit1aE }
struct B { A &p; } b{{a}};
// CHECK-DAG: @_ZGRN31NonAggregateCopyInAggregateInit1cE_ = internal global %[[A]] { i32 1, i32 0 }
// CHECK-DAG: @_ZN31NonAggregateCopyInAggregateInit1cE ={{.*}} global %{{.*}} { %{{.*}}* @_ZGRN31NonAggregateCopyInAggregateInit1cE_ }
struct C { A &&p; } c{{1}};
}
namespace NearlyZeroInit {
// CHECK-DAG: @_ZN14NearlyZeroInit1aE ={{.*}} global {{.*}} <{ i32 1, i32 2, i32 3, [120 x i32] zeroinitializer }>
int a[123] = {1, 2, 3};
// CHECK-DAG: @_ZN14NearlyZeroInit1bE ={{.*}} global {{.*}} { i32 1, <{ i32, [2147483647 x i32] }> <{ i32 2, [2147483647 x i32] zeroinitializer }> }
struct B { int n; int arr[1024 * 1024 * 1024 * 2u]; } b = {1, {2}};
}
namespace PR37560 {
union U {
char x;
int a;
};
// FIXME: [dcl.init]p2, the padding bits of the union object should be
// initialized to 0, not undef, which would allow us to collapse the tail
// of these arrays to zeroinitializer.
// CHECK-DAG: @_ZN7PR375601cE ={{.*}} global <{ { i8, [3 x i8] } }> <{ { i8, [3 x i8] } { i8 0, [3 x i8] undef } }>
U c[1] = {};
// CHECK-DAG: @_ZN7PR375601dE ={{.*}} global {{.*}} <{ { i8, [3 x i8] } { i8 97, [3 x i8] undef }, %"{{[^"]*}}" { i32 123 }, { i8, [3 x i8] } { i8 98, [3 x i8] undef }, { i8, [3 x i8] } { i8 0, [3 x i8] undef },
U d[16] = {'a', {.a = 123}, 'b'};
// CHECK-DAG: @_ZN7PR375601eE ={{.*}} global {{.*}} <{ %"{{[^"]*}}" { i32 123 }, %"{{[^"]*}}" { i32 456 }, { i8, [3 x i8] } { i8 0, [3 x i8] undef },
U e[16] = {{.a = 123}, {.a = 456}};
union V {
int a;
char x;
};
// CHECK-DAG: @_ZN7PR375601fE ={{.*}} global [1 x %"{{[^"]*}}"] zeroinitializer
V f[1] = {};
// CHECK-DAG: @_ZN7PR375601gE ={{.*}} global {{.*}} <{ { i8, [3 x i8] } { i8 97, [3 x i8] undef }, %"{{[^"]*}}" { i32 123 }, { i8, [3 x i8] } { i8 98, [3 x i8] undef }, [13 x %"{{[^"]*}}"] zeroinitializer }>
V g[16] = {{.x = 'a'}, {.a = 123}, {.x = 'b'}};
// CHECK-DAG: @_ZN7PR375601hE ={{.*}} global {{.*}} <{ %"{{[^"]*}}" { i32 123 }, %"{{[^"]*}}" { i32 456 }, [14 x %"{{[^"]*}}"] zeroinitializer }>
V h[16] = {{.a = 123}, {.a = 456}};
// CHECK-DAG: @_ZN7PR375601iE ={{.*}} global [4 x %"{{[^"]*}}"] [%"{{[^"]*}}" { i32 123 }, %"{{[^"]*}}" { i32 456 }, %"{{[^"]*}}" zeroinitializer, %"{{[^"]*}}" zeroinitializer]
V i[4] = {{.a = 123}, {.a = 456}};
}
// CHECK-LABEL: define {{.*}}@_Z3fn1i(
int fn1(int x) {
// CHECK: %[[INITLIST:.*]] = alloca %struct.A
// CHECK: %[[A:.*]] = getelementptr inbounds %struct.A, %struct.A* %[[INITLIST]], i32 0, i32 0
// CHECK: store i32 %{{.*}}, i32* %[[A]], align 4
// CHECK: %[[B:.*]] = getelementptr inbounds %struct.A, %struct.A* %[[INITLIST]], i32 0, i32 1
// CHECK: store i32 5, i32* %[[B]], align 4
// CHECK: call i32 @_ZN1A1fEv(%struct.A* {{[^,]*}} %[[INITLIST]])
return A{x, 5}.f();
}
struct B { int &r; int &f() { return r; } };
// CHECK-LABEL: define {{.*}}@_Z3fn2Ri(
int &fn2(int &v) {
// CHECK: %[[INITLIST2:.*]] = alloca %struct.B, align 8
// CHECK: %[[R:.*]] = getelementptr inbounds %struct.B, %struct.B* %[[INITLIST2:.*]], i32 0, i32 0
// CHECK: store i32* %{{.*}}, i32** %[[R]], align 8
// CHECK: call nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) i32* @_ZN1B1fEv(%struct.B* {{[^,]*}} %[[INITLIST2:.*]])
return B{v}.f();
}
// CHECK-LABEL: define {{.*}}@__cxx_global_var_init(
//
// CHECK: call {{.*}}@_ZN14NonTrivialInit1AC1Ev(
// CHECK: getelementptr inbounds {{.*}}, i64 1
// CHECK: br i1
//
// CHECK: getelementptr inbounds {{.*}}, i64 1
// CHECK: icmp eq {{.*}}, getelementptr inbounds {{.*}}, i64 1, i64 0
// CHECK: br i1
//
// CHECK: call i32 @__cxa_atexit(
namespace NonTrivialInit {
struct A { A(); A(const A&) = delete; ~A(); };
struct B { A a[20]; };
// NB, this must be large enough to be worth memsetting for this test to be
// meaningful.
B b[30] = {};
}
namespace ZeroInit {
enum { Zero, One };
constexpr int zero() { return 0; }
constexpr int *null() { return nullptr; }
struct Filler {
int x;
Filler();
};
struct S1 {
int x;
};
// These declarations, if implemented elementwise, require huge
// amout of memory and compiler time.
unsigned char data_1[1024 * 1024 * 1024 * 2u] = { 0 };
unsigned char data_2[1024 * 1024 * 1024 * 2u] = { Zero };
unsigned char data_3[1024][1024][1024] = {{{0}}};
unsigned char data_4[1024 * 1024 * 1024 * 2u] = { zero() };
int *data_5[1024 * 1024 * 512] = { nullptr };
int *data_6[1024 * 1024 * 512] = { null() };
struct S1 data_7[1024 * 1024 * 512] = {{0}};
char data_8[1000 * 1000 * 1000] = {};
int (&&data_9)[1000 * 1000 * 1000] = {0};
unsigned char data_10[1024 * 1024 * 1024 * 2u] = { 1 };
unsigned char data_11[1024 * 1024 * 1024 * 2u] = { One };
unsigned char data_12[1024][1024][1024] = {{{1}}};
// This variable must be initialized elementwise.
Filler data_e1[1024] = {};
// CHECK: getelementptr inbounds {{.*}} @_ZN8ZeroInit7data_e1E
struct Largeish {
long a, b, c;
};
// CHECK: define {{.*}}@_ZN8ZeroInit9largeish1Ev(
// CHECK-NOT }
// CHECK: call {{.*}}memset
Largeish largeish1() { return {}; }
// CHECK: define {{.*}}@_ZN8ZeroInit9largeish2Ev(
// CHECK-NOT }
// CHECK: call {{.*}}memset
Largeish largeish2() { return Largeish(); }
// CHECK: define {{.*}}@_ZN8ZeroInit9largeish3Ev(
// CHECK-NOT }
// CHECK: call {{.*}}memset
Largeish largeish3() { return Largeish{}; }
// CHECK: define {{.*}}@_ZN8ZeroInit9largeish4Ev(
// CHECK-NOT }
// CHECK: call {{.*}}memset
Largeish largeish4() { return (Largeish){}; }
// CHECK: define {{.*}}@_ZN8ZeroInit9largeish5Ev(
// CHECK-NOT }
// CHECK: call {{.*}}memset
Largeish largeish5() { return {0, 0, 0}; }
typedef __attribute__((ext_vector_type(4))) char CI4;
struct Conversions {
_Complex int a;
_Complex float b;
short c;
long double d;
CI4 e;
char f;
char g;
int *h;
long i;
};
// CHECK: define {{.*}}@_ZN8ZeroInit11conversionsEv(
// CHECK-NOT }
// CHECK: call {{.*}}memset
Conversions conversions() {
return {0,
0,
0,
0,
CI4(0),
static_cast<char>(0.0),
char(0 + 0i),
reinterpret_cast<int *>(0),
reinterpret_cast<long>((int *)nullptr)};
}
}