Files
clang-p2996/clang/test/CodeGenCXX/temporaries.cpp
Aaron Ballman 0f1c1be196 [clang] Remove rdar links; NFC
We have a new policy in place making links to private resources
something we try to avoid in source and test files. Normally, we'd
organically switch to the new policy rather than make a sweeping change
across a project. However, Clang is in a somewhat special circumstance
currently: recently, I've had several new contributors run into rdar
links around test code which their patch was changing the behavior of.
This turns out to be a surprisingly bad experience, especially for
newer folks, for a handful of reasons: not understanding what the link
is and feeling intimidated by it, wondering whether their changes are
actually breaking something important to a downstream in some way,
having to hunt down strangers not involved with the patch to impose on
them for help, accidental pressure from asking for potentially private
IP to be made public, etc. Because folks run into these links entirely
by chance (through fixing bugs or working on new features), there's not
really a set of problematic links to focus on -- all of the links have
basically the same potential for causing these problems. As a result,
this is an omnibus patch to remove all such links.

This was not a mechanical change; it was done by manually searching for
rdar, radar, radr, and other variants to find all the various
problematic links. From there, I tried to retain or reword the
surrounding comments so that we would lose as little context as
possible. However, because most links were just a plain link with no
supporting context, the majority of the changes are simple removals.

Differential Review: https://reviews.llvm.org/D158071
2023-08-28 12:13:42 -04:00

927 lines
28 KiB
C++

// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -std=c++11 | FileCheck %s -check-prefixes=CHECK,NULL-INVALID,CHECK-CXX11
// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -std=c++17 | FileCheck %s -check-prefixes=CHECK,NULL-INVALID,CHECK-CXX17
// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -std=c++11 -fno-delete-null-pointer-checks | FileCheck %s -check-prefixes=CHECK,NULL-VALID,CHECK-CXX11
namespace PR16263 {
const unsigned int n = 1234;
extern const int &r = (const int&)n;
// CHECK: @_ZGRN7PR162631rE_ = internal constant i32 1234,
// CHECK: @_ZN7PR162631rE ={{.*}} constant ptr @_ZGRN7PR162631rE_,
extern const int &s = reinterpret_cast<const int&>(n);
// CHECK: @_ZN7PR16263L1nE = internal constant i32 1234, align 4
// CHECK: @_ZN7PR162631sE ={{.*}} constant ptr @_ZN7PR16263L1nE, align 8
struct A { int n; };
struct B { int n; };
struct C : A, B {};
extern const A &&a = (A&&)(A&&)(C&&)(C{});
// CHECK: @_ZGRN7PR162631aE_ = internal global {{.*}} zeroinitializer,
// CHECK: @_ZN7PR162631aE ={{.*}} constant {{.*}} @_ZGRN7PR162631aE_
extern const int &&t = ((B&&)C{}).n;
// CHECK: @_ZGRN7PR162631tE_ = internal global {{.*}} zeroinitializer,
// CHECK: @_ZN7PR162631tE ={{.*}} constant ptr {{.*}} @_ZGRN7PR162631tE_, {{.*}} 4
struct D { double d; C c; };
extern const int &&u = (123, static_cast<B&&>(0, ((D&&)D{}).*&D::c).n);
// CHECK: @_ZGRN7PR162631uE_ = internal global {{.*}} zeroinitializer
// CHECK: @_ZN7PR162631uE ={{.*}} constant ptr {{.*}} @_ZGRN7PR162631uE_, {{.*}} 12
}
namespace PR20227 {
struct A { ~A(); };
struct B { virtual ~B(); };
struct C : B {};
A &&a = dynamic_cast<A&&>(A{});
// CHECK: @_ZGRN7PR202271aE_ = internal global
B &&b = dynamic_cast<C&&>(dynamic_cast<B&&>(C{}));
// CHECK: @_ZGRN7PR202271bE_ = internal global
B &&c = static_cast<C&&>(static_cast<B&&>(C{}));
// CHECK: @_ZGRN7PR202271cE_ = internal global
}
namespace BraceInit {
typedef const int &CIR;
CIR x = CIR{3};
// CHECK-CXX11: @_ZGRN9BraceInit1xE_ = internal constant i32 3
// FIXME: This should still be emitted as 'constant' in C++17.
// CHECK-CXX17: @_ZGRN9BraceInit1xE_ = internal global i32 3
// CHECK: @_ZN9BraceInit1xE ={{.*}} constant ptr @_ZGRN9BraceInit1xE_
}
namespace RefTempSubobject {
struct SelfReferential {
int *p = ints;
int ints[3] = {1, 2, 3};
};
// CHECK: @_ZGRN16RefTempSubobject2srE_ = internal global { ptr, [3 x i32] } { {{.*}} getelementptr {{.*}} @_ZGRN16RefTempSubobject2srE_, {{.*}}, [3 x i32] [i32 1, i32 2, i32 3] }
// CHECK: @_ZN16RefTempSubobject2srE = constant {{.*}} @_ZGRN16RefTempSubobject2srE_
constexpr const SelfReferential &sr = SelfReferential();
}
struct A {
A();
~A();
void f();
};
void f1() {
// CHECK: call void @_ZN1AC1Ev
// CHECK: call void @_ZN1AD1Ev
(void)A();
// CHECK: call void @_ZN1AC1Ev
// CHECK: call void @_ZN1AD1Ev
A().f();
}
// Function calls
struct B {
B();
~B();
};
B g();
void f2() {
// CHECK-NOT: call void @_ZN1BC1Ev
// CHECK: call void @_ZN1BD1Ev
(void)g();
}
// Member function calls
struct C {
C();
~C();
C f();
};
void f3() {
// CHECK: call void @_ZN1CC1Ev
// CHECK: call void @_ZN1CD1Ev
// CHECK: call void @_ZN1CD1Ev
C().f();
}
// Function call operator
struct D {
D();
~D();
D operator()();
};
void f4() {
// CHECK: call void @_ZN1DC1Ev
// CHECK: call void @_ZN1DD1Ev
// CHECK: call void @_ZN1DD1Ev
D()();
}
// Overloaded operators
struct E {
E();
~E();
E operator+(const E&);
E operator!();
};
void f5() {
// CHECK: call void @_ZN1EC1Ev
// CHECK: call void @_ZN1EC1Ev
// CHECK: call void @_ZN1ED1Ev
// CHECK: call void @_ZN1ED1Ev
// CHECK: call void @_ZN1ED1Ev
E() + E();
// CHECK: call void @_ZN1EC1Ev
// CHECK: call void @_ZN1ED1Ev
// CHECK: call void @_ZN1ED1Ev
!E();
}
struct F {
F();
~F();
F& f();
};
void f6() {
// CHECK: call void @_ZN1FC1Ev
// CHECK: call void @_ZN1FD1Ev
F().f();
}
struct G {
G();
G(A);
~G();
operator A();
};
void a(const A&);
void f7() {
// CHECK: call void @_ZN1AC1Ev
// CHECK: call void @_Z1aRK1A
// CHECK: call void @_ZN1AD1Ev
a(A());
// CHECK: call void @_ZN1GC1Ev
// CHECK: call void @_ZN1Gcv1AEv
// CHECK: call void @_Z1aRK1A
// CHECK: call void @_ZN1AD1Ev
// CHECK: call void @_ZN1GD1Ev
a(G());
}
namespace PR5077 {
struct A {
A();
~A();
int f();
};
void f();
int g(const A&);
struct B {
int a1;
int a2;
B();
~B();
};
B::B()
// CHECK: call void @_ZN6PR50771AC1Ev
// CHECK: call noundef i32 @_ZN6PR50771A1fEv
// CHECK: call void @_ZN6PR50771AD1Ev
: a1(A().f())
// CHECK: call void @_ZN6PR50771AC1Ev
// CHECK: call noundef i32 @_ZN6PR50771gERKNS_1AE
// CHECK: call void @_ZN6PR50771AD1Ev
, a2(g(A()))
{
// CHECK: call void @_ZN6PR50771fEv
f();
}
}
A f8() {
// CHECK: call void @_ZN1AC1Ev
// CHECK-NOT: call void @_ZN1AD1Ev
return A();
// CHECK: ret void
}
struct H {
H();
~H();
H(const H&);
};
void f9(H h) {
// CHECK: call void @_ZN1HC1Ev
// CHECK: call void @_Z2f91H
// CHECK: call void @_ZN1HD1Ev
f9(H());
// CHECK: call void @_ZN1HC1ERKS_
// CHECK: call void @_Z2f91H
// CHECK: call void @_ZN1HD1Ev
f9(h);
}
void f10(const H&);
void f11(H h) {
// CHECK: call void @_ZN1HC1Ev
// CHECK: call void @_Z3f10RK1H
// CHECK: call void @_ZN1HD1Ev
f10(H());
// CHECK: call void @_Z3f10RK1H
// CHECK-NOT: call void @_ZN1HD1Ev
// CHECK: ret void
f10(h);
}
// PR5808
struct I {
I(const char *);
~I();
};
// CHECK: _Z3f12v
I f12() {
// CHECK: call void @_ZN1IC1EPKc
// CHECK-NOT: call void @_ZN1ID1Ev
// CHECK: ret void
return "Hello";
}
// PR5867
namespace PR5867 {
struct S {
S();
S(const S &);
~S();
};
void f(S, int);
// CHECK-LABEL: define{{.*}} void @_ZN6PR58671gEv
void g() {
// CHECK: call void @_ZN6PR58671SC1Ev
// CHECK-NEXT: call void @_ZN6PR58671fENS_1SEi
// CHECK-NEXT: call void @_ZN6PR58671SD1Ev
// CHECK-NEXT: ret void
(f)(S(), 0);
}
// CHECK-LABEL: define linkonce_odr void @_ZN6PR58672g2IiEEvT_
template<typename T>
void g2(T) {
// CHECK: call void @_ZN6PR58671SC1Ev
// CHECK-NEXT: call void @_ZN6PR58671fENS_1SEi
// CHECK-NEXT: call void @_ZN6PR58671SD1Ev
// CHECK-NEXT: ret void
(f)(S(), 0);
}
void h() {
g2(17);
}
}
// PR6199
namespace PR6199 {
struct A { ~A(); };
struct B { operator A(); };
// CHECK-LABEL: define weak_odr void @_ZN6PR61992f2IiEENS_1AET_
template<typename T> A f2(T) {
B b;
// CHECK: call void @_ZN6PR61991BcvNS_1AEEv
// CHECK-NEXT: ret void
return b;
}
template A f2<int>(int);
}
namespace T12 {
struct A {
A();
~A();
int f();
};
int& f(int);
// CHECK-LABEL: define{{.*}} void @_ZN3T121gEv
void g() {
// CHECK: call void @_ZN3T121AC1Ev
// CHECK-NEXT: call noundef i32 @_ZN3T121A1fEv(
// CHECK-NEXT: call noundef {{(nonnull )?}}align {{[0-9]+}} dereferenceable({{[0-9]+}}) ptr @_ZN3T121fEi(
// CHECK-NEXT: call void @_ZN3T121AD1Ev(
int& i = f(A().f());
}
}
namespace PR6648 {
struct B {
~B();
};
B foo;
struct D;
D& zed(B);
void foobar() {
// NULL-INVALID: call noundef nonnull align 1 ptr @_ZN6PR66483zedENS_1BE
// NULL-VALID: call noundef align 1 ptr @_ZN6PR66483zedENS_1BE
zed(foo);
}
}
namespace UserConvertToValue {
struct X {
X(int);
X(const X&);
~X();
};
void f(X);
// CHECK: void @_ZN18UserConvertToValue1gEv()
void g() {
// CHECK: call void @_ZN18UserConvertToValue1XC1Ei
// CHECK: call void @_ZN18UserConvertToValue1fENS_1XE
// CHECK: call void @_ZN18UserConvertToValue1XD1Ev
// CHECK: ret void
f(1);
}
}
namespace PR7556 {
struct A { ~A(); };
struct B { int i; ~B(); };
struct C { int C::*pm; ~C(); };
// CHECK-LABEL: define{{.*}} void @_ZN6PR75563fooEv()
void foo() {
// CHECK: call void @_ZN6PR75561AD1Ev
A();
// CHECK: call void @llvm.memset.p0.i64
// CHECK: call void @_ZN6PR75561BD1Ev
B();
// CHECK: call void @llvm.memcpy.p0.p0.i64
// CHECK: call void @_ZN6PR75561CD1Ev
C();
// CHECK-NEXT: ret void
}
}
namespace Elision {
struct A {
A(); A(const A &); ~A();
void *p;
void foo() const;
};
void foo();
A fooA();
void takeA(A a);
// CHECK-LABEL: define{{.*}} void @_ZN7Elision5test0Ev()
void test0() {
// CHECK: [[I:%.*]] = alloca [[A:%.*]], align 8
// CHECK-NEXT: [[J:%.*]] = alloca [[A]], align 8
// CHECK-NEXT: [[T0:%.*]] = alloca [[A]], align 8
// CHECK-NEXT: [[K:%.*]] = alloca [[A]], align 8
// CHECK-NEXT: [[T1:%.*]] = alloca [[A]], align 8
// CHECK-NEXT: call void @_ZN7Elision3fooEv()
// CHECK-NEXT: call void @_ZN7Elision1AC1Ev(ptr {{[^,]*}} [[I]])
A i = (foo(), A());
// CHECK-NEXT: call void @_ZN7Elision4fooAEv(ptr sret([[A]]) align 8 [[T0]])
// CHECK-NEXT: call void @_ZN7Elision1AC1Ev(ptr {{[^,]*}} [[J]])
// CHECK-NEXT: call void @_ZN7Elision1AD1Ev(ptr {{[^,]*}} [[T0]])
A j = (fooA(), A());
// CHECK-NEXT: call void @_ZN7Elision1AC1Ev(ptr {{[^,]*}} [[T1]])
// CHECK-NEXT: call void @_ZN7Elision4fooAEv(ptr sret([[A]]) align 8 [[K]])
// CHECK-NEXT: call void @_ZN7Elision1AD1Ev(ptr {{[^,]*}} [[T1]])
A k = (A(), fooA());
// CHECK-NEXT: call void @_ZN7Elision1AD1Ev(ptr {{[^,]*}} [[K]])
// CHECK-NEXT: call void @_ZN7Elision1AD1Ev(ptr {{[^,]*}} [[J]])
// CHECK-NEXT: call void @_ZN7Elision1AD1Ev(ptr {{[^,]*}} [[I]])
}
// CHECK-LABEL: define{{.*}} void @_ZN7Elision5test1EbNS_1AE(
void test1(bool c, A x) {
// CHECK: [[I:%.*]] = alloca [[A]], align 8
// CHECK-NEXT: [[J:%.*]] = alloca [[A]], align 8
// CHECK: call void @_ZN7Elision1AC1Ev(ptr {{[^,]*}} [[I]])
// CHECK: call void @_ZN7Elision1AC1ERKS0_(ptr {{[^,]*}} [[I]], ptr noundef {{(nonnull )?}}align {{[0-9]+}} dereferenceable({{[0-9]+}}) [[X:%.*]])
A i = (c ? A() : x);
// CHECK: call void @_ZN7Elision1AC1ERKS0_(ptr {{[^,]*}} [[J]], ptr noundef {{(nonnull )?}}align {{[0-9]+}} dereferenceable({{[0-9]+}}) [[X]])
// CHECK: call void @_ZN7Elision1AC1Ev(ptr {{[^,]*}} [[J]])
A j = (c ? x : A());
// CHECK: call void @_ZN7Elision1AD1Ev(ptr {{[^,]*}} [[J]])
// CHECK-NEXT: call void @_ZN7Elision1AD1Ev(ptr {{[^,]*}} [[I]])
}
// CHECK: define{{.*}} void @_ZN7Elision5test2Ev(ptr noalias sret([[A]]) align 8
A test2() {
// CHECK: call void @_ZN7Elision3fooEv()
// CHECK-NEXT: call void @_ZN7Elision1AC1Ev(ptr {{[^,]*}} [[RET:%.*]])
// CHECK-NEXT: ret void
return (foo(), A());
}
// CHECK: define{{.*}} void @_ZN7Elision5test3EiNS_1AE(ptr noalias sret([[A]]) align 8
A test3(int v, A x) {
if (v < 5)
// CHECK: call void @_ZN7Elision1AC1Ev(ptr {{[^,]*}} [[RET:%.*]])
// CHECK: call void @_ZN7Elision1AC1ERKS0_(ptr {{[^,]*}} [[RET]], ptr noundef {{(nonnull )?}}align {{[0-9]+}} dereferenceable({{[0-9]+}}) [[X:%.*]])
return (v < 0 ? A() : x);
else
// CHECK: call void @_ZN7Elision1AC1ERKS0_(ptr {{[^,]*}} [[RET]], ptr noundef {{(nonnull )?}}align {{[0-9]+}} dereferenceable({{[0-9]+}}) [[X]])
// CHECK: call void @_ZN7Elision1AC1Ev(ptr {{[^,]*}} [[RET]])
return (v > 10 ? x : A());
// CHECK: ret void
}
// CHECK-LABEL: define{{.*}} void @_ZN7Elision5test4Ev()
void test4() {
// CHECK: [[X:%.*]] = alloca [[A]], align 8
// CHECK-NEXT: [[XS:%.*]] = alloca [2 x [[A]]], align 16
// CHECK-NEXT: call void @_ZN7Elision1AC1Ev(ptr {{[^,]*}} [[X]])
A x;
// CHECK-NEXT: [[XS0:%.*]] = getelementptr inbounds [2 x [[A]]], ptr [[XS]], i64 0, i64 0
// CHECK-NEXT: call void @_ZN7Elision1AC1Ev(ptr {{[^,]*}} [[XS0]])
// CHECK-NEXT: [[XS1:%.*]] = getelementptr inbounds [[A]], ptr [[XS0]], i64 1
// CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_(ptr {{[^,]*}} [[XS1]], ptr noundef {{(nonnull )?}}align {{[0-9]+}} dereferenceable({{[0-9]+}}) [[X]])
A xs[] = { A(), x };
// CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [2 x [[A]]], ptr [[XS]], i32 0, i32 0
// CHECK-NEXT: [[END:%.*]] = getelementptr inbounds [[A]], ptr [[BEGIN]], i64 2
// CHECK-NEXT: br label
// CHECK: [[AFTER:%.*]] = phi ptr
// CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds [[A]], ptr [[AFTER]], i64 -1
// CHECK-NEXT: call void @_ZN7Elision1AD1Ev(ptr {{[^,]*}} [[CUR]])
// CHECK-NEXT: [[T0:%.*]] = icmp eq ptr [[CUR]], [[BEGIN]]
// CHECK-NEXT: br i1 [[T0]],
// CHECK: call void @_ZN7Elision1AD1Ev(ptr {{[^,]*}} [[X]])
}
// CHECK: define{{.*}} void @_ZN7Elision5test5Ev(ptr noalias sret([[A]]) align 8
struct B { A a; B(); };
A test5() {
// CHECK: [[AT0:%.*]] = alloca [[A]], align 8
// CHECK-NEXT: [[BT0:%.*]] = alloca [[B:%.*]], align 8
// CHECK-NEXT: [[X:%.*]] = alloca [[A]], align 8
// CHECK-NEXT: [[BT1:%.*]] = alloca [[B]], align 8
// CHECK-NEXT: [[BT2:%.*]] = alloca [[B]], align 8
// CHECK: call void @_ZN7Elision1BC1Ev(ptr {{[^,]*}} [[BT0]])
// CHECK-NEXT: [[AM:%.*]] = getelementptr inbounds [[B]], ptr [[BT0]], i32 0, i32 0
// CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_(ptr {{[^,]*}} [[AT0]], ptr noundef {{(nonnull )?}}align {{[0-9]+}} dereferenceable({{[0-9]+}}) [[AM]])
// CHECK-NEXT: call void @_ZN7Elision5takeAENS_1AE(ptr noundef [[AT0]])
// CHECK-NEXT: call void @_ZN7Elision1AD1Ev(ptr {{[^,]*}} [[AT0]])
// CHECK-NEXT: call void @_ZN7Elision1BD1Ev(ptr {{[^,]*}} [[BT0]])
takeA(B().a);
// CHECK-NEXT: call void @_ZN7Elision1BC1Ev(ptr {{[^,]*}} [[BT1]])
// CHECK-NEXT: [[AM:%.*]] = getelementptr inbounds [[B]], ptr [[BT1]], i32 0, i32 0
// CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_(ptr {{[^,]*}} [[X]], ptr noundef {{(nonnull )?}}align {{[0-9]+}} dereferenceable({{[0-9]+}}) [[AM]])
// CHECK-NEXT: call void @_ZN7Elision1BD1Ev(ptr {{[^,]*}} [[BT1]])
A x = B().a;
// CHECK-NEXT: call void @_ZN7Elision1BC1Ev(ptr {{[^,]*}} [[BT2]])
// CHECK-NEXT: [[AM:%.*]] = getelementptr inbounds [[B]], ptr [[BT2]], i32 0, i32 0
// CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_(ptr {{[^,]*}} [[RET:%.*]], ptr noundef {{(nonnull )?}}align {{[0-9]+}} dereferenceable({{[0-9]+}}) [[AM]])
// CHECK-NEXT: call void @_ZN7Elision1BD1Ev(ptr {{[^,]*}} [[BT2]])
return B().a;
// CHECK: call void @_ZN7Elision1AD1Ev(ptr {{[^,]*}} [[X]])
}
// Reduced from webkit.
// CHECK: define{{.*}} void @_ZN7Elision5test6EPKNS_1CE(ptr
struct C { operator A() const; };
void test6(const C *x) {
// CHECK: [[T0:%.*]] = alloca [[A]], align 8
// CHECK: [[X:%.*]] = load ptr, ptr {{%.*}}, align 8
// CHECK-NEXT: call void @_ZNK7Elision1CcvNS_1AEEv(ptr sret([[A]]) align 8 [[T0]], ptr {{[^,]*}} [[X]])
// CHECK-NEXT: call void @_ZNK7Elision1A3fooEv(ptr {{[^,]*}} [[T0]])
// CHECK-NEXT: call void @_ZN7Elision1AD1Ev(ptr {{[^,]*}} [[T0]])
// CHECK-NEXT: ret void
A(*x).foo();
}
}
namespace PR8623 {
struct A { A(int); ~A(); };
// CHECK-LABEL: define{{.*}} void @_ZN6PR86233fooEb(
void foo(bool b) {
// CHECK: [[TMP:%.*]] = alloca [[A:%.*]], align 1
// CHECK-NEXT: [[LCONS:%.*]] = alloca i1
// CHECK-NEXT: [[RCONS:%.*]] = alloca i1
// CHECK: store i1 false, ptr [[LCONS]]
// CHECK-NEXT: store i1 false, ptr [[RCONS]]
// CHECK-NEXT: br i1
// CHECK: call void @_ZN6PR86231AC1Ei(ptr {{[^,]*}} [[TMP]], i32 noundef 2)
// CHECK-NEXT: store i1 true, ptr [[LCONS]]
// CHECK-NEXT: br label
// CHECK: call void @_ZN6PR86231AC1Ei(ptr {{[^,]*}} [[TMP]], i32 noundef 3)
// CHECK-NEXT: store i1 true, ptr [[RCONS]]
// CHECK-NEXT: br label
// CHECK: load i1, ptr [[RCONS]]
// CHECK-NEXT: br i1
// CHECK: call void @_ZN6PR86231AD1Ev(ptr {{[^,]*}} [[TMP]])
// CHECK-NEXT: br label
// CHECK: load i1, ptr [[LCONS]]
// CHECK-NEXT: br i1
// CHECK: call void @_ZN6PR86231AD1Ev(ptr {{[^,]*}} [[TMP]])
// CHECK-NEXT: br label
// CHECK: ret void
b ? A(2) : A(3);
}
}
namespace PR11365 {
struct A { A(); ~A(); };
// CHECK-LABEL: define{{.*}} void @_ZN7PR113653fooEv(
void foo() {
// CHECK: [[BEGIN:%.*]] = getelementptr inbounds [3 x [[A:%.*]]], ptr {{.*}}, i32 0, i32 0
// CHECK-NEXT: [[END:%.*]] = getelementptr inbounds [[A]], ptr [[BEGIN]], i64 3
// CHECK-NEXT: br label
// CHECK: [[PHI:%.*]] = phi
// CHECK-NEXT: [[ELEM:%.*]] = getelementptr inbounds [[A]], ptr [[PHI]], i64 -1
// CHECK-NEXT: call void @_ZN7PR113651AD1Ev(ptr {{[^,]*}} [[ELEM]])
// CHECK-NEXT: icmp eq ptr [[ELEM]], [[BEGIN]]
// CHECK-NEXT: br i1
(void) (A [3]) {};
}
}
namespace AssignmentOp {
struct A { ~A(); };
struct B { A operator=(const B&); };
struct C : B { B b1, b2; };
// CHECK-LABEL: define{{.*}} void @_ZN12AssignmentOp1fE
void f(C &c1, const C &c2) {
// CHECK: call {{.*}} @_ZN12AssignmentOp1CaSERKS0_(
c1 = c2;
}
// Ensure that each 'A' temporary is destroyed before the next subobject is
// copied.
// CHECK: define {{.*}} @_ZN12AssignmentOp1CaSERKS0_(
// CHECK: call {{.*}} @_ZN12AssignmentOp1BaSERKS
// CHECK: call {{.*}} @_ZN12AssignmentOp1AD1Ev(
// CHECK: call {{.*}} @_ZN12AssignmentOp1BaSERKS
// CHECK: call {{.*}} @_ZN12AssignmentOp1AD1Ev(
// CHECK: call {{.*}} @_ZN12AssignmentOp1BaSERKS
// CHECK: call {{.*}} @_ZN12AssignmentOp1AD1Ev(
}
namespace BindToSubobject {
struct A {
A();
~A();
int a;
};
void f(), g();
// CHECK: call void @_ZN15BindToSubobject1AC1Ev({{.*}} @_ZGRN15BindToSubobject1aE_)
// CHECK: call i32 @__cxa_atexit({{.*}} @_ZN15BindToSubobject1AD1Ev, ptr @_ZGRN15BindToSubobject1aE_, ptr @__dso_handle)
// CHECK: store ptr @_ZGRN15BindToSubobject1aE_, ptr @_ZN15BindToSubobject1aE, align 8
int &&a = A().a;
// CHECK: call void @_ZN15BindToSubobject1fEv()
// CHECK: call void @_ZN15BindToSubobject1AC1Ev({{.*}} @_ZGRN15BindToSubobject1bE_)
// CHECK: call i32 @__cxa_atexit({{.*}} @_ZN15BindToSubobject1AD1Ev, ptr @_ZGRN15BindToSubobject1bE_, ptr @__dso_handle)
// CHECK: store ptr @_ZGRN15BindToSubobject1bE_, ptr @_ZN15BindToSubobject1bE, align 8
int &&b = (f(), A().a);
int A::*h();
// CHECK: call void @_ZN15BindToSubobject1fEv()
// CHECK: call void @_ZN15BindToSubobject1gEv()
// CHECK: call void @_ZN15BindToSubobject1AC1Ev({{.*}} @_ZGRN15BindToSubobject1cE_)
// CHECK: call i32 @__cxa_atexit({{.*}} @_ZN15BindToSubobject1AD1Ev, ptr @_ZGRN15BindToSubobject1cE_, ptr @__dso_handle)
// CHECK: call {{.*}} @_ZN15BindToSubobject1hE
// CHECK: getelementptr
// CHECK: store ptr {{.*}}, ptr @_ZN15BindToSubobject1cE, align 8
int &&c = (f(), (g(), A().*h()));
struct B {
int padding;
A a;
};
// CHECK: call void @_ZN15BindToSubobject1BC1Ev({{.*}} @_ZGRN15BindToSubobject1dE_)
// CHECK: call i32 @__cxa_atexit({{.*}} @_ZN15BindToSubobject1BD1Ev, ptr @_ZGRN15BindToSubobject1dE_, ptr @__dso_handle)
// CHECK: call {{.*}} @_ZN15BindToSubobject1hE
// CHECK: getelementptr {{.*}} getelementptr
// CHECK: store ptr {{.*}}, ptr @_ZN15BindToSubobject1dE, align 8
int &&d = (B().a).*h();
}
namespace Bitfield {
struct S { int a : 5; ~S(); };
// Do not lifetime extend the S() temporary here.
// CHECK: alloca
// CHECK: call {{.*}}memset
// CHECK: store i32 {{.*}}, ptr @_ZGRN8Bitfield1rE_
// CHECK: call void @_ZN8Bitfield1SD1
// CHECK: store ptr @_ZGRN8Bitfield1rE_, ptr @_ZN8Bitfield1rE, align 8
int &&r = S().a;
}
namespace Vector {
typedef __attribute__((vector_size(16))) int vi4a;
typedef __attribute__((ext_vector_type(4))) int vi4b;
struct S {
vi4a v;
vi4b w;
};
// CHECK: alloca
// CHECK: extractelement
// CHECK: store i32 {{.*}}, ptr @_ZGRN6Vector1rE_
// CHECK: store ptr @_ZGRN6Vector1rE_, ptr @_ZN6Vector1rE,
int &&r = S().v[1];
// CHECK: alloca
// CHECK: extractelement
// CHECK: store i32 {{.*}}, ptr @_ZGRN6Vector1sE_
// CHECK: store ptr @_ZGRN6Vector1sE_, ptr @_ZN6Vector1sE,
int &&s = S().w[1];
// FIXME PR16204: The following code leads to an assertion in Sema.
//int &&s = S().w.y;
}
namespace ImplicitTemporaryCleanup {
struct A { A(int); ~A(); };
void g();
// CHECK-LABEL: define{{.*}} void @_ZN24ImplicitTemporaryCleanup1fEv(
void f() {
// CHECK: call {{.*}} @_ZN24ImplicitTemporaryCleanup1AC1Ei(
A &&a = 0;
// CHECK: call {{.*}} @_ZN24ImplicitTemporaryCleanup1gEv(
g();
// CHECK: call {{.*}} @_ZN24ImplicitTemporaryCleanup1AD1Ev(
}
}
namespace MultipleExtension {
struct A { A(); ~A(); };
struct B { B(); ~B(); };
struct C { C(); ~C(); };
struct D { D(); ~D(); int n; C c; };
struct E { const A &a; B b; const C &c; ~E(); };
E &&e1 = { A(), B(), D().c };
// CHECK: call void @_ZN17MultipleExtension1AC1Ev({{.*}} @[[TEMPA:_ZGRN17MultipleExtension2e1E.*]])
// CHECK: call i32 @__cxa_atexit({{.*}} @_ZN17MultipleExtension1AD1Ev, {{.*}} @[[TEMPA]]
// CHECK: store {{.*}} @[[TEMPA]], {{.*}} @[[TEMPE:_ZGRN17MultipleExtension2e1E.*]],
// CHECK: call void @_ZN17MultipleExtension1BC1Ev({{.*}} getelementptr inbounds ({{.*}} @[[TEMPE]], i32 0, i32 1))
// CHECK: call void @_ZN17MultipleExtension1DC1Ev({{.*}} @[[TEMPD:_ZGRN17MultipleExtension2e1E.*]])
// CHECK: call i32 @__cxa_atexit({{.*}} @_ZN17MultipleExtension1DD1Ev, {{.*}} @[[TEMPD]]
// CHECK: store {{.*}} @[[TEMPD]], {{.*}} getelementptr inbounds ({{.*}} @[[TEMPE]], i32 0, i32 2)
// CHECK: call i32 @__cxa_atexit({{.*}} @_ZN17MultipleExtension1ED1Ev, {{.*}} @[[TEMPE]]
// CHECK: store {{.*}} @[[TEMPE]], ptr @_ZN17MultipleExtension2e1E, align 8
E e2 = { A(), B(), D().c };
// CHECK: call void @_ZN17MultipleExtension1AC1Ev({{.*}} @[[TEMPA:_ZGRN17MultipleExtension2e2E.*]])
// CHECK: call i32 @__cxa_atexit({{.*}} @_ZN17MultipleExtension1AD1Ev, {{.*}} @[[TEMPA]]
// CHECK: store {{.*}} @[[TEMPA]], {{.*}} @[[E:_ZN17MultipleExtension2e2E]]
// CHECK: call void @_ZN17MultipleExtension1BC1Ev({{.*}} getelementptr inbounds ({{.*}} @[[E]], i32 0, i32 1))
// CHECK: call void @_ZN17MultipleExtension1DC1Ev({{.*}} @[[TEMPD:_ZGRN17MultipleExtension2e2E.*]])
// CHECK: call i32 @__cxa_atexit({{.*}} @_ZN17MultipleExtension1DD1Ev, {{.*}} @[[TEMPD]]
// CHECK: store {{.*}} @[[TEMPD]], {{.*}} getelementptr inbounds ({{.*}} @[[E]], i32 0, i32 2)
// CHECK: call i32 @__cxa_atexit({{.*}} @_ZN17MultipleExtension1ED1Ev, {{.*}} @[[E]]
void g();
// CHECK: define{{.*}} void @[[NS:_ZN17MultipleExtension]]1fEv(
void f() {
E &&e1 = { A(), B(), D().c };
// CHECK: %[[TEMPE1_A:.*]] = getelementptr inbounds {{.*}} %[[TEMPE1:.*]], i32 0, i32 0
// CHECK: call void @[[NS]]1AC1Ev({{.*}} %[[TEMPA1:.*]])
// CHECK: store {{.*}} %[[TEMPA1]], {{.*}} %[[TEMPE1_A]]
// CHECK: %[[TEMPE1_B:.*]] = getelementptr inbounds {{.*}} %[[TEMPE1]], i32 0, i32 1
// CHECK: call void @[[NS]]1BC1Ev({{.*}} %[[TEMPE1_B]])
// CHECK: %[[TEMPE1_C:.*]] = getelementptr inbounds {{.*}} %[[TEMPE1]], i32 0, i32 2
// CHECK: call void @[[NS]]1DC1Ev({{.*}} %[[TEMPD1:.*]])
// CHECK: %[[TEMPD1_C:.*]] = getelementptr inbounds {{.*}} %[[TEMPD1]], i32 0, i32 1
// CHECK: store {{.*}} %[[TEMPD1_C]], {{.*}} %[[TEMPE1_C]]
// CHECK: store {{.*}} %[[TEMPE1]], {{.*}} %[[E1:.*]]
g();
// CHECK: call void @[[NS]]1gEv()
E e2 = { A(), B(), D().c };
// CHECK: %[[TEMPE2_A:.*]] = getelementptr inbounds {{.*}} %[[E2:.*]], i32 0, i32 0
// CHECK: call void @[[NS]]1AC1Ev({{.*}} %[[TEMPA2:.*]])
// CHECK: store {{.*}} %[[TEMPA2]], {{.*}} %[[TEMPE2_A]]
// CHECK: %[[TEMPE2_B:.*]] = getelementptr inbounds {{.*}} %[[E2]], i32 0, i32 1
// CHECK: call void @[[NS]]1BC1Ev({{.*}} %[[TEMPE2_B]])
// CHECK: %[[TEMPE2_C:.*]] = getelementptr inbounds {{.*}} %[[E2]], i32 0, i32 2
// CHECK: call void @[[NS]]1DC1Ev({{.*}} %[[TEMPD2:.*]])
// CHECK: %[[TEMPD2_C:.*]] = getelementptr inbounds {{.*}} %[[TEMPD2]], i32 0, i32 1
// CHECK: store {{.*}} %[[TEMPD2_C]], ptr %[[TEMPE2_C]]
g();
// CHECK: call void @[[NS]]1gEv()
// CHECK: call void @[[NS]]1ED1Ev({{.*}} %[[E2]])
// CHECK: call void @[[NS]]1DD1Ev({{.*}} %[[TEMPD2]])
// CHECK: call void @[[NS]]1AD1Ev({{.*}} %[[TEMPA2]])
// CHECK: call void @[[NS]]1ED1Ev({{.*}} %[[TEMPE1]])
// CHECK: call void @[[NS]]1DD1Ev({{.*}} %[[TEMPD1]])
// CHECK: call void @[[NS]]1AD1Ev({{.*}} %[[TEMPA1]])
}
}
namespace ArrayAccess {
struct A { A(int); ~A(); };
void g();
void f() {
using T = A[3];
// CHECK: call void @_ZN11ArrayAccess1AC1Ei({{.*}}, i32 noundef 1
// CHECK-NOT: @_ZN11ArrayAccess1AD
// CHECK: call void @_ZN11ArrayAccess1AC1Ei({{.*}}, i32 noundef 2
// CHECK-NOT: @_ZN11ArrayAccess1AD
// CHECK: call void @_ZN11ArrayAccess1AC1Ei({{.*}}, i32 noundef 3
// CHECK-NOT: @_ZN11ArrayAccess1AD
A &&a = T{1, 2, 3}[1];
// CHECK: call void @_ZN11ArrayAccess1AC1Ei({{.*}}, i32 noundef 4
// CHECK-NOT: @_ZN11ArrayAccess1AD
// CHECK: call void @_ZN11ArrayAccess1AC1Ei({{.*}}, i32 noundef 5
// CHECK-NOT: @_ZN11ArrayAccess1AD
// CHECK: call void @_ZN11ArrayAccess1AC1Ei({{.*}}, i32 noundef 6
// CHECK-NOT: @_ZN11ArrayAccess1AD
A &&b = 2[T{4, 5, 6}];
// CHECK: call void @_ZN11ArrayAccess1gEv(
g();
// CHECK: call void @_ZN11ArrayAccess1AD
// CHECK: call void @_ZN11ArrayAccess1AD
}
}
namespace PR14130 {
struct S { S(int); };
struct U { S &&s; };
U v { { 0 } };
// CHECK: call void @_ZN7PR141301SC1Ei({{.*}} @_ZGRN7PR141301vE_, i32 noundef 0)
// CHECK: store {{.*}} @_ZGRN7PR141301vE_, {{.*}} @_ZN7PR141301vE
}
namespace Conditional {
struct A {};
struct B : A { B(); ~B(); };
struct C : A { C(); ~C(); };
void g();
// CHECK-LABEL: define {{.*}} @_ZN11Conditional1fEb(
void f(bool b) {
// CHECK: store i1 false, ptr %[[CLEANUP_B:.*]],
// CHECK: store i1 false, ptr %[[CLEANUP_C:.*]],
// CHECK: br i1
//
// CHECK: call {{.*}} @_ZN11Conditional1BC1Ev(
// CHECK: store i1 true, ptr %[[CLEANUP_B]],
// CHECK: br label
//
// CHECK: call {{.*}} @_ZN11Conditional1CC1Ev(
// CHECK: store i1 true, ptr %[[CLEANUP_C]],
// CHECK: br label
A &&r = b ? static_cast<A&&>(B()) : static_cast<A&&>(C());
// CHECK: call {{.*}} @_ZN11Conditional1gEv(
g();
// CHECK: load {{.*}} %[[CLEANUP_C]]
// CHECK: br i1
// CHECK: call {{.*}} @_ZN11Conditional1CD1Ev(
// CHECK: br label
// CHECK: load {{.*}} %[[CLEANUP_B]]
// CHECK: br i1
// CHECK: call {{.*}} @_ZN11Conditional1BD1Ev(
// CHECK: br label
}
struct D { A &&a; };
// CHECK-LABEL: define {{.*}} @_ZN11Conditional10f_indirectEb(
void f_indirect(bool b) {
// CHECK: store i1 false, ptr %[[CLEANUP_B:.*]],
// CHECK: store i1 false, ptr %[[CLEANUP_C:.*]],
// CHECK: br i1
//
// CHECK: call {{.*}} @_ZN11Conditional1BC1Ev(
// CHECK: store i1 true, ptr %[[CLEANUP_B]],
// CHECK: br label
//
// CHECK: call {{.*}} @_ZN11Conditional1CC1Ev(
// CHECK: store i1 true, ptr %[[CLEANUP_C]],
// CHECK: br label
D d = b ? D{B()} : D{C()};
// In C++17, the expression D{...} directly initializes the 'd' object, so
// lifetime-extending the temporaries to the lifetime of the D object
// extends them past the call to g().
//
// In C++14 and before, D is move-constructed from the result of the
// conditional expression, so no lifetime extension occurs.
// CHECK-CXX17: call {{.*}} @_ZN11Conditional1gEv(
// CHECK: load {{.*}} %[[CLEANUP_C]]
// CHECK: br i1
// CHECK: call {{.*}} @_ZN11Conditional1CD1Ev(
// CHECK: br label
// CHECK: load {{.*}} %[[CLEANUP_B]]
// CHECK: br i1
// CHECK: call {{.*}} @_ZN11Conditional1BD1Ev(
// CHECK: br label
// CHECK-CXX11: call {{.*}} @_ZN11Conditional1gEv(
g();
}
extern bool b;
// CHECK: load {{.*}} @_ZN11Conditional1b
// CHECK: br i1
//
// CHECK: call {{.*}} @_ZN11Conditional1BC1Ev({{.*}} @_ZGRN11Conditional1rE_)
// CHECK: call {{.*}} @__cxa_atexit({{.*}} @_ZN11Conditional1BD1Ev, ptr @_ZGRN11Conditional1rE_,
// CHECK: br label
//
// CHECK: call {{.*}} @_ZN11Conditional1CC1Ev({{.*}} @_ZGRN11Conditional1rE0_)
// CHECK: call {{.*}} @__cxa_atexit({{.*}} @_ZN11Conditional1CD1Ev, ptr @_ZGRN11Conditional1rE0_,
// CHECK: br label
A &&r = b ? static_cast<A&&>(B()) : static_cast<A&&>(C());
}
#if __cplusplus >= 201703L
namespace PR42220 {
struct X { X(); ~X(); };
struct A { X &&x; };
struct B : A {};
void g() noexcept;
// CHECK-CXX17-LABEL: define{{.*}} @_ZN7PR422201fEv(
void f() {
// CHECK-CXX17: call{{.*}} @_ZN7PR422201XC1Ev(
B &&b = {X()};
// CHECK-CXX17-NOT: call{{.*}} @_ZN7PR422201XD1Ev(
// CHECK-CXX17: call{{.*}} @_ZN7PR422201gEv(
g();
// CHECK-CXX17: call{{.*}} @_ZN7PR422201XD1Ev(
}
}
#endif