Index: include/clang/AST/DeclCXX.h =================================================================== --- include/clang/AST/DeclCXX.h +++ include/clang/AST/DeclCXX.h @@ -378,6 +378,10 @@ /// even if the class has a trivial default constructor. bool HasUninitializedReferenceMember : 1; + /// \brief True if any non-mutable field whose type doesn't have a user- + /// provided default ctor also doesn't have an in-class initializer. + bool HasUninitializedFields : 1; + /// \brief These flags are \c true if a defaulted corresponding special /// member can't be fully analyzed without performing overload resolution. /// @{ @@ -1270,6 +1274,13 @@ return !(data().HasTrivialSpecialMembers & SMF_Destructor); } + /// \brief Determine whether declaring a const variable with this type is ok + /// per core issue 253. + bool allowConstDefaultInit() const { + return !data().HasUninitializedFields || + hasUserProvidedDefaultConstructor(); + } + /// \brief Determine whether this class has a destructor which has no /// semantic effect. /// Index: lib/AST/ASTImporter.cpp =================================================================== --- lib/AST/ASTImporter.cpp +++ lib/AST/ASTImporter.cpp @@ -2023,6 +2023,7 @@ ToData.HasInClassInitializer = FromData.HasInClassInitializer; ToData.HasUninitializedReferenceMember = FromData.HasUninitializedReferenceMember; + ToData.HasUninitializedFields = FromData.HasUninitializedFields; ToData.NeedOverloadResolutionForMoveConstructor = FromData.NeedOverloadResolutionForMoveConstructor; ToData.NeedOverloadResolutionForMoveAssignment Index: lib/AST/DeclCXX.cpp =================================================================== --- lib/AST/DeclCXX.cpp +++ lib/AST/DeclCXX.cpp @@ -46,34 +46,31 @@ } CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) - : UserDeclaredConstructor(false), UserDeclaredSpecialMembers(0), - Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false), - Abstract(false), IsStandardLayout(true), HasNoNonEmptyBases(true), - HasPrivateFields(false), HasProtectedFields(false), HasPublicFields(false), - HasMutableFields(false), HasVariantMembers(false), HasOnlyCMembers(true), - HasInClassInitializer(false), HasUninitializedReferenceMember(false), - NeedOverloadResolutionForMoveConstructor(false), - NeedOverloadResolutionForMoveAssignment(false), - NeedOverloadResolutionForDestructor(false), - DefaultedMoveConstructorIsDeleted(false), - DefaultedMoveAssignmentIsDeleted(false), - DefaultedDestructorIsDeleted(false), - HasTrivialSpecialMembers(SMF_All), - DeclaredNonTrivialSpecialMembers(0), - HasIrrelevantDestructor(true), - HasConstexprNonCopyMoveConstructor(false), - DefaultedDefaultConstructorIsConstexpr(true), - HasConstexprDefaultConstructor(false), - HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false), - UserProvidedDefaultConstructor(false), DeclaredSpecialMembers(0), - ImplicitCopyConstructorHasConstParam(true), - ImplicitCopyAssignmentHasConstParam(true), - HasDeclaredCopyConstructorWithConstParam(false), - HasDeclaredCopyAssignmentWithConstParam(false), - IsLambda(false), IsParsingBaseSpecifiers(false), NumBases(0), NumVBases(0), - Bases(), VBases(), - Definition(D), FirstFriend() { -} + : UserDeclaredConstructor(false), UserDeclaredSpecialMembers(0), + Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false), + Abstract(false), IsStandardLayout(true), HasNoNonEmptyBases(true), + HasPrivateFields(false), HasProtectedFields(false), + HasPublicFields(false), HasMutableFields(false), HasVariantMembers(false), + HasOnlyCMembers(true), HasInClassInitializer(false), + HasUninitializedReferenceMember(false), HasUninitializedFields(false), + NeedOverloadResolutionForMoveConstructor(false), + NeedOverloadResolutionForMoveAssignment(false), + NeedOverloadResolutionForDestructor(false), + DefaultedMoveConstructorIsDeleted(false), + DefaultedMoveAssignmentIsDeleted(false), + DefaultedDestructorIsDeleted(false), HasTrivialSpecialMembers(SMF_All), + DeclaredNonTrivialSpecialMembers(0), HasIrrelevantDestructor(true), + HasConstexprNonCopyMoveConstructor(false), + DefaultedDefaultConstructorIsConstexpr(true), + HasConstexprDefaultConstructor(false), + HasNonLiteralTypeFieldsOrBases(false), ComputedVisibleConversions(false), + UserProvidedDefaultConstructor(false), DeclaredSpecialMembers(0), + ImplicitCopyConstructorHasConstParam(true), + ImplicitCopyAssignmentHasConstParam(true), + HasDeclaredCopyConstructorWithConstParam(false), + HasDeclaredCopyAssignmentWithConstParam(false), IsLambda(false), + IsParsingBaseSpecifiers(false), NumBases(0), NumVBases(0), Bases(), + VBases(), Definition(D), FirstFriend() {} CXXBaseSpecifier *CXXRecordDecl::DefinitionData::getBasesSlowCase() const { return Bases.get(Definition->getASTContext().getExternalSource()); @@ -332,6 +329,9 @@ if (BaseClassDecl->hasUninitializedReferenceMember()) data().HasUninitializedReferenceMember = true; + if (!BaseClassDecl->allowConstDefaultInit()) + data().HasUninitializedFields = true; + addedClassSubobject(BaseClassDecl); } @@ -392,6 +392,7 @@ return !forallBases([](const CXXRecordDecl *) { return true; }); } + bool CXXRecordDecl::isTriviallyCopyable() const { // C++0x [class]p5: // A trivially copyable class is a class that: @@ -702,6 +703,15 @@ data().IsStandardLayout = false; } + if (!Field->hasInClassInitializer() && !Field->isMutable()) { + if (CXXRecordDecl *FieldType = Field->getType()->getAsCXXRecordDecl()) { + if (!FieldType->allowConstDefaultInit()) + data().HasUninitializedFields = true; + } else { + data().HasUninitializedFields = true; + } + } + // Record if this field is the first non-literal or volatile field or base. if (!T->isLiteralType(Context) || T.isVolatileQualified()) data().HasNonLiteralTypeFieldsOrBases = true; Index: lib/Sema/SemaInit.cpp =================================================================== --- lib/Sema/SemaInit.cpp +++ lib/Sema/SemaInit.cpp @@ -3515,18 +3515,23 @@ // If a program calls for the default initialization of an object // of a const-qualified type T, T shall be a class type with a // user-provided default constructor. + // C++ core issue 253 proposal: + // If the implicit default constructor initializes all subobjects, no + // initializer should be required. + // The 253 proposal is for example needed to process libstdc++ headers in 5.x. + CXXConstructorDecl *CtorDecl = cast(Best->Function); if (Kind.getKind() == InitializationKind::IK_Default && - Entity.getType().isConstQualified() && - !cast(Best->Function)->isUserProvided()) { - if (!maybeRecoverWithZeroInitialization(S, Sequence, Entity)) - Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst); - return; + Entity.getType().isConstQualified()) { + if (!CtorDecl->getParent()->allowConstDefaultInit()) { + if (!maybeRecoverWithZeroInitialization(S, Sequence, Entity)) + Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst); + return; + } } // C++11 [over.match.list]p1: // In copy-list-initialization, if an explicit constructor is chosen, the // initializer is ill-formed. - CXXConstructorDecl *CtorDecl = cast(Best->Function); if (IsListInit && !Kind.AllowExplicit() && CtorDecl->isExplicit()) { Sequence.SetFailed(InitializationSequence::FK_ExplicitConstructor); return; Index: lib/Serialization/ASTReaderDecl.cpp =================================================================== --- lib/Serialization/ASTReaderDecl.cpp +++ lib/Serialization/ASTReaderDecl.cpp @@ -1412,6 +1412,7 @@ Data.HasOnlyCMembers = Record[Idx++]; Data.HasInClassInitializer = Record[Idx++]; Data.HasUninitializedReferenceMember = Record[Idx++]; + Data.HasUninitializedFields = Record[Idx++]; Data.NeedOverloadResolutionForMoveConstructor = Record[Idx++]; Data.NeedOverloadResolutionForMoveAssignment = Record[Idx++]; Data.NeedOverloadResolutionForDestructor = Record[Idx++]; @@ -1536,6 +1537,7 @@ MATCH_FIELD(HasOnlyCMembers) MATCH_FIELD(HasInClassInitializer) MATCH_FIELD(HasUninitializedReferenceMember) + MATCH_FIELD(HasUninitializedFields) MATCH_FIELD(NeedOverloadResolutionForMoveConstructor) MATCH_FIELD(NeedOverloadResolutionForMoveAssignment) MATCH_FIELD(NeedOverloadResolutionForDestructor) Index: lib/Serialization/ASTWriter.cpp =================================================================== --- lib/Serialization/ASTWriter.cpp +++ lib/Serialization/ASTWriter.cpp @@ -5547,6 +5547,7 @@ Record.push_back(Data.HasOnlyCMembers); Record.push_back(Data.HasInClassInitializer); Record.push_back(Data.HasUninitializedReferenceMember); + Record.push_back(Data.HasUninitializedFields); Record.push_back(Data.NeedOverloadResolutionForMoveConstructor); Record.push_back(Data.NeedOverloadResolutionForMoveAssignment); Record.push_back(Data.NeedOverloadResolutionForDestructor); Index: test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp =================================================================== --- test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp +++ test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.default/p2.cpp @@ -116,6 +116,7 @@ namespace PR13492 { struct B { B() = default; + int field; }; void f() { Index: test/CXX/dcl.decl/dcl.init/p6.cpp =================================================================== --- test/CXX/dcl.decl/dcl.init/p6.cpp +++ test/CXX/dcl.decl/dcl.init/p6.cpp @@ -4,9 +4,9 @@ // If a program calls for the default initialization of an object of a // const-qualified type T, T shall be a class type with a -// user-provided default constructor. +// user-provided default constructor, except if T has no uninitialized fields. struct MakeNonPOD { MakeNonPOD(); }; -struct NoUserDefault : public MakeNonPOD { }; +struct NoUserDefault : public MakeNonPOD { int field; }; struct HasUserDefault { HasUserDefault(); }; void test_const_default_init() { @@ -16,7 +16,7 @@ } // rdar://8501008 -struct s0 {}; +struct s0 { int field; }; struct s1 { static const s0 foo; }; const struct s0 s1::foo; // expected-error{{default initialization of an object of const type 'const struct s0' without a user-provided default constructor}} Index: test/CXX/drs/dr4xx.cpp =================================================================== --- test/CXX/drs/dr4xx.cpp +++ test/CXX/drs/dr4xx.cpp @@ -1197,12 +1197,12 @@ int check6[ __is_trivially_assignable(B, const B&) ? 1 : -1]; } -namespace dr497 { // dr497: yes +namespace dr497 { // dr497: sup 253 void before() { struct S { mutable int i; }; - const S cs; // expected-error {{default initialization}} + const S cs; int S::*pm = &S::i; cs.*pm = 88; // expected-error {{not assignable}} } Index: test/SemaCXX/attr-selectany.cpp =================================================================== --- test/SemaCXX/attr-selectany.cpp +++ test/SemaCXX/attr-selectany.cpp @@ -39,7 +39,9 @@ // The D3D11 headers do something like this. MSVC doesn't error on this at // all, even without the __declspec(selectany), in violation of the standard. // We fall back to a warning for selectany to accept headers. -struct SomeStruct {}; +struct SomeStruct { + int foo; +}; extern const __declspec(selectany) SomeStruct some_struct; // expected-warning {{default initialization of an object of const type 'const SomeStruct' without a user-provided default constructor is a Microsoft extension}} // It should be possible to redeclare variables that were defined Index: test/SemaCXX/constexpr-value-init.cpp =================================================================== --- test/SemaCXX/constexpr-value-init.cpp +++ test/SemaCXX/constexpr-value-init.cpp @@ -14,7 +14,7 @@ constexpr A a; // expected-error {{constant expression}} expected-note {{in call to 'A()'}} } -constexpr B b1; // expected-error {{without a user-provided default constructor}} +constexpr B b1; // ok constexpr B b2 = B(); // ok static_assert(b2.a.a == 1, ""); static_assert(b2.a.b == 2, ""); Index: test/SemaCXX/cxx0x-cursory-default-delete.cpp =================================================================== --- test/SemaCXX/cxx0x-cursory-default-delete.cpp +++ test/SemaCXX/cxx0x-cursory-default-delete.cpp @@ -11,6 +11,7 @@ non_const_copy& operator = (non_const_copy&) &; non_const_copy& operator = (non_const_copy&) &&; non_const_copy() = default; // expected-note {{not viable}} + int uninit_field; }; non_const_copy::non_const_copy(non_const_copy&) = default; // expected-note {{not viable}} non_const_copy& non_const_copy::operator = (non_const_copy&) & = default; // expected-note {{not viable}} @@ -30,6 +31,65 @@ ncc = cncc; // expected-error {{no viable overloaded}} }; +struct no_fields { }; +struct all_init { + int a = 0; + int b = 0; +}; +struct some_init { + int a = 0; + int b; + int c = 0; +}; +struct some_init_mutable { + int a = 0; + mutable int b; + int c = 0; +}; +struct some_init_def { + some_init_def() = default; + int a = 0; + int b; + int c = 0; +}; +struct some_init_ctor { + some_init_ctor(); + int a = 0; + int b; + int c = 0; +}; +struct sub_some_init : public some_init_def { }; +struct sub_some_init_ctor : public some_init_def { + sub_some_init_ctor(); +}; +struct sub_some_init_ctor2 : public some_init_ctor { +}; +struct some_init_container { + some_init_def sid; +}; +struct some_init_container_ctor { + some_init_container_ctor(); + some_init_def sid; +}; +struct no_fields_container { + no_fields nf; +}; + +void constobjs() { + const no_fields nf; // ok + const all_init ai; // ok + const some_init si; // expected-error {{default initialization of an object of const type 'const some_init' without a user-provided default constructor}} + const some_init_mutable sim; // ok + const some_init_def sid; // expected-error {{default initialization of an object of const type 'const some_init_def' without a user-provided default constructor}} + const some_init_ctor sic; // ok + const sub_some_init ssi; // expected-error {{default initialization of an object of const type 'const sub_some_init' without a user-provided default constructor}} + const sub_some_init_ctor ssic; // ok + const sub_some_init_ctor2 ssic2; // ok + 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 +} + struct non_const_derived : non_const_copy { non_const_derived(const non_const_derived&) = default; // expected-error {{requires it to be non-const}} non_const_derived& operator =(non_const_derived&) = default; Index: test/SemaCXX/illegal-member-initialization.cpp =================================================================== --- test/SemaCXX/illegal-member-initialization.cpp +++ test/SemaCXX/illegal-member-initialization.cpp @@ -7,6 +7,7 @@ }; struct B { + int field; }; struct X { Index: www/cxx_dr_status.html =================================================================== --- www/cxx_dr_status.html +++ www/cxx_dr_status.html @@ -1308,11 +1308,11 @@ Constructors should not be allowed to return normally after an exception Yes - + 212 - drafting + tentatively ready Implicit instantiation is not described clearly enough - Not resolved + Unknown 213 @@ -3023,7 +3023,7 @@ 497 CD1 Missing required initialization in example - Yes + Superseded by 253 498 @@ -9137,7 +9137,7 @@ 1554 - drafting + open Access and alias templates Not resolved @@ -11043,11 +11043,11 @@ Non-identifier characters in ud-suffix Not resolved - + 1872 - drafting + tentatively ready Instantiations of constexpr templates that cannot appear in constant expressions - Not resolved + Unknown 1873 @@ -11763,11 +11763,11 @@ Inheriting constructors vs default arguments Unknown - + 1992 - drafting + tentatively ready new (std::nothrow) int[N] can throw - Not resolved + Unknown 1993 @@ -11787,11 +11787,11 @@ exception-specifications and non-type template parameters Unknown - - 1996 - + + 1996 + drafting Reference list-initialization ignores conversion functions - Unknown + Not resolved 1997 @@ -12095,7 +12095,7 @@ 2047 - ready + tentatively ready Coordinating “throws anything” specifications Unknown @@ -12195,11 +12195,11 @@ Type/nontype hiding in class scope Unknown - + 2064 - drafting + tentatively ready Conflicting specifications for dependent decltype-specifiers - Not resolved + Unknown 2065 @@ -12435,11 +12435,11 @@ Lvalue-to-rvalue conversion is irrelevant in odr-use of a reference Not resolved - + 2104 - drafting + tentatively ready Internal-linkage constexpr references and ODR requirements - Not resolved + Unknown 2105 @@ -12543,11 +12543,11 @@ More flexible lambda syntax Not resolved - + 2122 - drafting + tentatively ready Glvalues of void type - Not resolved + Unknown 2123 @@ -12585,11 +12585,11 @@ Imprecise rule for reference member initializer Not resolved - + 2129 - drafting + tentatively ready Non-object prvalues and constant expressions - Not resolved + Unknown 2130 @@ -12651,17 +12651,17 @@ Floating-point requirements for integer representation Unknown - + 2140 - drafting + tentatively ready Lvalue-to-rvalue conversion of std::nullptr_t - Not resolved + Unknown - + 2141 - drafting + tentatively ready Ambiguity in new-expression with elaborated-type-specifier - Not resolved + Unknown 2142 @@ -12669,11 +12669,11 @@ Missing definition of associated classes and namespaces Unknown - + 2143 - drafting + tentatively ready Value-dependency via injected-class-name - Not resolved + Unknown 2144 @@ -12687,11 +12687,11 @@ Parenthesized declarator in function definition Not resolved - + 2146 - drafting + tentatively ready Scalar object vs memory location in definition of “unsequenced” - Not resolved + Unknown 2147 @@ -12729,17 +12729,17 @@ Can an alternative token be used as a ud-suffix? Unknown - + 2153 - drafting + tentatively ready pure-specifier in friend declaration - Not resolved + Unknown - + 2154 - drafting + tentatively ready Ambiguity of pure-specifier - Not resolved + Unknown 2155 @@ -12747,11 +12747,11 @@ Defining classes and enumerations via using-declarations Not resolved - + 2156 - drafting + tentatively ready Definition of enumeration declared by using-declaration - Not resolved + Unknown 2157 @@ -12783,17 +12783,17 @@ Explicit instantiation declaration and “preceding initialization” Unknown - + 2162 - drafting + tentatively ready Capturing this by reference - Not resolved + Unknown - + 2163 - drafting + tentatively ready Labels in constexpr functions - Not resolved + Unknown 2164 @@ -12813,11 +12813,11 @@ Unclear meaning of “undefined constexpr function” Not resolved - + 2167 - drafting + tentatively ready Non-member references with lifetimes within the current evaluation - Not resolved + Unknown 2168 @@ -12827,7 +12827,7 @@ 2169 - drafting + open Narrowing conversions and overload resolution Not resolved @@ -12861,17 +12861,17 @@ Unclear rules for friend definitions in templates Not resolved - + 2175 - drafting + tentatively ready Ambiguity with attribute in conversion operator declaration - Not resolved + Unknown - + 2176 - drafting + tentatively ready Destroying the returned object when a destructor throws - Not resolved + Unknown 2177 @@ -12891,11 +12891,11 @@ Required diagnostic for partial specialization after first use Not resolved - + 2180 - drafting + tentatively ready Virtual bases in destructors and defaulted assignment operators - Not resolved + Unknown 2181