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.
|
||||
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
|
||||
/// be constexpr.
|
||||
bool DefaultedDefaultConstructorIsConstexpr : 1;
|
||||
|
@ -1278,7 +1282,8 @@ public:
|
|||
/// per core issue 253.
|
||||
bool allowConstDefaultInit() const {
|
||||
return !data().HasUninitializedFields ||
|
||||
hasUserProvidedDefaultConstructor();
|
||||
!(data().HasDefaultedDefaultConstructor ||
|
||||
needsImplicitDefaultConstructor());
|
||||
}
|
||||
|
||||
/// \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.HasConstexprNonCopyMoveConstructor
|
||||
= FromData.HasConstexprNonCopyMoveConstructor;
|
||||
ToData.HasDefaultedDefaultConstructor
|
||||
= FromData.HasDefaultedDefaultConstructor;
|
||||
ToData.DefaultedDefaultConstructorIsConstexpr
|
||||
= FromData.DefaultedDefaultConstructorIsConstexpr;
|
||||
ToData.HasConstexprDefaultConstructor
|
||||
|
|
|
@ -61,6 +61,7 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D)
|
|||
DefaultedDestructorIsDeleted(false), HasTrivialSpecialMembers(SMF_All),
|
||||
DeclaredNonTrivialSpecialMembers(0), HasIrrelevantDestructor(true),
|
||||
HasConstexprNonCopyMoveConstructor(false),
|
||||
HasDefaultedDefaultConstructor(false),
|
||||
DefaultedDefaultConstructorIsConstexpr(true),
|
||||
HasConstexprDefaultConstructor(false),
|
||||
HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false),
|
||||
|
@ -497,6 +498,8 @@ void CXXRecordDecl::addedMember(Decl *D) {
|
|||
data().UserProvidedDefaultConstructor = true;
|
||||
if (Constructor->isConstexpr())
|
||||
data().HasConstexprDefaultConstructor = true;
|
||||
if (Constructor->isDefaulted())
|
||||
data().HasDefaultedDefaultConstructor = true;
|
||||
}
|
||||
|
||||
if (!FunTmpl) {
|
||||
|
|
|
@ -1423,6 +1423,7 @@ void ASTDeclReader::ReadCXXDefinitionData(
|
|||
Data.DeclaredNonTrivialSpecialMembers = Record[Idx++];
|
||||
Data.HasIrrelevantDestructor = Record[Idx++];
|
||||
Data.HasConstexprNonCopyMoveConstructor = Record[Idx++];
|
||||
Data.HasDefaultedDefaultConstructor = Record[Idx++];
|
||||
Data.DefaultedDefaultConstructorIsConstexpr = Record[Idx++];
|
||||
Data.HasConstexprDefaultConstructor = Record[Idx++];
|
||||
Data.HasNonLiteralTypeFieldsOrBases = Record[Idx++];
|
||||
|
@ -1548,6 +1549,7 @@ void ASTDeclReader::MergeDefinitionData(
|
|||
OR_FIELD(DeclaredNonTrivialSpecialMembers)
|
||||
MATCH_FIELD(HasIrrelevantDestructor)
|
||||
OR_FIELD(HasConstexprNonCopyMoveConstructor)
|
||||
OR_FIELD(HasDefaultedDefaultConstructor)
|
||||
MATCH_FIELD(DefaultedDefaultConstructorIsConstexpr)
|
||||
OR_FIELD(HasConstexprDefaultConstructor)
|
||||
MATCH_FIELD(HasNonLiteralTypeFieldsOrBases)
|
||||
|
|
|
@ -5558,6 +5558,7 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec
|
|||
Record.push_back(Data.DeclaredNonTrivialSpecialMembers);
|
||||
Record.push_back(Data.HasIrrelevantDestructor);
|
||||
Record.push_back(Data.HasConstexprNonCopyMoveConstructor);
|
||||
Record.push_back(Data.HasDefaultedDefaultConstructor);
|
||||
Record.push_back(Data.DefaultedDefaultConstructorIsConstexpr);
|
||||
Record.push_back(Data.HasConstexprDefaultConstructor);
|
||||
Record.push_back(Data.HasNonLiteralTypeFieldsOrBases);
|
||||
|
|
|
@ -74,6 +74,33 @@ struct some_init_container_ctor {
|
|||
struct no_fields_container {
|
||||
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() {
|
||||
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_ctor siconc; // 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 {
|
||||
|
|
Loading…
Reference in New Issue