================
@@ -76,27 +76,45 @@ namespace test1 {
~A();
};
- // CHECK-LABEL: define{{.*}} void @_ZN5test14testEPA10_A20_NS_1AE(
- void test(A (*arr)[10][20]) {
+ // CHECK-LABEL: define{{.*}} void @_ZN5test11fEPA10_A20_NS_1AE(
+ void f(A (*arr)[10][20]) {
delete [] arr;
// CHECK: icmp eq ptr [[PTR:%.*]], null
// CHECK-NEXT: br i1
- // CHECK: [[BEGIN:%.*]] = getelementptr inbounds [10 x [20 x
[[A:%.*]]]], ptr [[PTR]], i32 0, i32 0, i32 0
- // CHECK-NEXT: [[ALLOC:%.*]] = getelementptr inbounds i8, ptr [[BEGIN]],
i64 -8
+ // CHECK: [[ALLOC:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64
-8
// CHECK-NEXT: [[COUNT:%.*]] = load i64, ptr [[ALLOC]]
- // CHECK: [[END:%.*]] = getelementptr inbounds [[A]], ptr [[BEGIN]],
i64 [[COUNT]]
- // CHECK-NEXT: [[ISEMPTY:%.*]] = icmp eq ptr [[BEGIN]], [[END]]
+ // CHECK: [[END:%.*]] = getelementptr inbounds [[A:%.*]], ptr
[[PTR]], i64 [[COUNT]]
+ // CHECK-NEXT: [[ISEMPTY:%.*]] = icmp eq ptr [[PTR]], [[END]]
// CHECK-NEXT: br i1 [[ISEMPTY]],
// CHECK: [[PAST:%.*]] = phi ptr [ [[END]], {{%.*}} ], [ [[CUR:%.*]],
{{%.*}} ]
// CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds [[A]], ptr [[PAST]],
i64 -1
// CHECK-NEXT: call void @_ZN5test11AD1Ev(ptr {{[^,]*}} [[CUR]])
- // CHECK-NEXT: [[ISDONE:%.*]] = icmp eq ptr [[CUR]], [[BEGIN]]
+ // CHECK-NEXT: [[ISDONE:%.*]] = icmp eq ptr [[CUR]], [[PTR]]
// CHECK-NEXT: br i1 [[ISDONE]]
// CHECK: [[MUL:%.*]] = mul i64 4, [[COUNT]]
// CHECK-NEXT: [[SIZE:%.*]] = add i64 [[MUL]], 8
// CHECK-NEXT: call void @_ZdaPvm(ptr noundef [[ALLOC]], i64 noundef
[[SIZE]])
}
+
+ // CHECK-LABEL: define{{.*}} void @_ZN5test11gEPA_NS_1AE(
+ void g(A (*arr)[]) {
+ delete [] arr;
+ // CHECK: icmp eq ptr [[PTR:%.*]], null
+ // CHECK-NEXT: br i1
+
+ // CHECK: [[ALLOC:%.*]] = getelementptr inbounds i8, ptr [[PTR]], i64
-8
+ // CHECK-NEXT: [[COUNT:%.*]] = load i64, ptr [[ALLOC]]
+ // CHECK: [[END:%.*]] = getelementptr inbounds [[A:%.*]], ptr
[[PTR]], i64 [[COUNT]]
+ // CHECK-NEXT: [[ISEMPTY:%.*]] = icmp eq ptr [[PTR]], [[END]]
+ // CHECK-NEXT: br i1 [[ISEMPTY]],
+ // CHECK: [[PAST:%.*]] = phi ptr [ [[END]], {{%.*}} ], [ [[CUR:%.*]],
{{%.*}} ]
+ // CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds [[A]], ptr [[PAST]],
i64 -1
+ // CHECK-NEXT: call void @_ZN5test11AD1Ev(ptr {{[^,]*}} [[CUR]])
+ // CHECK-NEXT: [[ISDONE:%.*]] = icmp eq ptr [[CUR]], [[PTR]]
+ // CHECK-NEXT: br i1 [[ISDONE]]
+ // CHECK: call void @_ZdaPv(ptr noundef [[ALLOC]])
----------------
hvdijk wrote:
Correcting myself: this may be unspecified, actually.
https://eel.is/c++draft/expr.delete#9 says:
> - If the type is complete and if, for an array delete expression only, the
> operand is a pointer to a class type with a non-trivial destructor or a
> (possibly multidimensional) array thereof, the function with a parameter of
> type `std::size_t` is selected.
> - Otherwise, it is unspecified whether a deallocation function with a
> parameter of type `std::size_t` is selected.
The type here is an incomplete array type so that first quoted point does not
apply, and the second point allows `operator delete [](void*, size_t)` to be
called but does not require it. GCC calls it and ideally we would too, but it's
not required.
https://github.com/llvm/llvm-project/pull/150359
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits