reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
// RUN: %clang_cc1 -std=c++1z -verify %s

struct Noncopyable {
  Noncopyable();
  Noncopyable(const Noncopyable &) = delete; // expected-note 1+{{deleted}} expected-note 1+ {{not viable}}
  virtual ~Noncopyable();
};
struct Derived : Noncopyable {};
struct NoncopyableAggr { // expected-note 3{{candidate}}
  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}}
Noncopyable nc4((Noncopyable()));
Noncopyable nc5 = {Noncopyable()};
Noncopyable nc6{Noncopyable()};

NoncopyableAggr nca1 = NoncopyableAggr{};
NoncopyableAggr nca2 = NoncopyableAggr{{}};
NoncopyableAggr nca3 = NoncopyableAggr{NoncopyableAggr{Noncopyable()}};

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>()};

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}}
  typeid(Indestructible{}); // expected-error {{deleted}}
  typeid(make_indestructible()); // expected-error {{deleted}}
  typeid(make_incomplete()); // expected-error {{incomplete}}

  // 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 {
  AsDelegating(const AsDelegating &) = delete; // expected-note {{deleted}}
  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}}
};

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
}