r343131 - P1008R1 Classes with user-declared constructors are never aggregates in

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 26 12:00:17 PDT 2018


Author: rsmith
Date: Wed Sep 26 12:00:16 2018
New Revision: 343131

URL: http://llvm.org/viewvc/llvm-project?rev=343131&view=rev
Log:
P1008R1 Classes with user-declared constructors are never aggregates in
C++20.

Added:
    cfe/trunk/test/SemaCXX/cxx2a-compat.cpp
    cfe/trunk/test/SemaCXX/cxx2a-initializer-aggregates.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/www/cxx_status.html

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=343131&r1=343130&r2=343131&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Sep 26 12:00:16 2018
@@ -1872,6 +1872,9 @@ def err_reference_bind_init_list : Error
 def err_init_list_bad_dest_type : Error<
   "%select{|non-aggregate }0type %1 cannot be initialized with an initializer "
   "list">;
+def warn_cxx2a_compat_aggregate_init_with_ctors : Warning<
+  "aggregate initialization of type %0 with user-declared constructors "
+  "is incompatible with C++2a">, DefaultIgnore, InGroup<CXX2aCompat>;
 
 def err_reference_bind_to_bitfield : Error<
   "%select{non-const|volatile}0 reference cannot bind to "

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=343131&r1=343130&r2=343131&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Wed Sep 26 12:00:16 2018
@@ -731,9 +731,14 @@ void CXXRecordDecl::addedMember(Decl *D)
     }
 
     // C++11 [dcl.init.aggr]p1: DR1518
-    //   An aggregate is an array or a class with no user-provided, explicit, or
-    //   inherited constructors
-    if (Constructor->isUserProvided() || Constructor->isExplicit())
+    //   An aggregate is an array or a class with no user-provided [or]
+    //   explicit [...] constructors
+    // C++20 [dcl.init.aggr]p1:
+    //   An aggregate is an array or a class with no user-declared [...]
+    //   constructors
+    if (getASTContext().getLangOpts().CPlusPlus2a
+            ? !Constructor->isImplicit()
+            : (Constructor->isUserProvided() || Constructor->isExplicit()))
       data().Aggregate = false;
   }
 

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=343131&r1=343130&r2=343131&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Wed Sep 26 12:00:16 2018
@@ -964,6 +964,14 @@ void InitListChecker::CheckImplicitInitL
                      StructuredSubobjectInitList->getEndLoc()),
                  "}");
     }
+
+    // Warn if this type won't be an aggregate in future versions of C++.
+    auto *CXXRD = T->getAsCXXRecordDecl();
+    if (CXXRD && CXXRD->hasUserDeclaredConstructor()) {
+      SemaRef.Diag(StructuredSubobjectInitList->getBeginLoc(),
+                   diag::warn_cxx2a_compat_aggregate_init_with_ctors)
+          << StructuredSubobjectInitList->getSourceRange() << T;
+    }
   }
 }
 
@@ -1106,9 +1114,30 @@ void InitListChecker::CheckExplicitInitL
     }
   }
 
-  if (!VerifyOnly && T->isScalarType() &&
-      IList->getNumInits() == 1 && !isa<InitListExpr>(IList->getInit(0)))
-    warnBracedScalarInit(SemaRef, Entity, IList->getSourceRange());
+  if (!VerifyOnly) {
+    if (T->isScalarType() && IList->getNumInits() == 1 &&
+        !isa<InitListExpr>(IList->getInit(0)))
+      warnBracedScalarInit(SemaRef, Entity, IList->getSourceRange());
+
+    // Warn if this is a class type that won't be an aggregate in future
+    // versions of C++.
+    auto *CXXRD = T->getAsCXXRecordDecl();
+    if (CXXRD && CXXRD->hasUserDeclaredConstructor()) {
+      // Don't warn if there's an equivalent default constructor that would be
+      // used instead.
+      bool HasEquivCtor = false;
+      if (IList->getNumInits() == 0) {
+        auto *CD = SemaRef.LookupDefaultConstructor(CXXRD);
+        HasEquivCtor = CD && !CD->isDeleted();
+      }
+
+      if (!HasEquivCtor) {
+        SemaRef.Diag(IList->getBeginLoc(),
+                     diag::warn_cxx2a_compat_aggregate_init_with_ctors)
+            << IList->getSourceRange() << T;
+      }
+    }
+  }
 }
 
 void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity,

Added: cfe/trunk/test/SemaCXX/cxx2a-compat.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx2a-compat.cpp?rev=343131&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx2a-compat.cpp (added)
+++ cfe/trunk/test/SemaCXX/cxx2a-compat.cpp Wed Sep 26 12:00:16 2018
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -Wc++2a-compat-pedantic -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++2a -pedantic -verify %s
+
+struct A { // expected-note 0+{{candidate}}
+  A() = default; // expected-note 0+{{candidate}}
+  int x, y;
+};
+A a1 = {1, 2};
+#if __cplusplus <= 201703L
+  // expected-warning at -2 {{aggregate initialization of type 'A' with user-declared constructors is incompatible with C++2a}}
+#else
+  // expected-error at -4 {{no matching constructor}}
+#endif
+A a2 = {};
+
+struct B : A { A a; };
+B b1 = {{}, {}}; // ok
+B b2 = {1, 2, 3, 4};
+#if __cplusplus <= 201703L
+  // expected-warning at -2 2{{aggregate initialization of type 'A' with user-declared constructors is incompatible with C++2a}}
+#else
+  // expected-error at -4 2{{no viable conversion from 'int' to 'A'}}
+#endif

Added: cfe/trunk/test/SemaCXX/cxx2a-initializer-aggregates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx2a-initializer-aggregates.cpp?rev=343131&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx2a-initializer-aggregates.cpp (added)
+++ cfe/trunk/test/SemaCXX/cxx2a-initializer-aggregates.cpp Wed Sep 26 12:00:16 2018
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -std=c++2a %s -verify
+
+namespace class_with_ctor {
+  struct A { // expected-note 6{{candidate}}
+    A() = default; // expected-note 3{{candidate}}
+    int x;
+    int y;
+  };
+  A a = {1, 2}; // expected-error {{no matching constructor}}
+
+  struct B {
+    int x;
+    int y;
+  };
+  B b1 = B(); // trigger declaration of implicit ctors
+  B b2 = {1, 2}; // ok
+
+  struct C : A {
+    A a;
+  };
+  C c1 = {{}, {}}; // ok, call default ctor twice
+  C c2 = {{1, 2}, {3, 4}}; // expected-error 2{{no matching constructor}}
+}

Modified: cfe/trunk/www/cxx_status.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=343131&r1=343130&r2=343131&view=diff
==============================================================================
--- cfe/trunk/www/cxx_status.html (original)
+++ cfe/trunk/www/cxx_status.html Wed Sep 26 12:00:16 2018
@@ -952,7 +952,7 @@ as the draft C++2a standard evolves.
     <tr>
       <td>Prohibit aggregates with user-declared constructors</td>
       <td><a href="http://wg21.link/p1008r1">P1008R1</a></td>
-      <td class="none" align="center">No</td>
+      <td class="svn" align="center">SVN</td>
     </tr>
     <tr>
       <td>Contracts</td>




More information about the cfe-commits mailing list