From 0511d23aeb00062a1b61f4da4734eff322a79779 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 5 Oct 2016 22:41:02 +0000 Subject: 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. llvm-svn: 283406 --- clang/test/CodeGenCXX/new-array-init.cpp | 84 +++++++++++++++++++++++++++++--- 1 file changed, 77 insertions(+), 7 deletions(-) (limited to 'clang/test/CodeGenCXX/new-array-init.cpp') diff --git a/clang/test/CodeGenCXX/new-array-init.cpp b/clang/test/CodeGenCXX/new-array-init.cpp index 602f93c34f0..0429ae770bc 100644 --- a/clang/test/CodeGenCXX/new-array-init.cpp +++ b/clang/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 }; +} -- cgit v1.2.3