EricWF updated this revision to Diff 76095.
EricWF added a comment.

- Disallow classes with inherited constructors
- Add tests under `test/CXX/drs/dr15xx.cpp`

I still only implemented this change in C++1z, please let me know if you want 
me to backport the DR.


https://reviews.llvm.org/D25654

Files:
  lib/AST/DeclCXX.cpp
  test/CXX/drs/dr15xx.cpp
  test/SemaCXX/aggregate-initialization.cpp

Index: test/SemaCXX/aggregate-initialization.cpp
===================================================================
--- test/SemaCXX/aggregate-initialization.cpp
+++ test/SemaCXX/aggregate-initialization.cpp
@@ -146,3 +146,14 @@
   // expected-error@-5 {{protected constructor}}
   // expected-note@-30 {{here}}
 }
+
+namespace diff_cpp1z_dcl_init_aggr_example {
+struct ExplicitDefault {
+  explicit ExplicitDefault() = default;
+};
+ExplicitDefault d = {};
+#if __cplusplus > 201402L
+// expected-error@-2 {{explicit in copy-initialization}}
+// expected-note@-5 {{here}}
+#endif
+}
Index: test/CXX/drs/dr15xx.cpp
===================================================================
--- test/CXX/drs/dr15xx.cpp
+++ test/CXX/drs/dr15xx.cpp
@@ -135,6 +135,56 @@
   }
 }
 
+namespace dr1518 { // dr1518: 4.0
+#if __cplusplus >= 201103L
+struct Z0 { // expected-note 0+ {{candidate}}
+  explicit Z0() = default; // expected-note 0+ {{here}}
+};
+struct Z { // expected-note 0+ {{candidate}}
+  explicit Z(); // expected-note 0+ {{here}}
+  explicit Z(int);
+  explicit Z(int, int); // expected-note 0+ {{here}}
+};
+template <class T> int Eat(T); // expected-note 0+ {{candidate}}
+Z0 a;
+Z0 b{};
+Z0 c = {};
+int i = Eat<Z0>({});
+#if __cplusplus > 201402L
+// expected-error@-3 {{explicit in copy-initialization}}
+// expected-error@-3 {{no matching function for call to 'Eat'}}
+#endif
+Z c2 = {}; // expected-error {{explicit in copy-initialization}}
+int i2 = Eat<Z>({}); // expected-error {{no matching function for call to 'Eat'}}
+Z a1 = 1; // expected-error {{no viable conversion}}
+Z a3 = Z(1);
+Z a2(1);
+Z *p = new Z(1);
+Z a4 = (Z)1;
+Z a5 = static_cast<Z>(1);
+Z a6 = {4, 3}; // expected-error {{explicit in copy-initialization}}
+
+struct UserProvidedBaseCtor { // expected-note 0+ {{candidate}}
+  UserProvidedBaseCtor() {}
+};
+struct DoesntInheritCtor : UserProvidedBaseCtor { // expected-note 0+ {{candidate}}
+  int x;
+};
+DoesntInheritCtor I{{}, 42};
+#if __cplusplus <= 201402L
+// expected-error@-2 {{no matching constructor}}
+#endif
+
+struct BaseCtor { BaseCtor() = default; }; // expected-note 0+ {{candidate}}
+struct InheritsCtor : BaseCtor { // expected-note 1+ {{candidate}}
+  using BaseCtor::BaseCtor;      // expected-note 2 {{inherited here}}
+  int x;
+};
+InheritsCtor II = {{}, 42}; // expected-error {{no matching constructor}}
+
+#endif                      // __cplusplus >= 201103L
+}
+
 namespace dr1550 { // dr1550: yes
   int f(bool b, int n) {
     return (b ? (throw 0) : n) + (b ? n : (throw 0));
Index: lib/AST/DeclCXX.cpp
===================================================================
--- lib/AST/DeclCXX.cpp
+++ lib/AST/DeclCXX.cpp
@@ -553,13 +553,15 @@
     // C++11 [dcl.init.aggr]p1:
     //   An aggregate is an array or a class with no user-provided
     //   constructors [...].
-    // C++11 [dcl.init.aggr]p1:
-    //   An aggregate is an array or a class with no user-provided
-    //   constructors (including those inherited from a base class) [...].
+    // C++1z [dcl.init.aggr]p1:
+    //  An aggregate is an array or a class with no user-provided, explicit, or
+    //  inherited constructors
     if (getASTContext().getLangOpts().CPlusPlus11
             ? Constructor->isUserProvided()
             : !Constructor->isImplicit())
       data().Aggregate = false;
+    if (getASTContext().getLangOpts().CPlusPlus1z && Constructor->isExplicit())
+      data().Aggregate = false;
   }
 
   // Handle destructors.
@@ -989,8 +991,13 @@
 
   if (UsingDecl *Using = dyn_cast<UsingDecl>(D)) {
     if (Using->getDeclName().getNameKind() ==
-        DeclarationName::CXXConstructorName)
+        DeclarationName::CXXConstructorName) {
       data().HasInheritedConstructor = true;
+      // C++1z [dcl.init.aggr]p1:
+      //  An aggregate is [...] a class [...] with no inherited constructors
+      if (getASTContext().getLangOpts().CPlusPlus1z)
+        data().Aggregate = false;
+    }
 
     if (Using->getDeclName().getCXXOverloadedOperator() == OO_Equal)
       data().HasInheritedAssignment = true;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to