diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-12-14 00:03:17 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-12-14 00:03:17 +0000 |
commit | 30e304e2a646ccd5f34d5697cad0be9dcccfaa2d (patch) | |
tree | 163bb6f813594df2306fc76c0ec4241e296b8fb9 /clang/test/CodeGenCXX/lambda-expressions.cpp | |
parent | 54eb192b25aa766142e19203361f2d91f21b7263 (diff) | |
download | bcm5719-llvm-30e304e2a646ccd5f34d5697cad0be9dcccfaa2d.tar.gz bcm5719-llvm-30e304e2a646ccd5f34d5697cad0be9dcccfaa2d.zip |
Remove custom handling of array copies in lambda by-value array capture and
copy constructors of classes with array members, instead using
ArrayInitLoopExpr to represent the initialization loop.
This exposed a bug in the static analyzer where it was unable to differentiate
between zero-initialized and unknown array values, which has also been fixed
here.
llvm-svn: 289618
Diffstat (limited to 'clang/test/CodeGenCXX/lambda-expressions.cpp')
-rw-r--r-- | clang/test/CodeGenCXX/lambda-expressions.cpp | 76 |
1 files changed, 51 insertions, 25 deletions
diff --git a/clang/test/CodeGenCXX/lambda-expressions.cpp b/clang/test/CodeGenCXX/lambda-expressions.cpp index 2006f0f81ef..cefaeb4017b 100644 --- a/clang/test/CodeGenCXX/lambda-expressions.cpp +++ b/clang/test/CodeGenCXX/lambda-expressions.cpp @@ -54,12 +54,14 @@ int c(int x) { return [&x]{return x;}(); } // CHECK: ret i32 struct D { D(); D(const D&); int x; }; -int d(int x) { D y[10]; [x,y] { return y[x].x; }(); } +int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); } // CHECK-LABEL: define i32 @_Z1di // CHECK: call void @_ZN1DC1Ev -// CHECK: icmp ult i64 %{{.*}}, 10 +// CHECK: br label // CHECK: call void @_ZN1DC1ERKS_ +// CHECK: icmp eq i64 %{{.*}}, 10 +// CHECK: br i1 // CHECK: call i32 @"_ZZ1diENK3$_4clEv" // CHECK-LABEL: define internal i32 @"_ZZ1diENK3$_4clEv" // CHECK: load i32, i32* @@ -67,7 +69,7 @@ int d(int x) { D y[10]; [x,y] { return y[x].x; }(); } // CHECK: ret i32 struct E { E(); E(const E&); ~E(); int x; }; -int e(E a, E b, bool cond) { [a,b,cond](){ return (cond ? a : b).x; }(); } +int e(E a, E b, bool cond) { return [a,b,cond](){ return (cond ? a : b).x; }(); } // CHECK-LABEL: define i32 @_Z1e1ES_b // CHECK: call void @_ZN1EC1ERKS_ // CHECK: invoke void @_ZN1EC1ERKS_ @@ -127,42 +129,66 @@ namespace pr28595 { ~A(); }; + void after_init() noexcept; + // CHECK-LABEL: define void @_ZN7pr285954testEv() void test() { - // CHECK: [[ARRAY:%.*]] = alloca [3 x [5 x [[A:%.*]]]], align 1 - // CHECK: [[DESTIDX:%.*]] = alloca i64, align 8 - // CHECK: [[I0:%.*]] = alloca i64, align 8 - // CHECK: [[I1:%.*]] = alloca i64, align 8 + // CHECK: %[[SRC:.*]] = alloca [3 x [5 x %[[A:.*]]]], align 1 A array[3][5]; - // CHECK: [[DESTBASE:%.*]] = bitcast [3 x [5 x [[A]]]]* {{.*}} to [[A]]* - // CHECK: store i64 0, i64* [[DESTIDX]], align 8 - // CHECK: store i64 0, i64* [[I0]], align 8 + // Skip over the initialization loop. + // CHECK: call {{.*}}after_init + after_init(); + + // CHECK: %[[DST_0:.*]] = getelementptr inbounds [3 x [5 x %[[A]]]], {{.*}}, i64 0, i64 0 // CHECK: br label - // CHECK: icmp ult - // CHECK: store i64 0, i64* [[I1]], align 8 + // CHECK: %[[I:.*]] = phi i64 [ 0, %{{.*}} ], [ %[[I_NEXT:.*]], {{.*}} ] + // CHECK: %[[DST_I:.*]] = getelementptr {{.*}} [5 x %[[A]]]* %[[DST_0]], i64 %[[I]] + // CHECK: %[[SRC_I:.*]] = getelementptr {{.*}} [3 x [5 x %[[A]]]]* %[[SRC]], i64 0, i64 %[[I]] + // + // CHECK: %[[DST_I_0:.*]] = getelementptr {{.*}} [5 x %[[A]]]* %[[DST_I]], i64 0, i64 0 // CHECK: br label - // CHECK: icmp ult - // CHECK: [[T0:%.*]] = load i64, i64* [[DESTIDX]], align 8 - // CHECK: [[DEST:%.*]] = getelementptr inbounds [[A]], [[A]]* [[DESTBASE]], i64 [[T0]] + // CHECK: %[[J:.*]] = phi i64 [ 0, %{{.*}} ], [ %[[J_NEXT:.*]], {{.*}} ] + // CHECK: %[[DST_I_J:.*]] = getelementptr {{.*}} %[[A]]* %[[DST_I_0]], i64 %[[J]] + // CHECK: %[[SRC_I_J:.*]] = getelementptr {{.*}} [5 x %[[A]]]* %[[SRC_I]], i64 0, i64 %[[J]] + // // CHECK: invoke void @_ZN7pr285954TempC1Ev // CHECK: invoke void @_ZN7pr285951AC1ERKS0_RKNS_4TempE // CHECK: invoke void @_ZN7pr285954TempD1Ev + // + // CHECK: add nuw i64 %[[J]], 1 + // CHECK: icmp eq + // CHECK: br i1 + // + // CHECK: add nuw i64 %[[I]], 1 + // CHECK: icmp eq + // CHECK: br i1 + // + // CHECK: ret void + // // CHECK: landingpad // CHECK: landingpad - // CHECK: br label [[CLEANUP:%.*]]{{$}} + // CHECK: br label %[[CLEANUP:.*]]{{$}} // CHECK: landingpad // CHECK: invoke void @_ZN7pr285954TempD1Ev - // CHECK: br label [[CLEANUP]] - // CHECK: icmp eq [[A]]* [[DESTBASE]], [[DEST]] - // CHECK: [[T0:%.*]] = phi [[A]]* - // CHECK: [[T1:%.*]] = getelementptr inbounds [[A]], [[A]]* [[T0]], i64 -1 - // CHECK: call void @_ZN7pr285951AD1Ev([[A]]* [[T1]]) - // CHECK: icmp eq [[A]]* [[T1]], [[DESTBASE]] + // CHECK: br label %[[CLEANUP]] + // + // FIXME: only emit a single cleanup loop here + // CHECK: [[CLEANUP]]: + // CHECK: icmp eq %[[A]]* %[[DST_I_0]], %[[DST_I_J]] + // CHECK: %[[T0:.*]] = phi %[[A]]* + // CHECK: %[[T1:.*]] = getelementptr inbounds %[[A]], %[[A]]* %[[T0]], i64 -1 + // CHECK: call void @_ZN7pr285951AD1Ev(%[[A]]* %[[T1]]) + // CHECK: icmp eq %[[A]]* %[[T1]], %[[DST_I_0]] + // + // CHECK: %[[BEGIN:.*]] = getelementptr {{.*}} %[[DST_0]], i64 0, i64 0 + // CHECK: %[[END:.*]] = getelementptr {{.*}} %[[DST_I]], i64 0, i64 0 + // CHECK: icmp eq %[[A]]* %[[BEGIN]], %[[END]] + // CHECK: %[[T0:.*]] = phi %[[A]]* + // CHECK: %[[T1:.*]] = getelementptr inbounds %[[A]], %[[A]]* %[[T0]], i64 -1 + // CHECK: call void @_ZN7pr285951AD1Ev(%[[A]]* %[[T1]]) + // CHECK: icmp eq %[[A]]* %[[T1]], %[[BEGIN]] (void) [array]{}; - - // Skip over the initialization loop. - // CHECK: [[BEGIN:%.*]] = getelementptr inbounds [3 x [5 x [[A]]]], [3 x [5 x [[A]]]]* [[ARRAY]], i32 0, i32 0, i32 0 } } |