PR31606: Generalize our tentative DR resolution for inheriting copy/move
constructors to better match the pre-P0136R1 behavior.

llvm-svn: 291955
diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p15.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p15.cpp
index 74db2b8..0c58da0 100644
--- a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p15.cpp
+++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p15.cpp
@@ -1,16 +1,16 @@
 // RUN: %clang_cc1 -std=c++11 -verify %s
 
-struct B1 { // expected-note 2{{candidate}}
+struct B1 {
   B1(int); // expected-note {{candidate}}
 };
 
-struct B2 { // expected-note 2{{candidate}}
+struct B2 {
   B2(int); // expected-note {{candidate}}
 };
 
 struct D1 : B1, B2 { // expected-note 2{{candidate}}
-  using B1::B1; // expected-note 3{{inherited here}}
-  using B2::B2; // expected-note 3{{inherited here}}
+  using B1::B1; // expected-note {{inherited here}}
+  using B2::B2; // expected-note {{inherited here}}
 };
 D1 d1(0); // expected-error {{ambiguous}}
 
@@ -35,7 +35,7 @@
     operator D&&();
   };
 
-  struct A { // expected-note 4{{candidate}}
+  struct A { // expected-note 2{{candidate}}
     A(); // expected-note {{candidate}}
 
     A(C &&); // expected-note {{candidate}}
@@ -47,7 +47,7 @@
     A(convert_to_D2); // expected-note {{candidate}}
   };
 
-  struct B { // expected-note 4{{candidate}}
+  struct B { // expected-note 2{{candidate}}
     B(); // expected-note {{candidate}}
 
     B(C &&); // expected-note {{candidate}}
@@ -66,9 +66,9 @@
     using B::operator=;
   };
   struct D : A, B {
-    using A::A; // expected-note 5{{inherited here}}
+    using A::A; // expected-note 3{{inherited here}}
     using A::operator=;
-    using B::B; // expected-note 5{{inherited here}}
+    using B::B; // expected-note 3{{inherited here}}
     using B::operator=;
 
     D(int);
@@ -93,13 +93,13 @@
   }
 
   struct Y;
-  struct X { // expected-note 2{{candidate}}
+  struct X {
     X();
-    X(volatile Y &); // expected-note {{constructor inherited from base class cannot be used to initialize from an argument of the derived class type}}
+    X(volatile Y &); // expected-note 3{{inherited constructor cannot be used to copy object}}
   } x;
-  struct Y : X { using X::X; } volatile y; // expected-note 2{{candidate}}
-  struct Z : Y { using Y::Y; } volatile z; // expected-note 3{{candidate}} expected-note 5{{inherited here}}
-  Z z1(x); // ok
-  Z z2(y); // ok, Z is not reference-related to type of y
+  struct Y : X { using X::X; } volatile y;
+  struct Z : Y { using Y::Y; } volatile z; // expected-note 4{{no known conversion}} expected-note 2{{would lose volatile}} expected-note 3{{requires 0}} expected-note 3{{inherited here}}
+  Z z1(x); // expected-error {{no match}}
+  Z z2(y); // expected-error {{no match}}
   Z z3(z); // expected-error {{no match}}
 }
diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1.cpp
index 7a92e7a..f4f73a5 100644
--- a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1.cpp
+++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1.cpp
@@ -134,13 +134,13 @@
 
 struct DefaultedBase {
   int n;
-  DefaultedBase() = default; // expected-note 0+ {{candidate}}
-  DefaultedBase(DefaultedBase const&) = default; // expected-note 0+ {{candidate}}
-  DefaultedBase(DefaultedBase &&) = default; // expected-note 0+ {{candidate}}
+  DefaultedBase() = default;
+  DefaultedBase(DefaultedBase const&) = default;
+  DefaultedBase(DefaultedBase &&) = default;
 };
 
 struct InheritingConstructors : DefaultedBase { // expected-note 3 {{candidate}}
-  using DefaultedBase::DefaultedBase; // expected-note 2 {{inherited here}}
+  using DefaultedBase::DefaultedBase;
 };
 InheritingConstructors ic = { 42 }; // expected-error {{no matching constructor}}
 
diff --git a/clang/test/CXX/drs/dr16xx.cpp b/clang/test/CXX/drs/dr16xx.cpp
index c0b7c29..c9f084d 100644
--- a/clang/test/CXX/drs/dr16xx.cpp
+++ b/clang/test/CXX/drs/dr16xx.cpp
@@ -71,14 +71,14 @@
 
 namespace dr1645 { // dr1645: 3.9
 #if __cplusplus >= 201103L
-  struct A { // expected-note 2{{candidate}}
+  struct A {
     constexpr A(int, float = 0); // expected-note 2{{candidate}}
     explicit A(int, int = 0); // expected-note 2{{candidate}}
     A(int, int, int = 0) = delete; // expected-note {{candidate}}
   };
 
   struct B : A { // expected-note 2{{candidate}}
-    using A::A; // expected-note 7{{inherited here}}
+    using A::A; // expected-note 5{{inherited here}}
   };
 
   constexpr B a(0); // expected-error {{ambiguous}}
diff --git a/clang/test/CXX/drs/dr19xx.cpp b/clang/test/CXX/drs/dr19xx.cpp
index 15ed305..e6cf337 100644
--- a/clang/test/CXX/drs/dr19xx.cpp
+++ b/clang/test/CXX/drs/dr19xx.cpp
@@ -138,18 +138,21 @@
   struct c;
   struct a {
     a() = default;
-    a(const a &) = delete; // expected-note 2{{deleted}}
+    a(const a &) = delete; // expected-note {{deleted}}
     a(const b &) = delete; // not inherited
-    a(c &&) = delete;
-    template<typename T> a(T) = delete;
+    a(c &&) = delete; // expected-note {{not viable}}
+    template<typename T> a(T) = delete; // expected-note {{would take its own class type by value}}
   };
 
-  struct b : a { // expected-note {{copy constructor of 'b' is implicitly deleted because base class 'dr1959::a' has a deleted copy constructor}}
-    using a::a;
+  struct b : a { // expected-note {{cannot bind}} expected-note {{deleted because}}
+    using a::a; // expected-note 2{{inherited here}}
   };
 
   a x;
-  b y = x; // expected-error {{deleted}}
+  // FIXME: As a resolution to an open DR against P0136R0, we disallow
+  // use of inherited constructors to construct from a single argument
+  // where the base class is reference-related to the argument type.
+  b y = x; // expected-error {{no viable conversion}}
   b z = z; // expected-error {{deleted}}
 
   struct c : a {
@@ -158,7 +161,7 @@
   };
   // FIXME: As a resolution to an open DR against P0136R0, we disallow
   // use of inherited constructors to construct from a single argument
-  // where the derived class is reference-related to its type.
+  // where the base class is reference-related to the argument type.
   c q(static_cast<c&&>(q));
 #endif
 }
diff --git a/clang/test/CXX/special/class.inhctor/p1.cpp b/clang/test/CXX/special/class.inhctor/p1.cpp
index c006abe..45f6049 100644
--- a/clang/test/CXX/special/class.inhctor/p1.cpp
+++ b/clang/test/CXX/special/class.inhctor/p1.cpp
@@ -3,7 +3,7 @@
 // Note: [class.inhctor] was removed by P0136R1. This tests the new behavior
 // for the wording that used to be there.
 
-struct A { // expected-note 8{{candidate is the implicit}}
+struct A { // expected-note 4{{candidate is the implicit}}
   A(...); // expected-note 4{{candidate constructor}} expected-note 4{{candidate inherited constructor}}
   A(int = 0, int = 0, int = 0, int = 0, ...); // expected-note 3{{candidate constructor}} expected-note 3{{candidate inherited constructor}}
   A(int = 0, int = 0, ...); // expected-note 3{{candidate constructor}} expected-note 3{{candidate inherited constructor}}
@@ -15,7 +15,7 @@
 };
 
 struct B : A { // expected-note 4{{candidate is the implicit}}
-  using A::A; // expected-note 19{{inherited here}}
+  using A::A; // expected-note 15{{inherited here}}
   B(void*);
 };
 
diff --git a/clang/test/CXX/special/class.inhctor/p3.cpp b/clang/test/CXX/special/class.inhctor/p3.cpp
index 7f05487..19f15eb 100644
--- a/clang/test/CXX/special/class.inhctor/p3.cpp
+++ b/clang/test/CXX/special/class.inhctor/p3.cpp
@@ -14,21 +14,21 @@
 
 D1 fd1() { return 1; }
 
-struct B2 { // expected-note 2{{candidate}}
+struct B2 {
   explicit B2(int, int = 0, int = 0);
 };
 struct D2 : B2 { // expected-note 2{{candidate constructor}}
-  using B2::B2; // expected-note 2{{inherited here}}
+  using B2::B2;
 };
 D2 d2a(1), d2b(1, 1), d2c(1, 1, 1);
 
 D2 fd2() { return 1; } // expected-error {{no viable conversion}}
 
-struct B3 { // expected-note 2{{candidate}}
+struct B3 {
   B3(void*); // expected-note {{candidate}}
 };
 struct D3 : B3 { // expected-note 2{{candidate constructor}}
-  using B3::B3; // expected-note 3{{inherited here}}
+  using B3::B3; // expected-note {{inherited here}}
 };
 D3 fd3() { return 1; } // expected-error {{no viable conversion}}
 
diff --git a/clang/test/CXX/special/class.inhctor/p7.cpp b/clang/test/CXX/special/class.inhctor/p7.cpp
index c22a43a..2d7acdc 100644
--- a/clang/test/CXX/special/class.inhctor/p7.cpp
+++ b/clang/test/CXX/special/class.inhctor/p7.cpp
@@ -3,15 +3,15 @@
 // Note: [class.inhctor] was removed by P0136R1. This tests the new behavior
 // for the wording that used to be there.
 
-struct B1 { // expected-note 2{{candidate}}
+struct B1 {
   B1(int); // expected-note {{candidate}}
 };
-struct B2 { // expected-note 2{{candidate}}
+struct B2 {
   B2(int); // expected-note {{candidate}}
 };
 struct D1 : B1, B2 { // expected-note 2{{candidate}}
-  using B1::B1; // expected-note 3{{inherited here}}
-  using B2::B2; // expected-note 3{{inherited here}}
+  using B1::B1; // expected-note {{inherited here}}
+  using B2::B2; // expected-note {{inherited here}}
 };
 struct D2 : B1, B2 {
   using B1::B1;
diff --git a/clang/test/SemaCXX/cxx11-inheriting-ctors.cpp b/clang/test/SemaCXX/cxx11-inheriting-ctors.cpp
index 5ce8d1a..c9e0118 100644
--- a/clang/test/SemaCXX/cxx11-inheriting-ctors.cpp
+++ b/clang/test/SemaCXX/cxx11-inheriting-ctors.cpp
@@ -56,9 +56,9 @@
 }
 
 namespace ExplicitConv {
-  struct B {}; // expected-note 2{{candidate}}
+  struct B {};
   struct D : B { // expected-note 3{{candidate}}
-    using B::B; // expected-note 2{{inherited}}
+    using B::B;
   };
   struct X { explicit operator B(); } x;
   struct Y { explicit operator D(); } y;
@@ -68,19 +68,40 @@
 }
 
 namespace NestedListInit {
-  struct B { B(); } b; // expected-note 5{{candidate}}
-  struct D : B { // expected-note 3{{candidate}}
-    using B::B; // expected-note 2{{inherited}}
+  struct B { B(); } b; // expected-note 3{{candidate}}
+  struct D : B { // expected-note 14{{not viable}}
+    using B::B;
   };
   // This is a bit weird. We're allowed one pair of braces for overload
   // resolution, and one more pair of braces due to [over.ics.list]/2.
   B b1 = {b};
   B b2 = {{b}};
   B b3 = {{{b}}}; // expected-error {{no match}}
-  // This is the same, but we get one call to D's version of B::B(const B&)
-  // before the two permitted calls to D::D(D&&).
-  D d1 = {b};
-  D d2 = {{b}};
-  D d3 = {{{b}}};
+  // Per a proposed defect resolution, we don't get to call
+  // D's version of B::B(const B&) here.
+  D d0 = b; // expected-error {{no viable conversion}}
+  D d1 = {b}; // expected-error {{no match}}
+  D d2 = {{b}}; // expected-error {{no match}}
+  D d3 = {{{b}}}; // expected-error {{no match}}
   D d4 = {{{{b}}}}; // expected-error {{no match}}
 }
+
+namespace PR31606 {
+  // PR31606: as part of a proposed defect resolution, do not consider
+  // inherited constructors that would be copy constructors for any class
+  // between the declaring class and the constructed class (inclusive).
+  struct Base {};
+
+  struct A : Base {
+    using Base::Base;
+    bool operator==(A const &) const; // expected-note {{no known conversion from 'PR31606::B' to 'const PR31606::A' for 1st argument}}
+  };
+
+  struct B : Base {
+    using Base::Base;
+  };
+
+  bool a = A{} == A{};
+  // Note, we do *not* allow operator=='s argument to use the inherited A::A(Base&&) constructor to construct from B{}.
+  bool b = A{} == B{}; // expected-error {{invalid operands}}
+}
diff --git a/clang/test/SemaTemplate/cxx1z-using-declaration.cpp b/clang/test/SemaTemplate/cxx1z-using-declaration.cpp
index 7bef36d..87ca748 100644
--- a/clang/test/SemaTemplate/cxx1z-using-declaration.cpp
+++ b/clang/test/SemaTemplate/cxx1z-using-declaration.cpp
@@ -17,7 +17,7 @@
 
 // Test using non-type members from pack of base classes.
 template<typename ...T> struct A : T... { // expected-note 2{{candidate}}
-  using T::T ...; // expected-note 6{{inherited here}}
+  using T::T ...; // expected-note 2{{inherited here}}
   using T::operator() ...;
   using T::operator T* ...;
   using T::h ...;
@@ -29,7 +29,7 @@
 };
 
 namespace test_A {
-  struct X { // expected-note 2{{candidate}}
+  struct X {
     X();
     X(int); // expected-note {{candidate}}
     void operator()(int); // expected-note 2{{candidate}}
@@ -43,7 +43,7 @@
     operator Y *();
     void h(int, int); // expected-note {{not viable}}
   };
-  struct Z { // expected-note 2{{candidate}}
+  struct Z {
     Z();
     Z(int); // expected-note {{candidate}}
     void operator()(int); // expected-note 2{{candidate}}