forked from OSchip/llvm-project
[Sema] Don't perform aggregate initialization for types with explicit constructors
Summary: The C++17 rules for aggregate initialization changed to disallow types with explicit constructors [dcl.init.aggr]p1. This patch implements that new rule. Reviewers: rsmith Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D25654 llvm-svn: 288565
This commit is contained in:
parent
572e6deeb7
commit
283d8d45db
|
@ -533,6 +533,17 @@ void CXXRecordDecl::addedMember(Decl *D) {
|
|||
} 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 @@ void CXXRecordDecl::addedMember(Decl *D) {
|
|||
// 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 @@ void CXXRecordDecl::addedMember(Decl *D) {
|
|||
|
||||
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
|
||||
data().Aggregate = false;
|
||||
}
|
||||
|
||||
if (Using->getDeclName().getCXXOverloadedOperator() == OO_Equal)
|
||||
data().HasInheritedAssignment = true;
|
||||
|
|
|
@ -122,3 +122,39 @@ struct DefaultedAggr {
|
|||
~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}}
|
||||
ExplicitDefaultedAggr eda2{};
|
||||
|
||||
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
|
||||
|
|
|
@ -12,3 +12,5 @@ struct B : NotAggregateBase {
|
|||
explicit B() = default; // expected-note {{here}}
|
||||
};
|
||||
B b = {}; // expected-error {{chosen constructor is explicit}}
|
||||
B b2{};
|
||||
B b3;
|
||||
|
|
|
@ -135,6 +135,53 @@ namespace dr1512 { // dr1512: 4.0
|
|||
}
|
||||
}
|
||||
|
||||
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 = {}; // expected-error {{explicit in copy-initialization}}
|
||||
int i = Eat<Z0>({}); // expected-error {{no matching function for call to 'Eat'}}
|
||||
|
||||
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));
|
||||
|
|
Loading…
Reference in New Issue