Fix rejects-valid caused by r261297.
r261297 called hasUserProvidedDefaultConstructor() to check if defining a const object is ok. This is incorrect for this example: struct X { template<typename ...T> X(T...); int n; }; const X x; // formerly OK, now bogus error Instead, track if a class has a defaulted default constructor, and disallow a const object for classes that either have defaulted default constructors or if they need an implicit constructor. Bug report and fix approach by Richard Smith, thanks! llvm-svn: 261770
This commit is contained in:
parent
57ca270b7a
commit
72c57f49c4
|
@ -421,6 +421,10 @@ class CXXRecordDecl : public RecordDecl {
|
||||||
/// constructor which is neither the copy nor move constructor.
|
/// constructor which is neither the copy nor move constructor.
|
||||||
bool HasConstexprNonCopyMoveConstructor : 1;
|
bool HasConstexprNonCopyMoveConstructor : 1;
|
||||||
|
|
||||||
|
/// \brief True if this class has a (possibly implicit) defaulted default
|
||||||
|
/// constructor.
|
||||||
|
bool HasDefaultedDefaultConstructor : 1;
|
||||||
|
|
||||||
/// \brief True if a defaulted default constructor for this class would
|
/// \brief True if a defaulted default constructor for this class would
|
||||||
/// be constexpr.
|
/// be constexpr.
|
||||||
bool DefaultedDefaultConstructorIsConstexpr : 1;
|
bool DefaultedDefaultConstructorIsConstexpr : 1;
|
||||||
|
@ -1278,7 +1282,8 @@ public:
|
||||||
/// per core issue 253.
|
/// per core issue 253.
|
||||||
bool allowConstDefaultInit() const {
|
bool allowConstDefaultInit() const {
|
||||||
return !data().HasUninitializedFields ||
|
return !data().HasUninitializedFields ||
|
||||||
hasUserProvidedDefaultConstructor();
|
!(data().HasDefaultedDefaultConstructor ||
|
||||||
|
needsImplicitDefaultConstructor());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Determine whether this class has a destructor which has no
|
/// \brief Determine whether this class has a destructor which has no
|
||||||
|
|
|
@ -2040,6 +2040,8 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To,
|
||||||
ToData.HasIrrelevantDestructor = FromData.HasIrrelevantDestructor;
|
ToData.HasIrrelevantDestructor = FromData.HasIrrelevantDestructor;
|
||||||
ToData.HasConstexprNonCopyMoveConstructor
|
ToData.HasConstexprNonCopyMoveConstructor
|
||||||
= FromData.HasConstexprNonCopyMoveConstructor;
|
= FromData.HasConstexprNonCopyMoveConstructor;
|
||||||
|
ToData.HasDefaultedDefaultConstructor
|
||||||
|
= FromData.HasDefaultedDefaultConstructor;
|
||||||
ToData.DefaultedDefaultConstructorIsConstexpr
|
ToData.DefaultedDefaultConstructorIsConstexpr
|
||||||
= FromData.DefaultedDefaultConstructorIsConstexpr;
|
= FromData.DefaultedDefaultConstructorIsConstexpr;
|
||||||
ToData.HasConstexprDefaultConstructor
|
ToData.HasConstexprDefaultConstructor
|
||||||
|
|
|
@ -61,6 +61,7 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
|
||||||
DefaultedDestructorIsDeleted(false), HasTrivialSpecialMembers(SMF_All),
|
DefaultedDestructorIsDeleted(false), HasTrivialSpecialMembers(SMF_All),
|
||||||
DeclaredNonTrivialSpecialMembers(0), HasIrrelevantDestructor(true),
|
DeclaredNonTrivialSpecialMembers(0), HasIrrelevantDestructor(true),
|
||||||
HasConstexprNonCopyMoveConstructor(false),
|
HasConstexprNonCopyMoveConstructor(false),
|
||||||
|
HasDefaultedDefaultConstructor(false),
|
||||||
DefaultedDefaultConstructorIsConstexpr(true),
|
DefaultedDefaultConstructorIsConstexpr(true),
|
||||||
HasConstexprDefaultConstructor(false),
|
HasConstexprDefaultConstructor(false),
|
||||||
HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false),
|
HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false),
|
||||||
|
@ -497,6 +498,8 @@ void CXXRecordDecl::addedMember(Decl *D) {
|
||||||
data().UserProvidedDefaultConstructor = true;
|
data().UserProvidedDefaultConstructor = true;
|
||||||
if (Constructor->isConstexpr())
|
if (Constructor->isConstexpr())
|
||||||
data().HasConstexprDefaultConstructor = true;
|
data().HasConstexprDefaultConstructor = true;
|
||||||
|
if (Constructor->isDefaulted())
|
||||||
|
data().HasDefaultedDefaultConstructor = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!FunTmpl) {
|
if (!FunTmpl) {
|
||||||
|
|
|
@ -1423,6 +1423,7 @@ void ASTDeclReader::ReadCXXDefinitionData(
|
||||||
Data.DeclaredNonTrivialSpecialMembers = Record[Idx++];
|
Data.DeclaredNonTrivialSpecialMembers = Record[Idx++];
|
||||||
Data.HasIrrelevantDestructor = Record[Idx++];
|
Data.HasIrrelevantDestructor = Record[Idx++];
|
||||||
Data.HasConstexprNonCopyMoveConstructor = Record[Idx++];
|
Data.HasConstexprNonCopyMoveConstructor = Record[Idx++];
|
||||||
|
Data.HasDefaultedDefaultConstructor = Record[Idx++];
|
||||||
Data.DefaultedDefaultConstructorIsConstexpr = Record[Idx++];
|
Data.DefaultedDefaultConstructorIsConstexpr = Record[Idx++];
|
||||||
Data.HasConstexprDefaultConstructor = Record[Idx++];
|
Data.HasConstexprDefaultConstructor = Record[Idx++];
|
||||||
Data.HasNonLiteralTypeFieldsOrBases = Record[Idx++];
|
Data.HasNonLiteralTypeFieldsOrBases = Record[Idx++];
|
||||||
|
@ -1548,6 +1549,7 @@ void ASTDeclReader::MergeDefinitionData(
|
||||||
OR_FIELD(DeclaredNonTrivialSpecialMembers)
|
OR_FIELD(DeclaredNonTrivialSpecialMembers)
|
||||||
MATCH_FIELD(HasIrrelevantDestructor)
|
MATCH_FIELD(HasIrrelevantDestructor)
|
||||||
OR_FIELD(HasConstexprNonCopyMoveConstructor)
|
OR_FIELD(HasConstexprNonCopyMoveConstructor)
|
||||||
|
OR_FIELD(HasDefaultedDefaultConstructor)
|
||||||
MATCH_FIELD(DefaultedDefaultConstructorIsConstexpr)
|
MATCH_FIELD(DefaultedDefaultConstructorIsConstexpr)
|
||||||
OR_FIELD(HasConstexprDefaultConstructor)
|
OR_FIELD(HasConstexprDefaultConstructor)
|
||||||
MATCH_FIELD(HasNonLiteralTypeFieldsOrBases)
|
MATCH_FIELD(HasNonLiteralTypeFieldsOrBases)
|
||||||
|
|
|
@ -5558,6 +5558,7 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec
|
||||||
Record.push_back(Data.DeclaredNonTrivialSpecialMembers);
|
Record.push_back(Data.DeclaredNonTrivialSpecialMembers);
|
||||||
Record.push_back(Data.HasIrrelevantDestructor);
|
Record.push_back(Data.HasIrrelevantDestructor);
|
||||||
Record.push_back(Data.HasConstexprNonCopyMoveConstructor);
|
Record.push_back(Data.HasConstexprNonCopyMoveConstructor);
|
||||||
|
Record.push_back(Data.HasDefaultedDefaultConstructor);
|
||||||
Record.push_back(Data.DefaultedDefaultConstructorIsConstexpr);
|
Record.push_back(Data.DefaultedDefaultConstructorIsConstexpr);
|
||||||
Record.push_back(Data.HasConstexprDefaultConstructor);
|
Record.push_back(Data.HasConstexprDefaultConstructor);
|
||||||
Record.push_back(Data.HasNonLiteralTypeFieldsOrBases);
|
Record.push_back(Data.HasNonLiteralTypeFieldsOrBases);
|
||||||
|
|
|
@ -74,6 +74,33 @@ struct some_init_container_ctor {
|
||||||
struct no_fields_container {
|
struct no_fields_container {
|
||||||
no_fields nf;
|
no_fields nf;
|
||||||
};
|
};
|
||||||
|
struct param_pack_ctor {
|
||||||
|
template <typename... T>
|
||||||
|
param_pack_ctor(T...);
|
||||||
|
int n;
|
||||||
|
};
|
||||||
|
struct param_pack_ctor_field {
|
||||||
|
param_pack_ctor ndc;
|
||||||
|
};
|
||||||
|
struct multi_param_pack_ctor {
|
||||||
|
template <typename... T, typename... U>
|
||||||
|
multi_param_pack_ctor(T..., U..., int f = 0);
|
||||||
|
int n;
|
||||||
|
};
|
||||||
|
struct ignored_template_ctor_and_def {
|
||||||
|
template <class T> ignored_template_ctor_and_def(T* f = nullptr);
|
||||||
|
ignored_template_ctor_and_def() = default;
|
||||||
|
int field;
|
||||||
|
};
|
||||||
|
template<bool, typename = void> struct enable_if {};
|
||||||
|
template<typename T> struct enable_if<true, T> { typedef T type; };
|
||||||
|
struct multi_param_pack_and_defaulted {
|
||||||
|
template <typename... T,
|
||||||
|
typename enable_if<sizeof...(T) != 0>::type* = nullptr>
|
||||||
|
multi_param_pack_and_defaulted(T...);
|
||||||
|
multi_param_pack_and_defaulted() = default;
|
||||||
|
int n;
|
||||||
|
};
|
||||||
|
|
||||||
void constobjs() {
|
void constobjs() {
|
||||||
const no_fields nf; // ok
|
const no_fields nf; // ok
|
||||||
|
@ -88,6 +115,12 @@ void constobjs() {
|
||||||
const some_init_container sicon; // expected-error {{default initialization of an object of const type 'const some_init_container' without a user-provided default constructor}}
|
const some_init_container sicon; // expected-error {{default initialization of an object of const type 'const some_init_container' without a user-provided default constructor}}
|
||||||
const some_init_container_ctor siconc; // ok
|
const some_init_container_ctor siconc; // ok
|
||||||
const no_fields_container nfc; // ok
|
const no_fields_container nfc; // ok
|
||||||
|
const param_pack_ctor ppc; // ok
|
||||||
|
const param_pack_ctor_field ppcf; // ok
|
||||||
|
const multi_param_pack_ctor mppc; // ok
|
||||||
|
const multi_param_pack_and_defaulted mppad; // expected-error {{default initialization of an object of const type 'const multi_param_pack_and_defaulted' without a user-provided default constructor}}
|
||||||
|
const ignored_template_ctor_and_def itcad; // expected-error {{default initialization of an object of const type 'const ignored_template_ctor_and_def' without a user-provided default constructor}}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct non_const_derived : non_const_copy {
|
struct non_const_derived : non_const_copy {
|
||||||
|
|
Loading…
Reference in New Issue