summaryrefslogtreecommitdiffstats
path: root/test/CodeGenCXX/new-array-init.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2016-10-05 22:41:02 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2016-10-05 22:41:02 +0000
commit76767b5a5757212d47c2bc4d55751ad28bf535be (patch)
tree6a0d577fe38f7bc43a7471e79df5770c5d0c69da /test/CodeGenCXX/new-array-init.cpp
parent9deb8dd73416c9e81ed263cea329cfeeb5874694 (diff)
PR22924, PR22845, some of CWG1464: When checking the initializer for an array
new expression, distinguish between the case of a constant and non-constant initializer. In the former case, if the bound is erroneous (too many initializer elements, bound is negative, or allocated size overflows), reject, and take the bound into account when determining whether we need to default-construct any elements. In the remanining cases, move the logic to check for default-constructibility of trailing elements into the initialization code rather than inventing a bogus array bound, to cope with cases where the number of initialized elements is not the same as the number of initializer list elements (this can happen due to string literal initialization or brace elision). This also fixes rejects-valid and crash-on-valid errors when initializing a new'd array of character type from a braced string literal. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@283406 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CodeGenCXX/new-array-init.cpp')
-rw-r--r--test/CodeGenCXX/new-array-init.cpp84
1 files changed, 77 insertions, 7 deletions
diff --git a/test/CodeGenCXX/new-array-init.cpp b/test/CodeGenCXX/new-array-init.cpp
index 602f93c34f..0429ae770b 100644
--- a/test/CodeGenCXX/new-array-init.cpp
+++ b/test/CodeGenCXX/new-array-init.cpp
@@ -1,5 +1,8 @@
// RUN: %clang_cc1 -std=c++11 -triple i386-unknown-unknown %s -emit-llvm -o - | FileCheck %s
+// CHECK: @[[ABC4:.*]] = {{.*}} constant [4 x i8] c"abc\00"
+// CHECK: @[[ABC15:.*]] = {{.*}} constant [15 x i8] c"abc\00\00\00\00
+
// CHECK-LABEL: define void @_Z2fni
void fn(int n) {
// CHECK: icmp ult i{{32|64}} %{{[^ ]+}}, 3
@@ -11,13 +14,6 @@ void fn(int n) {
new int[n] { 1, 2, 3 };
}
-// CHECK-LABEL: define void @_Z15const_underflowv
-void const_underflow() {
- // CHECK-NOT: icmp ult i{{32|64}} %{{[^ ]+}}, 3
- // CHECK: call i8* @_Zna{{.}}(i{{32|64}} -1)
- new int[2] { 1, 2, 3 };
-}
-
// CHECK-LABEL: define void @_Z11const_exactv
void const_exact() {
// CHECK-NOT: icmp ult i{{32|64}} %{{[^ ]+}}, 3
@@ -46,3 +42,77 @@ void check_array_value_init() {
// CHECK: icmp eq
// CHECK: br i1
}
+
+// CHECK-LABEL: define void @_Z15string_nonconsti
+void string_nonconst(int n) {
+ // CHECK: icmp slt i{{32|64}} %{{[^ ]+}}, 4
+ // FIXME: Conditionally throw an exception rather than passing -1 to alloc function
+ // CHECK: select
+ // CHECK: %[[PTR:.*]] = call i8* @_Zna{{.}}(i{{32|64}}
+ // CHECK: call void @llvm.memcpy{{.*}}(i8* %[[PTR]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[ABC4]], i32 0, i32 0), i32 4,
+ // CHECK: %[[REST:.*]] = getelementptr inbounds i8, i8* %[[PTR]], i32 4
+ // CHECK: %[[RESTSIZE:.*]] = sub {{.*}}, 4
+ // CHECK: call void @llvm.memset{{.*}}(i8* %[[REST]], i8 0, i{{32|64}} %[[RESTSIZE]],
+ new char[n] { "abc" };
+}
+
+// CHECK-LABEL: define void @_Z12string_exactv
+void string_exact() {
+ // CHECK-NOT: icmp
+ // CHECK: %[[PTR:.*]] = call i8* @_Zna{{.}}(i{{32|64}} 4)
+ // CHECK: call void @llvm.memcpy{{.*}}(i8* %[[PTR]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @[[ABC4]], i32 0, i32 0), i32 4,
+ // CHECK-NOT: memset
+ new char[4] { "abc" };
+}
+
+// CHECK-LABEL: define void @_Z17string_sufficientv
+void string_sufficient() {
+ // CHECK-NOT: icmp
+ // CHECK: %[[PTR:.*]] = call i8* @_Zna{{.}}(i{{32|64}} 15)
+ // FIXME: For very large arrays, it would be preferable to emit a small copy and a memset.
+ // CHECK: call void @llvm.memcpy{{.*}}(i8* %[[PTR]], i8* getelementptr inbounds ([15 x i8], [15 x i8]* @[[ABC15]], i32 0, i32 0), i32 15,
+ // CHECK-NOT: memset
+ new char[15] { "abc" };
+}
+
+// CHECK-LABEL: define void @_Z10aggr_exactv
+void aggr_exact() {
+ // CHECK-NOT: icmp
+ // CHECK: %[[MEM:.*]] = call i8* @_Zna{{.}}(i{{32|64}} 16)
+ // CHECK: %[[PTR0:.*]] = bitcast i8* %[[MEM]] to %[[AGGR:.*]]*
+ // CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR0]], i32 0, i32 0{{$}}
+ // CHECK: store i32 1, i32* %[[FIELD]]
+ // CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR0]], i32 0, i32 1{{$}}
+ // CHECK: store i32 2, i32* %[[FIELD]]
+ // CHECK: %[[PTR1:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR0]], i32 1{{$}}
+ // CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR1]], i32 0, i32 0{{$}}
+ // CHECK: store i32 3, i32* %[[FIELD]]
+ // CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR1]], i32 0, i32 1{{$}}
+ // CHECK: store i32 0, i32* %[[FIELD]]
+ // CHECK-NOT: store
+ // CHECK-NOT: memset
+ struct Aggr { int a, b; };
+ new Aggr[2] { 1, 2, 3 };
+}
+
+// CHECK-LABEL: define void @_Z15aggr_sufficienti
+void aggr_sufficient(int n) {
+ // CHECK: icmp ult i32 %{{.*}}, 2
+ // CHECK: %[[MEM:.*]] = call i8* @_Zna{{.}}(
+ // CHECK: %[[PTR0:.*]] = bitcast i8* %[[MEM]] to %[[AGGR:.*]]*
+ // CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR0]], i32 0, i32 0{{$}}
+ // CHECK: store i32 1, i32* %[[FIELD]]
+ // CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR0]], i32 0, i32 1{{$}}
+ // CHECK: store i32 2, i32* %[[FIELD]]
+ // CHECK: %[[PTR1:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR0]], i32 1{{$}}
+ // CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR1]], i32 0, i32 0{{$}}
+ // CHECK: store i32 3, i32* %[[FIELD]]
+ // CHECK: %[[FIELD:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR1]], i32 0, i32 1{{$}}
+ // CHECK: store i32 0, i32* %[[FIELD]]
+ // CHECK: %[[PTR2:.*]] = getelementptr inbounds %[[AGGR]], %[[AGGR]]* %[[PTR1]], i32 1{{$}}
+ // CHECK: %[[REMAIN:.*]] = sub i32 {{.*}}, 16
+ // CHECK: %[[MEM:.*]] = bitcast %[[AGGR]]* %[[PTR2]] to i8*
+ // CHECK: call void @llvm.memset{{.*}}(i8* %[[MEM]], i8 0, i32 %[[REMAIN]],
+ struct Aggr { int a, b; };
+ new Aggr[n] { 1, 2, 3 };
+}