
copy-initialization. We previously got this wrong in a couple of ways: - we only looked for copy / move constructors and constructor templates for this copy, and thus would fail to copy in cases where doing so should use some other constructor (but see core issue 670), - we mishandled the special case for disabling user-defined conversions that blocks infinite recursion through repeated application of a copy constructor (applying it in slightly too many cases) -- though as far as I can tell, this does not ever actually affect the result of overload resolution, and - we misapplied the special-case rules for constructors taking a parameter whose type is a (reference to) the same class type by incorrectly assuming that only happens for copy/move constructors (it also happens for constructors instantiated from templates and those inherited from base classes). These changes should only affect strange corner cases (for instance, where the copy constructor exists but has a non-const-qualified parameter type), so for the most part it only causes us to produce more 'candidate' notes, but see the test changes for other cases whose behavior is affected. llvm-svn: 280776
97 lines
2.4 KiB
C++
97 lines
2.4 KiB
C++
// RUN: %clang_cc1 -triple armv7-none-eabi -emit-llvm -o - %s | FileCheck %s
|
|
|
|
struct A { int x; A(int); ~A(); };
|
|
A f() { return A(0); }
|
|
// CHECK-LABEL: define void @_Z1fv
|
|
// CHECK: call {{.*}} @_ZN1AC1Ei
|
|
// CHECK-NEXT: ret void
|
|
|
|
// Verify that we do not elide copies when constructing a base class.
|
|
namespace no_elide_base {
|
|
struct Base {
|
|
Base(const Base&);
|
|
~Base();
|
|
};
|
|
|
|
struct Other {
|
|
operator Base() const;
|
|
};
|
|
|
|
struct Derived : public virtual Base {
|
|
Derived(const Other &O);
|
|
};
|
|
|
|
// CHECK: define {{.*}} @_ZN13no_elide_base7DerivedC1ERKNS_5OtherE(%"struct.no_elide_base::Derived"* returned %this, %"struct.no_elide_base::Other"* dereferenceable({{[0-9]+}}) %O) unnamed_addr
|
|
Derived::Derived(const Other &O)
|
|
// CHECK: call {{.*}} @_ZNK13no_elide_base5OthercvNS_4BaseEEv
|
|
// CHECK: call {{.*}} @_ZN13no_elide_base4BaseC2ERKS0_
|
|
// CHECK: call {{.*}} @_ZN13no_elide_base4BaseD1Ev
|
|
: Base(O)
|
|
{
|
|
// CHECK: ret
|
|
}
|
|
}
|
|
|
|
// PR8683.
|
|
|
|
namespace PR8683 {
|
|
|
|
struct A {
|
|
A();
|
|
A(const A&);
|
|
A& operator=(const A&);
|
|
};
|
|
|
|
struct B {
|
|
A a;
|
|
};
|
|
|
|
void f() {
|
|
// Verify that we don't mark the copy constructor in this expression as elidable.
|
|
// CHECK: call {{.*}} @_ZN6PR86831AC1ERKS0_
|
|
A a = (B().a);
|
|
}
|
|
|
|
}
|
|
|
|
namespace PR12139 {
|
|
struct A {
|
|
A() : value(1) { }
|
|
A(A const &, int value = 2) : value(value) { }
|
|
int value;
|
|
|
|
static A makeA() { A a; a.value = 2; return a; }
|
|
};
|
|
|
|
// CHECK-LABEL: define i32 @_ZN7PR121394testEv
|
|
int test() {
|
|
// CHECK: call void @_ZN7PR121391A5makeAEv
|
|
// CHECK-NEXT: call %"struct.PR12139::A"* @_ZN7PR121391AC1ERKS0_i
|
|
A a(A::makeA(), 3);
|
|
// CHECK-NEXT: getelementptr inbounds
|
|
// CHECK-NEXT: load
|
|
// CHECK-NEXT: ret i32
|
|
return a.value;
|
|
}
|
|
}
|
|
|
|
namespace ElidableCallIsNotCopyCtor {
|
|
struct A { A(const A&); };
|
|
struct B : A {
|
|
B(B&);
|
|
B(A);
|
|
B(int);
|
|
};
|
|
void f() {
|
|
// Here, we construct via B(int) then B(A). The B(A) construction is
|
|
// elidable, but we don't have an AST representation for the case where we
|
|
// must elide not only a constructor call but also some argument
|
|
// conversions, so we don't elide it.
|
|
// CHECK-LABEL: define void @_ZN25ElidableCallIsNotCopyCtor1fEv(
|
|
// CHECK: call {{.*}} @_ZN25ElidableCallIsNotCopyCtor1BC1Ei(
|
|
// CHECK: call {{.*}} @_ZN25ElidableCallIsNotCopyCtor1AC1ERKS0_(
|
|
// CHECK: call {{.*}} @_ZN25ElidableCallIsNotCopyCtor1BC1ENS_1AE(
|
|
B b = 0;
|
|
}
|
|
}
|