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