[AST][RecoveryExpr] Build recovery expressions by default for C++.
Reland https://reviews.llvm.org/D76696
All known crashes have been fixed, another attemption.
We have rolled out this to all internal users for a while, didn't see
big issues, we consider it is stable enough.
Reviewed By: sammccall
Subscribers: rsmith, hubert.reinterpretcast, ebevhan, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D78350
2020-04-23 17:14:01 +08:00
|
|
|
// RUN: %clang_cc1 -std=c++1z -verify -Wno-unused %s
|
2016-12-07 07:52:28 +08:00
|
|
|
|
|
|
|
struct Noncopyable {
|
|
|
|
Noncopyable();
|
2017-09-27 02:37:55 +08:00
|
|
|
Noncopyable(const Noncopyable &) = delete; // expected-note 1+{{deleted}} expected-note 1+ {{not viable}}
|
2016-12-07 07:52:28 +08:00
|
|
|
virtual ~Noncopyable();
|
|
|
|
};
|
|
|
|
struct Derived : Noncopyable {};
|
2017-09-27 02:37:55 +08:00
|
|
|
struct NoncopyableAggr { // expected-note 3{{candidate}}
|
2016-12-07 07:52:28 +08:00
|
|
|
Noncopyable nc;
|
|
|
|
};
|
|
|
|
struct Indestructible {
|
|
|
|
Indestructible();
|
|
|
|
~Indestructible() = delete; // expected-note 1+{{deleted}}
|
|
|
|
};
|
|
|
|
struct Incomplete; // expected-note 1+{{declar}}
|
|
|
|
|
|
|
|
Noncopyable make(int kind = 0) {
|
|
|
|
switch (kind) {
|
|
|
|
case 0: return {};
|
|
|
|
case 1: return Noncopyable();
|
|
|
|
case 2: return Noncopyable{};
|
|
|
|
case 3: return make();
|
|
|
|
}
|
|
|
|
__builtin_unreachable();
|
|
|
|
}
|
|
|
|
|
|
|
|
Indestructible make_indestructible();
|
|
|
|
Incomplete make_incomplete(); // expected-note 1+{{here}}
|
|
|
|
|
|
|
|
void take(Noncopyable nc) {}
|
|
|
|
|
|
|
|
Noncopyable nrvo() {
|
|
|
|
Noncopyable nrvo;
|
|
|
|
return nrvo; // expected-error {{deleted constructor}}
|
|
|
|
}
|
|
|
|
|
|
|
|
Noncopyable nc1 = make();
|
|
|
|
Noncopyable nc2 = Noncopyable();
|
|
|
|
Noncopyable nc3 = Derived(); // expected-error {{deleted constructor}}
|
2017-09-27 02:37:55 +08:00
|
|
|
Noncopyable nc4((Noncopyable()));
|
|
|
|
Noncopyable nc5 = {Noncopyable()};
|
|
|
|
Noncopyable nc6{Noncopyable()};
|
2016-12-07 07:52:28 +08:00
|
|
|
|
|
|
|
NoncopyableAggr nca1 = NoncopyableAggr{};
|
|
|
|
NoncopyableAggr nca2 = NoncopyableAggr{{}};
|
|
|
|
NoncopyableAggr nca3 = NoncopyableAggr{NoncopyableAggr{Noncopyable()}};
|
|
|
|
|
2017-09-27 02:37:55 +08:00
|
|
|
template<typename T> struct Convert { operator T(); }; // expected-note 1+{{candidate}}
|
|
|
|
Noncopyable conv1 = Convert<Noncopyable>();
|
|
|
|
Noncopyable conv2((Convert<Noncopyable>()));
|
|
|
|
Noncopyable conv3 = {Convert<Noncopyable>()};
|
|
|
|
Noncopyable conv4{Convert<Noncopyable>()};
|
|
|
|
|
|
|
|
Noncopyable ref_conv1 = Convert<Noncopyable&>(); // expected-error {{deleted constructor}}
|
|
|
|
Noncopyable ref_conv2((Convert<Noncopyable&>())); // expected-error {{deleted constructor}}
|
|
|
|
Noncopyable ref_conv3 = {Convert<Noncopyable&>()}; // expected-error {{deleted constructor}}
|
|
|
|
Noncopyable ref_conv4{Convert<Noncopyable&>()}; // expected-error {{deleted constructor}}
|
|
|
|
|
|
|
|
Noncopyable derived_conv1 = Convert<Derived>(); // expected-error {{deleted constructor}}
|
|
|
|
Noncopyable derived_conv2((Convert<Derived>())); // expected-error {{deleted constructor}}
|
|
|
|
Noncopyable derived_conv3 = {Convert<Derived>()}; // expected-error {{deleted constructor}}
|
|
|
|
Noncopyable derived_conv4{Convert<Derived>()}; // expected-error {{deleted constructor}}
|
|
|
|
|
|
|
|
NoncopyableAggr nc_aggr1 = Convert<NoncopyableAggr>();
|
|
|
|
NoncopyableAggr nc_aggr2((Convert<NoncopyableAggr>()));
|
|
|
|
NoncopyableAggr nc_aggr3 = {Convert<NoncopyableAggr>()}; // expected-error {{no viable conversion}}
|
|
|
|
NoncopyableAggr nc_aggr4{Convert<NoncopyableAggr>()}; // expected-error {{no viable conversion}}
|
|
|
|
NoncopyableAggr nc_aggr5 = Convert<Noncopyable>(); // expected-error {{no viable}}
|
|
|
|
NoncopyableAggr nc_aggr6((Convert<Noncopyable>())); // expected-error {{no matching constructor}}
|
|
|
|
NoncopyableAggr nc_aggr7 = {Convert<Noncopyable>()};
|
|
|
|
NoncopyableAggr nc_aggr8{Convert<Noncopyable>()};
|
|
|
|
|
2016-12-07 07:52:28 +08:00
|
|
|
void test_expressions(bool b) {
|
|
|
|
auto lambda = [a = make()] {};
|
|
|
|
|
|
|
|
take({});
|
|
|
|
take(Noncopyable());
|
|
|
|
take(Noncopyable{});
|
|
|
|
take(make());
|
|
|
|
|
|
|
|
Noncopyable &&dc1 = dynamic_cast<Noncopyable&&>(Noncopyable());
|
|
|
|
Noncopyable &&dc2 = dynamic_cast<Noncopyable&&>(nc1);
|
|
|
|
Noncopyable &&dc3 = dynamic_cast<Noncopyable&&>(Derived());
|
|
|
|
|
|
|
|
Noncopyable sc1 = static_cast<Noncopyable>(Noncopyable());
|
|
|
|
Noncopyable sc2 = static_cast<Noncopyable>(nc1); // expected-error {{deleted}}
|
|
|
|
Noncopyable sc3 = static_cast<Noncopyable&&>(Noncopyable()); // expected-error {{deleted}}
|
|
|
|
Noncopyable sc4 = static_cast<Noncopyable>(static_cast<Noncopyable&&>(Noncopyable())); // expected-error {{deleted}}
|
|
|
|
|
|
|
|
Noncopyable cc1 = (Noncopyable)Noncopyable();
|
|
|
|
Noncopyable cc2 = (Noncopyable)Derived(); // expected-error {{deleted}}
|
|
|
|
|
|
|
|
Noncopyable fc1 = Noncopyable(Noncopyable());
|
|
|
|
Noncopyable fc2 = Noncopyable(Derived()); // expected-error {{deleted}}
|
|
|
|
|
|
|
|
// We must check for a complete type for every materialized temporary. (Note
|
|
|
|
// that in the special case of the top level of a decltype, no temporary is
|
|
|
|
// materialized.)
|
|
|
|
make_incomplete(); // expected-error {{incomplete}}
|
|
|
|
make_incomplete().a; // expected-error {{incomplete}}
|
|
|
|
make_incomplete().*(int Incomplete::*)nullptr; // expected-error {{incomplete}}
|
|
|
|
dynamic_cast<Incomplete&&>(make_incomplete()); // expected-error {{incomplete}}
|
|
|
|
const_cast<Incomplete&&>(make_incomplete()); // expected-error {{incomplete}}
|
|
|
|
|
|
|
|
sizeof(Indestructible{}); // expected-error {{deleted}}
|
|
|
|
sizeof(make_indestructible()); // expected-error {{deleted}}
|
|
|
|
sizeof(make_incomplete()); // expected-error {{incomplete}}
|
2020-07-20 19:11:15 +08:00
|
|
|
typeid(Indestructible{}); // expected-error {{deleted}} expected-error {{you need to include <typeinfo>}}
|
[AST][RecoveryExpr] Build recovery expressions by default for C++.
Reland https://reviews.llvm.org/D76696
All known crashes have been fixed, another attemption.
We have rolled out this to all internal users for a while, didn't see
big issues, we consider it is stable enough.
Reviewed By: sammccall
Subscribers: rsmith, hubert.reinterpretcast, ebevhan, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D78350
2020-04-23 17:14:01 +08:00
|
|
|
typeid(make_indestructible()); // expected-error {{deleted}} \
|
|
|
|
// expected-error {{need to include <typeinfo>}}
|
|
|
|
typeid(make_incomplete()); // expected-error {{incomplete}} \
|
|
|
|
// expected-error {{need to include <typeinfo>}}
|
2016-12-07 07:52:28 +08:00
|
|
|
|
|
|
|
// FIXME: The first two cases here are now also valid in C++17 onwards.
|
|
|
|
using I = decltype(Indestructible()); // expected-error {{deleted}}
|
|
|
|
using I = decltype(Indestructible{}); // expected-error {{deleted}}
|
|
|
|
using I = decltype(make_indestructible());
|
|
|
|
using J = decltype(make_incomplete());
|
|
|
|
|
|
|
|
Noncopyable cond1 = b ? Noncopyable() : make();
|
|
|
|
Noncopyable cond2 = b ? Noncopyable() : Derived(); // expected-error {{incompatible}}
|
|
|
|
Noncopyable cond3 = b ? Derived() : Noncopyable(); // expected-error {{incompatible}}
|
|
|
|
Noncopyable cond4 = b ? Noncopyable() : nc1; // expected-error {{deleted}}
|
|
|
|
Noncopyable cond5 = b ? nc1 : Noncopyable(); // expected-error {{deleted}}
|
|
|
|
// Could convert both to an xvalue of type Noncopyable here, but we're not
|
|
|
|
// permitted to consider that.
|
|
|
|
Noncopyable &&cond6 = b ? Noncopyable() : Derived(); // expected-error {{incompatible}}
|
|
|
|
Noncopyable &&cond7 = b ? Derived() : Noncopyable(); // expected-error {{incompatible}}
|
|
|
|
// Could convert both to a const lvalue of type Noncopyable here, but we're
|
|
|
|
// not permitted to consider that, either.
|
|
|
|
const Noncopyable cnc;
|
|
|
|
const Noncopyable &cond8 = b ? cnc : Derived(); // expected-error {{incompatible}}
|
|
|
|
const Noncopyable &cond9 = b ? Derived() : cnc; // expected-error {{incompatible}}
|
|
|
|
|
|
|
|
extern const volatile Noncopyable make_cv();
|
|
|
|
Noncopyable cv_difference1 = make_cv();
|
|
|
|
const volatile Noncopyable cv_difference2 = make();
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T> struct ConversionFunction { operator T(); };
|
|
|
|
Noncopyable cf1 = ConversionFunction<Noncopyable>();
|
|
|
|
Noncopyable cf2 = ConversionFunction<Noncopyable&&>(); // expected-error {{deleted}}
|
|
|
|
Noncopyable cf3 = ConversionFunction<const volatile Noncopyable>();
|
|
|
|
const volatile Noncopyable cf4 = ConversionFunction<Noncopyable>();
|
|
|
|
Noncopyable cf5 = ConversionFunction<Derived>(); // expected-error {{deleted}}
|
|
|
|
|
|
|
|
struct AsMember {
|
|
|
|
Noncopyable member;
|
|
|
|
AsMember() : member(make()) {}
|
|
|
|
};
|
|
|
|
// FIXME: DR (no number yet): we still get a copy for base or delegating construction.
|
|
|
|
struct AsBase : Noncopyable {
|
|
|
|
AsBase() : Noncopyable(make()) {} // expected-error {{deleted}}
|
|
|
|
};
|
|
|
|
struct AsDelegating final {
|
2016-12-07 08:24:40 +08:00
|
|
|
AsDelegating(const AsDelegating &) = delete; // expected-note {{deleted}}
|
2016-12-07 07:52:28 +08:00
|
|
|
static AsDelegating make(int);
|
|
|
|
|
|
|
|
// The base constructor version of this is problematic; the complete object
|
|
|
|
// version would be OK. Perhaps we could allow copy omission here for final
|
|
|
|
// classes?
|
|
|
|
AsDelegating(int n) : AsDelegating(make(n)) {} // expected-error {{deleted}}
|
|
|
|
};
|
2017-11-01 09:37:11 +08:00
|
|
|
|
|
|
|
namespace CtorTemplateBeatsNonTemplateConversionFn {
|
|
|
|
struct Foo { template <typename Derived> Foo(const Derived &); };
|
|
|
|
template <typename Derived> struct Base { operator Foo() const = delete; }; // expected-note {{deleted}}
|
|
|
|
struct Derived : Base<Derived> {};
|
|
|
|
|
|
|
|
Foo f(Derived d) { return d; } // expected-error {{invokes a deleted function}}
|
|
|
|
Foo g(Derived d) { return Foo(d); } // ok, calls constructor
|
|
|
|
}
|