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@-2 {{aggregate initialization of type 'A' with user-declared constructors is incompatible with C++2a}} +#else + // expected-error@-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@-2 2{{aggregate initialization of type 'A' with user-declared constructors is incompatible with C++2a}} +#else + // expected-error@-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> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits