2018-07-24 06:56:45 +08:00
|
|
|
// 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
|
2013-06-15 08:30:29 +08:00
|
|
|
|
|
|
|
namespace PR16263 {
|
|
|
|
const unsigned int n = 1234;
|
|
|
|
extern const int &r = (const int&)n;
|
2015-02-20 03:25:17 +08:00
|
|
|
// CHECK: @_ZGRN7PR162631rE_ = internal constant i32 1234,
|
2014-05-07 06:49:16 +08:00
|
|
|
// CHECK: @_ZN7PR162631rE = constant i32* @_ZGRN7PR162631rE_,
|
2013-06-15 08:30:29 +08:00
|
|
|
|
|
|
|
extern const int &s = reinterpret_cast<const int&>(n);
|
|
|
|
// CHECK: @_ZN7PR16263L1nE = internal constant i32 1234, align 4
|
|
|
|
// CHECK: @_ZN7PR162631sE = constant i32* @_ZN7PR16263L1nE, align 8
|
|
|
|
|
|
|
|
struct A { int n; };
|
|
|
|
struct B { int n; };
|
|
|
|
struct C : A, B {};
|
|
|
|
extern const A &&a = (A&&)(A&&)(C&&)(C{});
|
2015-02-20 03:25:17 +08:00
|
|
|
// CHECK: @_ZGRN7PR162631aE_ = internal global {{.*}} zeroinitializer,
|
2014-05-07 06:49:16 +08:00
|
|
|
// CHECK: @_ZN7PR162631aE = constant {{.*}} bitcast ({{.*}}* @_ZGRN7PR162631aE_ to
|
2013-06-15 08:30:29 +08:00
|
|
|
|
|
|
|
extern const int &&t = ((B&&)C{}).n;
|
2015-02-20 03:25:17 +08:00
|
|
|
// CHECK: @_ZGRN7PR162631tE_ = internal global {{.*}} zeroinitializer,
|
2014-05-07 06:49:16 +08:00
|
|
|
// CHECK: @_ZN7PR162631tE = constant i32* {{.*}}* @_ZGRN7PR162631tE_ {{.*}} 4
|
2013-06-15 08:30:29 +08:00
|
|
|
|
|
|
|
struct D { double d; C c; };
|
|
|
|
extern const int &&u = (123, static_cast<B&&>(0, ((D&&)D{}).*&D::c).n);
|
2015-02-20 03:25:17 +08:00
|
|
|
// CHECK: @_ZGRN7PR162631uE_ = internal global {{.*}} zeroinitializer
|
2014-05-07 06:49:16 +08:00
|
|
|
// CHECK: @_ZN7PR162631uE = constant i32* {{.*}} @_ZGRN7PR162631uE_ {{.*}} 12
|
2013-06-15 08:30:29 +08:00
|
|
|
}
|
|
|
|
|
2014-07-09 01:25:14 +08:00
|
|
|
namespace PR20227 {
|
|
|
|
struct A { ~A(); };
|
|
|
|
struct B { virtual ~B(); };
|
|
|
|
struct C : B {};
|
|
|
|
|
|
|
|
A &&a = dynamic_cast<A&&>(A{});
|
2015-02-20 03:25:17 +08:00
|
|
|
// CHECK: @_ZGRN7PR202271aE_ = internal global
|
2014-07-09 01:25:14 +08:00
|
|
|
|
|
|
|
B &&b = dynamic_cast<C&&>(dynamic_cast<B&&>(C{}));
|
2015-02-20 03:25:17 +08:00
|
|
|
// CHECK: @_ZGRN7PR202271bE_ = internal global
|
2014-07-09 01:25:14 +08:00
|
|
|
|
|
|
|
B &&c = static_cast<C&&>(static_cast<B&&>(C{}));
|
2015-02-20 03:25:17 +08:00
|
|
|
// CHECK: @_ZGRN7PR202271cE_ = internal global
|
2014-07-09 01:25:14 +08:00
|
|
|
}
|
|
|
|
|
2015-01-10 09:28:13 +08:00
|
|
|
namespace BraceInit {
|
|
|
|
typedef const int &CIR;
|
|
|
|
CIR x = CIR{3};
|
2018-07-24 06:56:45 +08:00
|
|
|
// 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
|
2015-01-10 09:28:13 +08:00
|
|
|
// CHECK: @_ZN9BraceInit1xE = constant i32* @_ZGRN9BraceInit1xE_
|
|
|
|
}
|
|
|
|
|
2009-08-16 06:30:50 +08:00
|
|
|
struct A {
|
|
|
|
A();
|
|
|
|
~A();
|
|
|
|
void f();
|
|
|
|
};
|
|
|
|
|
2009-08-16 11:06:32 +08:00
|
|
|
void f1() {
|
2009-10-19 05:11:11 +08:00
|
|
|
// CHECK: call void @_ZN1AC1Ev
|
|
|
|
// CHECK: call void @_ZN1AD1Ev
|
2009-08-16 11:06:32 +08:00
|
|
|
(void)A();
|
2009-10-19 05:11:11 +08:00
|
|
|
|
|
|
|
// CHECK: call void @_ZN1AC1Ev
|
|
|
|
// CHECK: call void @_ZN1AD1Ev
|
2009-08-16 06:30:50 +08:00
|
|
|
A().f();
|
|
|
|
}
|
2009-08-16 11:06:32 +08:00
|
|
|
|
2009-08-16 11:42:12 +08:00
|
|
|
// Function calls
|
2009-08-16 11:06:32 +08:00
|
|
|
struct B {
|
|
|
|
B();
|
|
|
|
~B();
|
|
|
|
};
|
|
|
|
|
|
|
|
B g();
|
|
|
|
|
|
|
|
void f2() {
|
2009-10-19 05:11:11 +08:00
|
|
|
// CHECK-NOT: call void @_ZN1BC1Ev
|
|
|
|
// CHECK: call void @_ZN1BD1Ev
|
2009-08-16 11:06:32 +08:00
|
|
|
(void)g();
|
|
|
|
}
|
|
|
|
|
2009-08-16 11:42:12 +08:00
|
|
|
// Member function calls
|
|
|
|
struct C {
|
|
|
|
C();
|
|
|
|
~C();
|
|
|
|
|
|
|
|
C f();
|
|
|
|
};
|
|
|
|
|
|
|
|
void f3() {
|
2009-10-19 05:11:11 +08:00
|
|
|
// CHECK: call void @_ZN1CC1Ev
|
|
|
|
// CHECK: call void @_ZN1CD1Ev
|
|
|
|
// CHECK: call void @_ZN1CD1Ev
|
2009-08-16 11:42:12 +08:00
|
|
|
C().f();
|
|
|
|
}
|
|
|
|
|
2009-08-16 11:53:54 +08:00
|
|
|
// Function call operator
|
|
|
|
struct D {
|
|
|
|
D();
|
|
|
|
~D();
|
|
|
|
|
|
|
|
D operator()();
|
|
|
|
};
|
|
|
|
|
|
|
|
void f4() {
|
2009-11-01 04:42:26 +08:00
|
|
|
// CHECK: call void @_ZN1DC1Ev
|
|
|
|
// CHECK: call void @_ZN1DD1Ev
|
|
|
|
// CHECK: call void @_ZN1DD1Ev
|
2009-08-16 11:53:54 +08:00
|
|
|
D()();
|
|
|
|
}
|
2009-08-16 11:42:12 +08:00
|
|
|
|
2009-08-16 12:11:06 +08:00
|
|
|
// Overloaded operators
|
|
|
|
struct E {
|
|
|
|
E();
|
|
|
|
~E();
|
|
|
|
E operator+(const E&);
|
|
|
|
E operator!();
|
|
|
|
};
|
|
|
|
|
|
|
|
void f5() {
|
2009-10-19 05:11:11 +08:00
|
|
|
// CHECK: call void @_ZN1EC1Ev
|
|
|
|
// CHECK: call void @_ZN1EC1Ev
|
|
|
|
// CHECK: call void @_ZN1ED1Ev
|
|
|
|
// CHECK: call void @_ZN1ED1Ev
|
|
|
|
// CHECK: call void @_ZN1ED1Ev
|
2009-08-16 12:11:06 +08:00
|
|
|
E() + E();
|
2009-10-19 05:11:11 +08:00
|
|
|
|
|
|
|
// CHECK: call void @_ZN1EC1Ev
|
|
|
|
// CHECK: call void @_ZN1ED1Ev
|
|
|
|
// CHECK: call void @_ZN1ED1Ev
|
2009-08-16 12:11:06 +08:00
|
|
|
!E();
|
|
|
|
}
|
2009-08-16 11:42:12 +08:00
|
|
|
|
2009-09-14 09:30:44 +08:00
|
|
|
struct F {
|
|
|
|
F();
|
|
|
|
~F();
|
|
|
|
F& f();
|
|
|
|
};
|
|
|
|
|
|
|
|
void f6() {
|
2009-10-19 05:11:11 +08:00
|
|
|
// CHECK: call void @_ZN1FC1Ev
|
|
|
|
// CHECK: call void @_ZN1FD1Ev
|
2009-09-14 09:30:44 +08:00
|
|
|
F().f();
|
|
|
|
}
|
|
|
|
|
2009-10-19 05:20:14 +08:00
|
|
|
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());
|
|
|
|
}
|
2009-11-06 12:11:09 +08:00
|
|
|
|
|
|
|
namespace PR5077 {
|
|
|
|
|
|
|
|
struct A {
|
|
|
|
A();
|
|
|
|
~A();
|
|
|
|
int f();
|
|
|
|
};
|
|
|
|
|
|
|
|
void f();
|
|
|
|
int g(const A&);
|
|
|
|
|
|
|
|
struct B {
|
|
|
|
int a1;
|
|
|
|
int a2;
|
|
|
|
B();
|
2009-11-06 12:19:02 +08:00
|
|
|
~B();
|
2009-11-06 12:11:09 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
B::B()
|
|
|
|
// CHECK: call void @_ZN6PR50771AC1Ev
|
|
|
|
// CHECK: call i32 @_ZN6PR50771A1fEv
|
|
|
|
// CHECK: call void @_ZN6PR50771AD1Ev
|
|
|
|
: a1(A().f())
|
|
|
|
// CHECK: call void @_ZN6PR50771AC1Ev
|
|
|
|
// CHECK: call i32 @_ZN6PR50771gERKNS_1AE
|
|
|
|
// CHECK: call void @_ZN6PR50771AD1Ev
|
|
|
|
, a2(g(A()))
|
|
|
|
{
|
|
|
|
// CHECK: call void @_ZN6PR50771fEv
|
|
|
|
f();
|
|
|
|
}
|
|
|
|
|
2009-11-13 12:34:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
A f8() {
|
|
|
|
// CHECK: call void @_ZN1AC1Ev
|
|
|
|
// CHECK-NOT: call void @_ZN1AD1Ev
|
|
|
|
return A();
|
|
|
|
// CHECK: ret void
|
|
|
|
}
|
2009-11-06 12:19:02 +08:00
|
|
|
|
2009-11-13 12:34:45 +08:00
|
|
|
struct H {
|
|
|
|
H();
|
|
|
|
~H();
|
|
|
|
H(const H&);
|
|
|
|
};
|
2009-11-06 12:19:02 +08:00
|
|
|
|
2009-11-13 12:34:45 +08:00
|
|
|
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);
|
2009-11-06 12:11:09 +08:00
|
|
|
}
|
2009-11-14 01:04:35 +08:00
|
|
|
|
|
|
|
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);
|
2009-12-16 04:14:24 +08:00
|
|
|
}
|
Switch the initialization required by return statements over to the
new InitializationSequence. This fixes some bugs (e.g., PR5808),
changed some diagnostics, and caused more churn than expected. What's
new:
- InitializationSequence now has a "C conversion sequence" category
and step kind, which falls back to
- Changed the diagnostics for returns to always have the result type
of the function first and the type of the expression second.
CheckSingleAssignmentConstraints to peform checking in C.
- Improved ASTs for initialization of return values. The ASTs now
capture all of the temporaries we need to create, but
intentionally do not bind the tempoary that is actually returned,
so that it won't get destroyed twice.
- Make sure to perform an (elidable!) copy of the class object that
is returned from a class.
- Fix copy elision in CodeGen to properly see through the
subexpressions that occur with elidable copies.
- Give "new" its own entity kind; as with return values and thrown
objects, we don't bind the expression so we don't call a
destructor for it.
Note that, with this patch, I've broken returning move-only types in
C++0x. We'll fix it later, when we tackle NRVO.
llvm-svn: 91669
2009-12-18 13:02:21 +08:00
|
|
|
|
|
|
|
// 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";
|
|
|
|
}
|
2009-12-25 01:16:46 +08:00
|
|
|
|
|
|
|
// PR5867
|
|
|
|
namespace PR5867 {
|
|
|
|
struct S {
|
|
|
|
S();
|
|
|
|
S(const S &);
|
|
|
|
~S();
|
|
|
|
};
|
|
|
|
|
|
|
|
void f(S, int);
|
2013-08-15 14:47:53 +08:00
|
|
|
// CHECK-LABEL: define void @_ZN6PR58671gEv
|
2009-12-25 01:16:46 +08:00
|
|
|
void g() {
|
|
|
|
// CHECK: call void @_ZN6PR58671SC1Ev
|
|
|
|
// CHECK-NEXT: call void @_ZN6PR58671fENS_1SEi
|
|
|
|
// CHECK-NEXT: call void @_ZN6PR58671SD1Ev
|
|
|
|
// CHECK-NEXT: ret void
|
|
|
|
(f)(S(), 0);
|
|
|
|
}
|
2009-12-25 02:51:59 +08:00
|
|
|
|
2013-08-15 14:47:53 +08:00
|
|
|
// CHECK-LABEL: define linkonce_odr void @_ZN6PR58672g2IiEEvT_
|
2009-12-25 02:51:59 +08:00
|
|
|
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);
|
|
|
|
}
|
2009-12-25 01:16:46 +08:00
|
|
|
}
|
2010-02-02 15:10:35 +08:00
|
|
|
|
|
|
|
// PR6199
|
|
|
|
namespace PR6199 {
|
|
|
|
struct A { ~A(); };
|
|
|
|
|
|
|
|
struct B { operator A(); };
|
|
|
|
|
2013-08-15 14:47:53 +08:00
|
|
|
// CHECK-LABEL: define weak_odr void @_ZN6PR61992f2IiEENS_1AET_
|
2010-02-02 15:10:35 +08:00
|
|
|
template<typename T> A f2(T) {
|
|
|
|
B b;
|
|
|
|
// CHECK: call void @_ZN6PR61991BcvNS_1AEEv
|
|
|
|
// CHECK-NEXT: ret void
|
|
|
|
return b;
|
|
|
|
}
|
|
|
|
|
|
|
|
template A f2<int>(int);
|
|
|
|
|
|
|
|
}
|
2010-02-05 01:32:58 +08:00
|
|
|
|
|
|
|
namespace T12 {
|
|
|
|
|
|
|
|
struct A {
|
|
|
|
A();
|
|
|
|
~A();
|
|
|
|
int f();
|
|
|
|
};
|
|
|
|
|
|
|
|
int& f(int);
|
|
|
|
|
2013-08-15 14:47:53 +08:00
|
|
|
// CHECK-LABEL: define void @_ZN3T121gEv
|
2010-02-05 01:32:58 +08:00
|
|
|
void g() {
|
|
|
|
// CHECK: call void @_ZN3T121AC1Ev
|
|
|
|
// CHECK-NEXT: call i32 @_ZN3T121A1fEv(
|
2014-07-18 23:52:10 +08:00
|
|
|
// CHECK-NEXT: call dereferenceable({{[0-9]+}}) i32* @_ZN3T121fEi(
|
2010-02-05 01:32:58 +08:00
|
|
|
// CHECK-NEXT: call void @_ZN3T121AD1Ev(
|
|
|
|
int& i = f(A().f());
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2010-03-22 01:11:05 +08:00
|
|
|
|
|
|
|
namespace PR6648 {
|
|
|
|
struct B {
|
|
|
|
~B();
|
|
|
|
};
|
|
|
|
B foo;
|
|
|
|
struct D;
|
|
|
|
D& zed(B);
|
|
|
|
void foobar() {
|
[clang]: Add support for "-fno-delete-null-pointer-checks"
Summary:
Support for this option is needed for building Linux kernel.
This is a very frequently requested feature by kernel developers.
More details : https://lkml.org/lkml/2018/4/4/601
GCC option description for -fdelete-null-pointer-checks:
This Assume that programs cannot safely dereference null pointers,
and that no code or data element resides at address zero.
-fno-delete-null-pointer-checks is the inverse of this implying that
null pointer dereferencing is not undefined.
This feature is implemented in as the function attribute
"null-pointer-is-valid"="true".
This CL only adds the attribute on the function.
It also strips "nonnull" attributes from function arguments but
keeps the related warnings unchanged.
Corresponding LLVM change rL336613 already updated the
optimizations to not treat null pointer dereferencing
as undefined if the attribute is present.
Reviewers: t.p.northover, efriedma, jyknight, chandlerc, rnk, srhines, void, george.burgess.iv
Reviewed By: jyknight
Subscribers: drinkcat, xbolva00, cfe-commits
Differential Revision: https://reviews.llvm.org/D47894
llvm-svn: 337433
2018-07-19 08:44:52 +08:00
|
|
|
// NULL-INVALID: call nonnull %"struct.PR6648::D"* @_ZN6PR66483zedENS_1BE
|
|
|
|
// NULL-VALID: call %"struct.PR6648::D"* @_ZN6PR66483zedENS_1BE
|
2010-03-22 01:11:05 +08:00
|
|
|
zed(foo);
|
|
|
|
}
|
|
|
|
}
|
2010-04-25 08:55:24 +08:00
|
|
|
|
|
|
|
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
|
2010-04-25 08:56:07 +08:00
|
|
|
// CHECK: ret void
|
2010-04-25 08:55:24 +08:00
|
|
|
f(1);
|
|
|
|
}
|
|
|
|
}
|
2010-07-08 14:14:04 +08:00
|
|
|
|
|
|
|
namespace PR7556 {
|
|
|
|
struct A { ~A(); };
|
|
|
|
struct B { int i; ~B(); };
|
|
|
|
struct C { int C::*pm; ~C(); };
|
2013-08-15 14:47:53 +08:00
|
|
|
// CHECK-LABEL: define void @_ZN6PR75563fooEv()
|
2010-07-08 14:14:04 +08:00
|
|
|
void foo() {
|
|
|
|
// CHECK: call void @_ZN6PR75561AD1Ev
|
|
|
|
A();
|
|
|
|
// CHECK: call void @llvm.memset.p0i8.i64
|
|
|
|
// CHECK: call void @_ZN6PR75561BD1Ev
|
|
|
|
B();
|
|
|
|
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64
|
|
|
|
// CHECK: call void @_ZN6PR75561CD1Ev
|
|
|
|
C();
|
|
|
|
// CHECK-NEXT: ret void
|
|
|
|
}
|
|
|
|
}
|
2010-09-15 18:14:12 +08:00
|
|
|
|
|
|
|
namespace Elision {
|
2010-09-18 08:58:34 +08:00
|
|
|
struct A {
|
|
|
|
A(); A(const A &); ~A();
|
|
|
|
void *p;
|
|
|
|
void foo() const;
|
|
|
|
};
|
2010-09-15 18:14:12 +08:00
|
|
|
|
|
|
|
void foo();
|
|
|
|
A fooA();
|
2010-09-16 14:57:56 +08:00
|
|
|
void takeA(A a);
|
2010-09-15 18:14:12 +08:00
|
|
|
|
2013-08-15 14:47:53 +08:00
|
|
|
// CHECK-LABEL: define void @_ZN7Elision5test0Ev()
|
2010-09-15 18:14:12 +08:00
|
|
|
void test0() {
|
|
|
|
// CHECK: [[I:%.*]] = alloca [[A:%.*]], align 8
|
2010-09-15 18:38:11 +08:00
|
|
|
// 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
|
2010-09-15 18:14:12 +08:00
|
|
|
|
|
|
|
// CHECK-NEXT: call void @_ZN7Elision3fooEv()
|
2018-10-15 23:43:00 +08:00
|
|
|
// CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[I]])
|
2010-09-15 18:14:12 +08:00
|
|
|
A i = (foo(), A());
|
|
|
|
|
|
|
|
// CHECK-NEXT: call void @_ZN7Elision4fooAEv([[A]]* sret [[T0]])
|
2018-10-15 23:43:00 +08:00
|
|
|
// CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[J]])
|
2010-09-15 18:14:12 +08:00
|
|
|
// CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[T0]])
|
|
|
|
A j = (fooA(), A());
|
|
|
|
|
2018-10-15 23:43:00 +08:00
|
|
|
// CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[T1]])
|
2010-09-15 18:14:12 +08:00
|
|
|
// CHECK-NEXT: call void @_ZN7Elision4fooAEv([[A]]* sret [[K]])
|
|
|
|
// CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[T1]])
|
|
|
|
A k = (A(), fooA());
|
|
|
|
|
|
|
|
// CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[K]])
|
|
|
|
// CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[J]])
|
|
|
|
// CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[I]])
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-08-15 14:47:53 +08:00
|
|
|
// CHECK-LABEL: define void @_ZN7Elision5test1EbNS_1AE(
|
2010-09-15 18:14:12 +08:00
|
|
|
void test1(bool c, A x) {
|
2010-09-15 18:38:11 +08:00
|
|
|
// CHECK: [[I:%.*]] = alloca [[A]], align 8
|
|
|
|
// CHECK-NEXT: [[J:%.*]] = alloca [[A]], align 8
|
2010-09-15 18:14:12 +08:00
|
|
|
|
2018-10-15 23:43:00 +08:00
|
|
|
// CHECK: call void @_ZN7Elision1AC1Ev([[A]]* [[I]])
|
|
|
|
// CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[I]], [[A]]* dereferenceable({{[0-9]+}}) [[X:%.*]])
|
2010-09-15 18:14:12 +08:00
|
|
|
A i = (c ? A() : x);
|
|
|
|
|
2018-10-15 23:43:00 +08:00
|
|
|
// CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[J]], [[A]]* dereferenceable({{[0-9]+}}) [[X]])
|
|
|
|
// CHECK: call void @_ZN7Elision1AC1Ev([[A]]* [[J]])
|
2010-09-15 18:14:12 +08:00
|
|
|
A j = (c ? x : A());
|
|
|
|
|
|
|
|
// CHECK: call void @_ZN7Elision1AD1Ev([[A]]* [[J]])
|
|
|
|
// CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[I]])
|
|
|
|
}
|
|
|
|
|
2013-02-01 07:17:12 +08:00
|
|
|
// CHECK: define void @_ZN7Elision5test2Ev([[A]]* noalias sret
|
2010-09-15 18:14:12 +08:00
|
|
|
A test2() {
|
|
|
|
// CHECK: call void @_ZN7Elision3fooEv()
|
2018-10-15 23:43:00 +08:00
|
|
|
// CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[RET:%.*]])
|
2010-09-15 18:14:12 +08:00
|
|
|
// CHECK-NEXT: ret void
|
|
|
|
return (foo(), A());
|
|
|
|
}
|
|
|
|
|
2013-02-01 07:17:12 +08:00
|
|
|
// CHECK: define void @_ZN7Elision5test3EiNS_1AE([[A]]* noalias sret
|
2010-09-15 18:14:12 +08:00
|
|
|
A test3(int v, A x) {
|
|
|
|
if (v < 5)
|
2018-10-15 23:43:00 +08:00
|
|
|
// CHECK: call void @_ZN7Elision1AC1Ev([[A]]* [[RET:%.*]])
|
|
|
|
// CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[RET]], [[A]]* dereferenceable({{[0-9]+}}) [[X:%.*]])
|
2010-09-15 18:14:12 +08:00
|
|
|
return (v < 0 ? A() : x);
|
|
|
|
else
|
2018-10-15 23:43:00 +08:00
|
|
|
// CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[RET]], [[A]]* dereferenceable({{[0-9]+}}) [[X]])
|
|
|
|
// CHECK: call void @_ZN7Elision1AC1Ev([[A]]* [[RET]])
|
2010-09-15 18:14:12 +08:00
|
|
|
return (v > 10 ? x : A());
|
|
|
|
|
|
|
|
// CHECK: ret void
|
|
|
|
}
|
|
|
|
|
2013-08-15 14:47:53 +08:00
|
|
|
// CHECK-LABEL: define void @_ZN7Elision5test4Ev()
|
2010-09-15 18:14:12 +08:00
|
|
|
void test4() {
|
|
|
|
// CHECK: [[X:%.*]] = alloca [[A]], align 8
|
|
|
|
// CHECK-NEXT: [[XS:%.*]] = alloca [2 x [[A]]], align 16
|
|
|
|
|
2018-10-15 23:43:00 +08:00
|
|
|
// CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[X]])
|
2010-09-15 18:14:12 +08:00
|
|
|
A x;
|
|
|
|
|
2015-02-28 03:18:17 +08:00
|
|
|
// CHECK-NEXT: [[XS0:%.*]] = getelementptr inbounds [2 x [[A]]], [2 x [[A]]]* [[XS]], i64 0, i64 0
|
2018-10-15 23:43:00 +08:00
|
|
|
// CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[XS0]])
|
2015-02-28 03:18:17 +08:00
|
|
|
// CHECK-NEXT: [[XS1:%.*]] = getelementptr inbounds [[A]], [[A]]* [[XS0]], i64 1
|
2018-10-15 23:43:00 +08:00
|
|
|
// CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[XS1]], [[A]]* dereferenceable({{[0-9]+}}) [[X]])
|
2010-09-15 18:14:12 +08:00
|
|
|
A xs[] = { A(), x };
|
|
|
|
|
2015-02-28 03:18:17 +08:00
|
|
|
// CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [2 x [[A]]], [2 x [[A]]]* [[XS]], i32 0, i32 0
|
|
|
|
// CHECK-NEXT: [[END:%.*]] = getelementptr inbounds [[A]], [[A]]* [[BEGIN]], i64 2
|
2010-09-15 18:14:12 +08:00
|
|
|
// CHECK-NEXT: br label
|
2011-07-09 09:37:26 +08:00
|
|
|
// CHECK: [[AFTER:%.*]] = phi [[A]]*
|
2015-02-28 03:18:17 +08:00
|
|
|
// CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds [[A]], [[A]]* [[AFTER]], i64 -1
|
2011-07-09 09:37:26 +08:00
|
|
|
// CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[CUR]])
|
|
|
|
// CHECK-NEXT: [[T0:%.*]] = icmp eq [[A]]* [[CUR]], [[BEGIN]]
|
|
|
|
// CHECK-NEXT: br i1 [[T0]],
|
2010-09-15 18:14:12 +08:00
|
|
|
|
|
|
|
// CHECK: call void @_ZN7Elision1AD1Ev([[A]]* [[X]])
|
|
|
|
}
|
2010-09-16 14:57:56 +08:00
|
|
|
|
|
|
|
// rdar://problem/8433352
|
2013-02-01 07:17:12 +08:00
|
|
|
// CHECK: define void @_ZN7Elision5test5Ev([[A]]* noalias sret
|
2010-09-16 14:57:56 +08:00
|
|
|
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
|
|
|
|
|
2018-10-15 23:43:00 +08:00
|
|
|
// CHECK: call void @_ZN7Elision1BC1Ev([[B]]* [[BT0]])
|
2015-02-28 03:18:17 +08:00
|
|
|
// CHECK-NEXT: [[AM:%.*]] = getelementptr inbounds [[B]], [[B]]* [[BT0]], i32 0, i32 0
|
2018-10-15 23:43:00 +08:00
|
|
|
// CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[AT0]], [[A]]* dereferenceable({{[0-9]+}}) [[AM]])
|
2010-09-16 14:57:56 +08:00
|
|
|
// CHECK-NEXT: call void @_ZN7Elision5takeAENS_1AE([[A]]* [[AT0]])
|
|
|
|
// CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[AT0]])
|
|
|
|
// CHECK-NEXT: call void @_ZN7Elision1BD1Ev([[B]]* [[BT0]])
|
|
|
|
takeA(B().a);
|
|
|
|
|
2018-10-15 23:43:00 +08:00
|
|
|
// CHECK-NEXT: call void @_ZN7Elision1BC1Ev([[B]]* [[BT1]])
|
2015-02-28 03:18:17 +08:00
|
|
|
// CHECK-NEXT: [[AM:%.*]] = getelementptr inbounds [[B]], [[B]]* [[BT1]], i32 0, i32 0
|
2018-10-15 23:43:00 +08:00
|
|
|
// CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[X]], [[A]]* dereferenceable({{[0-9]+}}) [[AM]])
|
2010-09-16 14:57:56 +08:00
|
|
|
// CHECK-NEXT: call void @_ZN7Elision1BD1Ev([[B]]* [[BT1]])
|
|
|
|
A x = B().a;
|
|
|
|
|
2018-10-15 23:43:00 +08:00
|
|
|
// CHECK-NEXT: call void @_ZN7Elision1BC1Ev([[B]]* [[BT2]])
|
2015-02-28 03:18:17 +08:00
|
|
|
// CHECK-NEXT: [[AM:%.*]] = getelementptr inbounds [[B]], [[B]]* [[BT2]], i32 0, i32 0
|
2018-10-15 23:43:00 +08:00
|
|
|
// CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[RET:%.*]], [[A]]* dereferenceable({{[0-9]+}}) [[AM]])
|
2010-09-16 14:57:56 +08:00
|
|
|
// CHECK-NEXT: call void @_ZN7Elision1BD1Ev([[B]]* [[BT2]])
|
|
|
|
return B().a;
|
|
|
|
|
|
|
|
// CHECK: call void @_ZN7Elision1AD1Ev([[A]]* [[X]])
|
|
|
|
}
|
2010-09-18 08:58:34 +08:00
|
|
|
|
|
|
|
// Reduced from webkit.
|
|
|
|
// CHECK: define void @_ZN7Elision5test6EPKNS_1CE([[C:%.*]]*
|
|
|
|
struct C { operator A() const; };
|
|
|
|
void test6(const C *x) {
|
|
|
|
// CHECK: [[T0:%.*]] = alloca [[A]], align 8
|
2015-02-28 05:19:58 +08:00
|
|
|
// CHECK: [[X:%.*]] = load [[C]]*, [[C]]** {{%.*}}, align 8
|
2010-09-18 08:58:34 +08:00
|
|
|
// CHECK-NEXT: call void @_ZNK7Elision1CcvNS_1AEEv([[A]]* sret [[T0]], [[C]]* [[X]])
|
|
|
|
// CHECK-NEXT: call void @_ZNK7Elision1A3fooEv([[A]]* [[T0]])
|
|
|
|
// CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[T0]])
|
|
|
|
// CHECK-NEXT: ret void
|
|
|
|
A(*x).foo();
|
|
|
|
}
|
2010-09-15 18:14:12 +08:00
|
|
|
}
|
2010-11-17 08:07:33 +08:00
|
|
|
|
|
|
|
namespace PR8623 {
|
|
|
|
struct A { A(int); ~A(); };
|
|
|
|
|
2013-08-15 14:47:53 +08:00
|
|
|
// CHECK-LABEL: define void @_ZN6PR86233fooEb(
|
2010-11-17 08:07:33 +08:00
|
|
|
void foo(bool b) {
|
|
|
|
// CHECK: [[TMP:%.*]] = alloca [[A:%.*]], align 1
|
|
|
|
// CHECK-NEXT: [[LCONS:%.*]] = alloca i1
|
|
|
|
// CHECK-NEXT: [[RCONS:%.*]] = alloca i1
|
2011-01-27 03:15:39 +08:00
|
|
|
// CHECK: store i1 false, i1* [[LCONS]]
|
2010-11-17 08:07:33 +08:00
|
|
|
// CHECK-NEXT: store i1 false, i1* [[RCONS]]
|
2011-01-27 03:15:39 +08:00
|
|
|
// CHECK-NEXT: br i1
|
2018-10-15 23:43:00 +08:00
|
|
|
// CHECK: call void @_ZN6PR86231AC1Ei([[A]]* [[TMP]], i32 2)
|
2010-11-17 08:07:33 +08:00
|
|
|
// CHECK-NEXT: store i1 true, i1* [[LCONS]]
|
|
|
|
// CHECK-NEXT: br label
|
2018-10-15 23:43:00 +08:00
|
|
|
// CHECK: call void @_ZN6PR86231AC1Ei([[A]]* [[TMP]], i32 3)
|
2010-11-17 08:07:33 +08:00
|
|
|
// CHECK-NEXT: store i1 true, i1* [[RCONS]]
|
|
|
|
// CHECK-NEXT: br label
|
2015-02-28 05:19:58 +08:00
|
|
|
// CHECK: load i1, i1* [[RCONS]]
|
2010-11-17 08:07:33 +08:00
|
|
|
// CHECK-NEXT: br i1
|
|
|
|
// CHECK: call void @_ZN6PR86231AD1Ev([[A]]* [[TMP]])
|
|
|
|
// CHECK-NEXT: br label
|
2015-02-28 05:19:58 +08:00
|
|
|
// CHECK: load i1, i1* [[LCONS]]
|
2010-11-17 08:07:33 +08:00
|
|
|
// CHECK-NEXT: br i1
|
|
|
|
// CHECK: call void @_ZN6PR86231AD1Ev([[A]]* [[TMP]])
|
|
|
|
// CHECK-NEXT: br label
|
|
|
|
// CHECK: ret void
|
|
|
|
b ? A(2) : A(3);
|
|
|
|
}
|
|
|
|
}
|
2011-11-28 06:09:28 +08:00
|
|
|
|
|
|
|
namespace PR11365 {
|
|
|
|
struct A { A(); ~A(); };
|
|
|
|
|
2013-08-15 14:47:53 +08:00
|
|
|
// CHECK-LABEL: define void @_ZN7PR113653fooEv(
|
2011-11-28 06:09:28 +08:00
|
|
|
void foo() {
|
2015-02-28 03:18:17 +08:00
|
|
|
// CHECK: [[BEGIN:%.*]] = getelementptr inbounds [3 x [[A:%.*]]], [3 x [[A:%.*]]]* {{.*}}, i32 0, i32 0
|
|
|
|
// CHECK-NEXT: [[END:%.*]] = getelementptr inbounds [[A]], [[A]]* [[BEGIN]], i64 3
|
2011-11-28 06:09:28 +08:00
|
|
|
// CHECK-NEXT: br label
|
|
|
|
|
|
|
|
// CHECK: [[PHI:%.*]] = phi
|
2015-02-28 03:18:17 +08:00
|
|
|
// CHECK-NEXT: [[ELEM:%.*]] = getelementptr inbounds [[A]], [[A]]* [[PHI]], i64 -1
|
2011-11-28 06:09:28 +08:00
|
|
|
// CHECK-NEXT: call void @_ZN7PR113651AD1Ev([[A]]* [[ELEM]])
|
|
|
|
// CHECK-NEXT: icmp eq [[A]]* [[ELEM]], [[BEGIN]]
|
|
|
|
// CHECK-NEXT: br i1
|
|
|
|
(void) (A [3]) {};
|
|
|
|
}
|
|
|
|
}
|
2012-11-13 08:54:12 +08:00
|
|
|
|
|
|
|
namespace AssignmentOp {
|
|
|
|
struct A { ~A(); };
|
|
|
|
struct B { A operator=(const B&); };
|
|
|
|
struct C : B { B b1, b2; };
|
2013-08-15 14:47:53 +08:00
|
|
|
// CHECK-LABEL: define void @_ZN12AssignmentOp1fE
|
2012-11-13 08:54:12 +08:00
|
|
|
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(
|
|
|
|
}
|
2013-06-03 08:17:11 +08:00
|
|
|
|
|
|
|
namespace BindToSubobject {
|
|
|
|
struct A {
|
|
|
|
A();
|
|
|
|
~A();
|
|
|
|
int a;
|
|
|
|
};
|
|
|
|
|
|
|
|
void f(), g();
|
|
|
|
|
2014-05-07 06:49:16 +08:00
|
|
|
// CHECK: call void @_ZN15BindToSubobject1AC1Ev({{.*}} @_ZGRN15BindToSubobject1aE_)
|
|
|
|
// CHECK: call i32 @__cxa_atexit({{.*}} bitcast ({{.*}} @_ZN15BindToSubobject1AD1Ev to void (i8*)*), i8* bitcast ({{.*}} @_ZGRN15BindToSubobject1aE_ to i8*), i8* @__dso_handle)
|
|
|
|
// CHECK: store i32* getelementptr inbounds ({{.*}} @_ZGRN15BindToSubobject1aE_, i32 0, i32 0), i32** @_ZN15BindToSubobject1aE, align 8
|
2013-06-03 08:17:11 +08:00
|
|
|
int &&a = A().a;
|
|
|
|
|
|
|
|
// CHECK: call void @_ZN15BindToSubobject1fEv()
|
2014-05-07 06:49:16 +08:00
|
|
|
// CHECK: call void @_ZN15BindToSubobject1AC1Ev({{.*}} @_ZGRN15BindToSubobject1bE_)
|
|
|
|
// CHECK: call i32 @__cxa_atexit({{.*}} bitcast ({{.*}} @_ZN15BindToSubobject1AD1Ev to void (i8*)*), i8* bitcast ({{.*}} @_ZGRN15BindToSubobject1bE_ to i8*), i8* @__dso_handle)
|
|
|
|
// CHECK: store i32* getelementptr inbounds ({{.*}} @_ZGRN15BindToSubobject1bE_, i32 0, i32 0), i32** @_ZN15BindToSubobject1bE, align 8
|
2013-06-03 08:17:11 +08:00
|
|
|
int &&b = (f(), A().a);
|
|
|
|
|
|
|
|
int A::*h();
|
|
|
|
|
|
|
|
// CHECK: call void @_ZN15BindToSubobject1fEv()
|
|
|
|
// CHECK: call void @_ZN15BindToSubobject1gEv()
|
2014-05-07 06:49:16 +08:00
|
|
|
// CHECK: call void @_ZN15BindToSubobject1AC1Ev({{.*}} @_ZGRN15BindToSubobject1cE_)
|
|
|
|
// CHECK: call i32 @__cxa_atexit({{.*}} bitcast ({{.*}} @_ZN15BindToSubobject1AD1Ev to void (i8*)*), i8* bitcast ({{.*}} @_ZGRN15BindToSubobject1cE_ to i8*), i8* @__dso_handle)
|
2013-06-03 08:17:11 +08:00
|
|
|
// CHECK: call {{.*}} @_ZN15BindToSubobject1hE
|
|
|
|
// CHECK: getelementptr
|
|
|
|
// CHECK: store i32* {{.*}}, i32** @_ZN15BindToSubobject1cE, align 8
|
|
|
|
int &&c = (f(), (g(), A().*h()));
|
|
|
|
|
|
|
|
struct B {
|
|
|
|
int padding;
|
|
|
|
A a;
|
|
|
|
};
|
|
|
|
|
2014-05-07 06:49:16 +08:00
|
|
|
// CHECK: call void @_ZN15BindToSubobject1BC1Ev({{.*}} @_ZGRN15BindToSubobject1dE_)
|
|
|
|
// CHECK: call i32 @__cxa_atexit({{.*}} bitcast ({{.*}} @_ZN15BindToSubobject1BD1Ev to void (i8*)*), i8* bitcast ({{.*}} @_ZGRN15BindToSubobject1dE_ to i8*), i8* @__dso_handle)
|
2013-06-03 08:17:11 +08:00
|
|
|
// CHECK: call {{.*}} @_ZN15BindToSubobject1hE
|
|
|
|
// CHECK: getelementptr {{.*}} getelementptr
|
|
|
|
// CHECK: store i32* {{.*}}, i32** @_ZN15BindToSubobject1dE, align 8
|
|
|
|
int &&d = (B().a).*h();
|
|
|
|
}
|
2013-06-03 15:13:35 +08:00
|
|
|
|
|
|
|
namespace Bitfield {
|
|
|
|
struct S { int a : 5; ~S(); };
|
|
|
|
|
|
|
|
// Do not lifetime extend the S() temporary here.
|
2013-06-04 01:00:25 +08:00
|
|
|
// CHECK: alloca
|
|
|
|
// CHECK: call {{.*}}memset
|
2014-05-07 06:49:16 +08:00
|
|
|
// CHECK: store i32 {{.*}}, i32* @_ZGRN8Bitfield1rE_
|
2013-06-03 15:13:35 +08:00
|
|
|
// CHECK: call void @_ZN8Bitfield1SD1
|
2014-05-07 06:49:16 +08:00
|
|
|
// CHECK: store i32* @_ZGRN8Bitfield1rE_, i32** @_ZN8Bitfield1rE, align 8
|
2013-06-03 15:13:35 +08:00
|
|
|
int &&r = S().a;
|
|
|
|
}
|
2013-06-04 12:45:03 +08:00
|
|
|
|
|
|
|
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
|
2014-05-07 06:49:16 +08:00
|
|
|
// CHECK: store i32 {{.*}}, i32* @_ZGRN6Vector1rE_
|
|
|
|
// CHECK: store i32* @_ZGRN6Vector1rE_, i32** @_ZN6Vector1rE,
|
2013-06-04 12:45:03 +08:00
|
|
|
int &&r = S().v[1];
|
|
|
|
|
|
|
|
// CHECK: alloca
|
|
|
|
// CHECK: extractelement
|
2014-05-07 06:49:16 +08:00
|
|
|
// CHECK: store i32 {{.*}}, i32* @_ZGRN6Vector1sE_
|
|
|
|
// CHECK: store i32* @_ZGRN6Vector1sE_, i32** @_ZN6Vector1sE,
|
2013-06-04 12:45:03 +08:00
|
|
|
int &&s = S().w[1];
|
|
|
|
// FIXME PR16204: The following code leads to an assertion in Sema.
|
|
|
|
//int &&s = S().w.y;
|
|
|
|
}
|
2013-06-13 04:42:33 +08:00
|
|
|
|
|
|
|
namespace ImplicitTemporaryCleanup {
|
|
|
|
struct A { A(int); ~A(); };
|
|
|
|
void g();
|
|
|
|
|
2013-08-15 14:47:53 +08:00
|
|
|
// CHECK-LABEL: define void @_ZN24ImplicitTemporaryCleanup1fEv(
|
2013-06-13 04:42:33 +08:00
|
|
|
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]], {{.*}} getelementptr inbounds ({{.*}} @[[TEMPE:_ZGRN17MultipleExtension2e1E.*]], i32 0, i32 0)
|
|
|
|
|
|
|
|
// 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]], %"struct.MultipleExtension::E"** @_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]], {{.*}} getelementptr inbounds ({{.*}} @[[E:_ZN17MultipleExtension2e2E]], i32 0, i32 0)
|
|
|
|
|
|
|
|
// 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]], {{.*}}* %[[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]])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-05 15:49:14 +08:00
|
|
|
namespace ArrayAccess {
|
|
|
|
struct A { A(int); ~A(); };
|
|
|
|
void g();
|
|
|
|
void f() {
|
|
|
|
using T = A[3];
|
|
|
|
|
|
|
|
// CHECK: call void @_ZN11ArrayAccess1AC1Ei({{.*}}, i32 1
|
|
|
|
// CHECK-NOT: @_ZN11ArrayAccess1AD
|
|
|
|
// CHECK: call void @_ZN11ArrayAccess1AC1Ei({{.*}}, i32 2
|
|
|
|
// CHECK-NOT: @_ZN11ArrayAccess1AD
|
|
|
|
// CHECK: call void @_ZN11ArrayAccess1AC1Ei({{.*}}, i32 3
|
|
|
|
// CHECK-NOT: @_ZN11ArrayAccess1AD
|
|
|
|
A &&a = T{1, 2, 3}[1];
|
|
|
|
|
|
|
|
// CHECK: call void @_ZN11ArrayAccess1AC1Ei({{.*}}, i32 4
|
|
|
|
// CHECK-NOT: @_ZN11ArrayAccess1AD
|
|
|
|
// CHECK: call void @_ZN11ArrayAccess1AC1Ei({{.*}}, i32 5
|
|
|
|
// CHECK-NOT: @_ZN11ArrayAccess1AD
|
|
|
|
// CHECK: call void @_ZN11ArrayAccess1AC1Ei({{.*}}, i32 6
|
|
|
|
// CHECK-NOT: @_ZN11ArrayAccess1AD
|
|
|
|
A &&b = 2[T{4, 5, 6}];
|
|
|
|
|
|
|
|
// CHECK: call void @_ZN11ArrayAccess1gEv(
|
|
|
|
g();
|
|
|
|
|
|
|
|
// CHECK: call void @_ZN11ArrayAccess1AD
|
|
|
|
// CHECK: call void @_ZN11ArrayAccess1AD
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-04 12:04:20 +08:00
|
|
|
namespace PR14130 {
|
|
|
|
struct S { S(int); };
|
|
|
|
struct U { S &&s; };
|
|
|
|
U v { { 0 } };
|
2014-05-07 06:49:16 +08:00
|
|
|
// CHECK: call void @_ZN7PR141301SC1Ei({{.*}} @_ZGRN7PR141301vE_, i32 0)
|
|
|
|
// CHECK: store {{.*}} @_ZGRN7PR141301vE_, {{.*}} @_ZN7PR141301vE
|
2013-07-04 12:04:20 +08:00
|
|
|
}
|
2018-07-24 06:56:45 +08:00
|
|
|
|
|
|
|
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, i1* %[[CLEANUP_B:.*]],
|
|
|
|
// CHECK: store i1 false, i1* %[[CLEANUP_C:.*]],
|
|
|
|
// CHECK: br i1
|
|
|
|
//
|
|
|
|
// CHECK: call {{.*}} @_ZN11Conditional1BC1Ev(
|
|
|
|
// CHECK: store i1 true, i1* %[[CLEANUP_B]],
|
|
|
|
// CHECK: br label
|
|
|
|
//
|
|
|
|
// CHECK: call {{.*}} @_ZN11Conditional1CC1Ev(
|
|
|
|
// CHECK: store i1 true, i1* %[[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, i1* %[[CLEANUP_B:.*]],
|
|
|
|
// CHECK: store i1 false, i1* %[[CLEANUP_C:.*]],
|
|
|
|
// CHECK: br i1
|
|
|
|
//
|
|
|
|
// CHECK: call {{.*}} @_ZN11Conditional1BC1Ev(
|
|
|
|
// CHECK: store i1 true, i1* %[[CLEANUP_B]],
|
|
|
|
// CHECK: br label
|
|
|
|
//
|
|
|
|
// CHECK: call {{.*}} @_ZN11Conditional1CC1Ev(
|
|
|
|
// CHECK: store i1 true, i1* %[[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 {{.*}} @_ZGRN11Conditional1rE_,
|
|
|
|
// CHECK: br label
|
|
|
|
//
|
|
|
|
// CHECK: call {{.*}} @_ZN11Conditional1CC1Ev({{.*}} @_ZGRN11Conditional1rE0_)
|
|
|
|
// CHECK: call {{.*}} @__cxa_atexit({{.*}} @_ZN11Conditional1CD1Ev {{.*}} @_ZGRN11Conditional1rE0_,
|
|
|
|
// CHECK: br label
|
|
|
|
A &&r = b ? static_cast<A&&>(B()) : static_cast<A&&>(C());
|
|
|
|
}
|