Index: lib/AST/DeclCXX.cpp =================================================================== --- lib/AST/DeclCXX.cpp +++ lib/AST/DeclCXX.cpp @@ -533,6 +533,17 @@ } else if (Constructor->isMoveConstructor()) SMKind |= SMF_MoveConstructor; } + + // C++ [dcl.init.aggr]p1: + // An aggregate is an array or a class with no user-declared + // constructors [...]. + // C++11 [dcl.init.aggr]p1: DR1518 + // An aggregate is an array or a class with no user-provided, explicit, or + // inherited constructors + if (getASTContext().getLangOpts().CPlusPlus11 + ? (Constructor->isUserProvided() || Constructor->isExplicit()) + : !Constructor->isImplicit()) + data().Aggregate = false; } // Handle constructors, including those inherited from base classes. @@ -546,20 +557,6 @@ // constructor [...] if (Constructor->isConstexpr() && !Constructor->isCopyOrMoveConstructor()) data().HasConstexprNonCopyMoveConstructor = true; - - // C++ [dcl.init.aggr]p1: - // An aggregate is an array or a class with no user-declared - // constructors [...]. - // 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) [...]. - if (getASTContext().getLangOpts().CPlusPlus11 - ? Constructor->isUserProvided() - : !Constructor->isImplicit()) - data().Aggregate = false; } // Handle destructors. @@ -989,8 +986,12 @@ if (UsingDecl *Using = dyn_cast(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 + data().Aggregate = false; + } if (Using->getDeclName().getCXXOverloadedOperator() == OO_Equal) data().HasInheritedAssignment = true; Index: test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1.cpp =================================================================== --- test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1.cpp +++ test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p1.cpp @@ -122,3 +122,38 @@ ~DefaultedAggr() = default; }; DefaultedAggr da = { 42 } ; + +struct ExplicitDefaultedAggr { + int n; + explicit ExplicitDefaultedAggr() = default; // expected-note {{candidate}} + ExplicitDefaultedAggr(const ExplicitDefaultedAggr &) = default; // expected-note {{candidate}} + ExplicitDefaultedAggr(ExplicitDefaultedAggr &&) = default; // expected-note {{candidate}} +}; +ExplicitDefaultedAggr eda = { 42 }; // expected-error {{no matching constructor}} + +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}} +}; + +struct InheritingConstructors : DefaultedBase { // expected-note 3 {{candidate}} + using DefaultedBase::DefaultedBase; // expected-note 2 {{inherited here}} +}; +InheritingConstructors ic = { 42 }; // expected-error {{no matching constructor}} + +struct NonInheritingConstructors : DefaultedBase {}; // expected-note 0+ {{candidate}} +NonInheritingConstructors nic = { 42 }; +#if __cplusplus <= 201402L +// expected-error@-2 {{no matching constructor}} +#endif + +struct NonAggrBase { + NonAggrBase(int) {} +}; +struct HasNonAggrBase : NonAggrBase {}; // expected-note 0+ {{candidate}} +HasNonAggrBase hnab = {42}; +#if __cplusplus <= 201402L +// expected-error@-2 {{no matching constructor}} +#endif Index: test/CXX/drs/dr15xx.cpp =================================================================== --- test/CXX/drs/dr15xx.cpp +++ test/CXX/drs/dr15xx.cpp @@ -135,6 +135,53 @@ } } +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 int Eat(T); // expected-note 0+ {{candidate}} +Z0 a; +Z0 b{}; +Z0 c = {}; // expected-error {{explicit in copy-initialization}} +int i = Eat({}); // expected-error {{no matching function for call to 'Eat'}} + +Z c2 = {}; // expected-error {{explicit in copy-initialization}} +int i2 = Eat({}); // 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(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));