These should all be addressed by r227224.
On Mon, Jan 26, 2015 at 6:50 PM, Larisse Voufo <[email protected]> wrote: > > > On Mon, Jan 26, 2015 at 11:31 AM, Richard Smith <[email protected]> > wrote: > >> On Sat, Jan 24, 2015 at 3:09 PM, Larisse Voufo <[email protected]> wrote: >> > Author: lvoufo >> > Date: Sat Jan 24 17:09:54 2015 >> > New Revision: 227022 >> > >> > URL: http://llvm.org/viewvc/llvm-project?rev=227022&view=rev >> > Log: >> > First steps in implementing DR1467: List-initialization of aggregate >> from same-type object. >> > Only the first two items for now, changing Sections 8.5.4 >> [dcl.init.list] paragraph 3 and 13.3.1.7 [over.match.list] paragraph 1, >> > so that defining class objects and character arrays using uniform >> initialization syntax is actually treated as list initialization >> > and before it is treated aggregate initialization. >> > >> > Modified: >> > cfe/trunk/lib/Sema/SemaInit.cpp >> > cfe/trunk/test/CXX/drs/dr14xx.cpp >> > >> > Modified: cfe/trunk/lib/Sema/SemaInit.cpp >> > URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=227022&r1=227021&r2=227022&view=diff >> > >> ============================================================================== >> > --- cfe/trunk/lib/Sema/SemaInit.cpp (original) >> > +++ cfe/trunk/lib/Sema/SemaInit.cpp Sat Jan 24 17:09:54 2015 >> > @@ -3222,9 +3222,16 @@ static void TryConstructorInitialization >> > OverloadCandidateSet::iterator Best; >> > bool AsInitializerList = false; >> > >> > + // C++14 DR 1467 [over.match.list]p1: >> > + // When objects of non-aggregate type T are list-initialized, such >> that >> > + // 8.5.4 [dcl.init.list] specifies that overload resolution is >> performed >> > + // according to the rules in this section, overload resolution >> selects >> > + // the constructor in two phases: >> > + // >> > // C++11 [over.match.list]p1: >> > // When objects of non-aggregate type T are list-initialized, >> overload >> > // resolution selects the constructor in two phases: >> > + // >> > // - Initially, the candidate functions are the initializer-list >> > // constructors of the class T and the argument list consists of >> the >> > // initializer list as a single argument. >> > @@ -3425,42 +3432,88 @@ static void TryListInitialization(Sema & >> > TryReferenceListInitialization(S, Entity, Kind, InitList, >> Sequence); >> > return; >> > } >> > - if (DestType->isRecordType()) { >> > - if (S.RequireCompleteType(InitList->getLocStart(), DestType, 0)) { >> > - Sequence.setIncompleteTypeFailure(DestType); >> > - return; >> > - } >> > >> > - // C++11 [dcl.init.list]p3: >> > - // - If T is an aggregate, aggregate initialization is performed. >> > - if (!DestType->isAggregateType()) { >> > - if (S.getLangOpts().CPlusPlus11) { >> > - // - Otherwise, if the initializer list has no elements and >> T is a >> > - // class type with a default constructor, the object is >> > - // value-initialized. >> > - if (InitList->getNumInits() == 0) { >> > - CXXRecordDecl *RD = DestType->getAsCXXRecordDecl(); >> > - if (RD->hasDefaultConstructor()) { >> > - TryValueInitialization(S, Entity, Kind, Sequence, >> InitList); >> > - return; >> > - } >> > - } >> > - >> > - // - Otherwise, if T is a specialization of >> std::initializer_list<E>, >> > - // an initializer_list object constructed [...] >> > - if (TryInitializerListConstruction(S, InitList, DestType, >> Sequence)) >> > - return; >> > + if (DestType->isRecordType() && >> > + S.RequireCompleteType(InitList->getLocStart(), DestType, 0)) { >> > + Sequence.setIncompleteTypeFailure(DestType); >> > + return; >> > + } >> > >> > - // - Otherwise, if T is a class type, constructors are >> considered. >> > + // C++14 DR1467 [dcl.init.list]p3: >> > + // - If T is a class type and the initializer list has a single >> element of >> > + // type cv U, where U is T or a class derived from T, the object is >> > + // initialized from that element (by copy-initialization for >> > + // copy-list-initialization, or by direct-initialization for >> > + // direct-list-initialization). >> > + // - Otherwise, if T is a character array and the initializer list >> has a >> > + // single element that is an appropriately-typed string literal >> > + // (8.5.2 [dcl.init.string]), initialization is performed as >> described >> > + // in that section. >> > + // - Otherwise, If T is an aggregate, [...] (continue below). >> > + if (S.getLangOpts().CPlusPlus14 && InitList->getNumInits() == 1) { >> >> This issue is in DR status, so should be applied retroactively to all >> standard revisions where it makes sense. In this case, that means it >> should apply to C++11 mode as well as C++14 mode. >> > > Ok. > >> >> > + if (DestType->isRecordType()) { >> > + QualType InitType = InitList->getInit(0)->getType(); >> > + if (S.Context.hasSameUnqualifiedType(InitType, DestType) || >> > + S.IsDerivedFrom(InitType, DestType)) { >> > Expr *InitListAsExpr = InitList; >> > TryConstructorInitialization(S, Entity, Kind, InitListAsExpr, >> DestType, >> > Sequence, /*InitListSyntax*/true); >> > - } else >> > - Sequence.SetFailed( >> > - InitializationSequence::FK_InitListBadDestinationType); >> > - return; >> > + return; >> > + } >> > + } >> > + if (const ArrayType *DestAT = S.Context.getAsArrayType(DestType)) { >> > + Expr *SubInit[1] = {InitList->getInit(0)}; >> > + if (!isa<VariableArrayType>(DestAT) && >> > + IsStringInit(SubInit[0], DestAT, S.Context) == SIF_None) { >> > + InitializationKind SubKind = >> > + Kind.getKind() == InitializationKind::IK_DirectList >> > + ? InitializationKind::CreateDirect(Kind.getLocation(), >> > + >> InitList->getLBraceLoc(), >> > + >> InitList->getRBraceLoc()) >> > + : Kind; >> > + Sequence.InitializeFrom(S, Entity, SubKind, SubInit, >> > + /*TopLevelOfInitList*/ true); >> > + >> > + // TryStringLiteralInitialization() (in InitializeFrom()) will >> fail if >> > + // the element is not an appropriately-typed string literal, >> in which >> > + // case we should proceed as in C++11 (below). >> > + if (Sequence) { >> > + Sequence.RewrapReferenceInitList(Entity.getType(), InitList); >> > + return; >> > + } >> > + } >> > } >> > } >> > + >> > + // C++11 [dcl.init.list]p3: >> > + // - If T is an aggregate, aggregate initialization is performed. >> > + if (DestType->isRecordType() && !DestType->isAggregateType()) { >> > + if (S.getLangOpts().CPlusPlus11) { >> > + // - Otherwise, if the initializer list has no elements and T >> is a >> > + // class type with a default constructor, the object is >> > + // value-initialized. >> > + if (InitList->getNumInits() == 0) { >> > + CXXRecordDecl *RD = DestType->getAsCXXRecordDecl(); >> > + if (RD->hasDefaultConstructor()) { >> > + TryValueInitialization(S, Entity, Kind, Sequence, InitList); >> > + return; >> > + } >> > + } >> > + >> > + // - Otherwise, if T is a specialization of >> std::initializer_list<E>, >> > + // an initializer_list object constructed [...] >> > + if (TryInitializerListConstruction(S, InitList, DestType, >> Sequence)) >> > + return; >> > + >> > + // - Otherwise, if T is a class type, constructors are >> considered. >> > + Expr *InitListAsExpr = InitList; >> > + TryConstructorInitialization(S, Entity, Kind, InitListAsExpr, >> DestType, >> > + Sequence, /*InitListSyntax*/ true); >> > + } else >> > + >> Sequence.SetFailed(InitializationSequence::FK_InitListBadDestinationType); >> > + return; >> > + } >> > + >> > if (S.getLangOpts().CPlusPlus && !DestType->isAggregateType() && >> > InitList->getNumInits() == 1 && >> > InitList->getInit(0)->getType()->isRecordType()) { >> > @@ -3469,6 +3522,14 @@ static void TryListInitialization(Sema & >> > // initialized from that element; if a narrowing conversion is >> required >> > // to convert the element to T, the program is ill-formed. >> > // >> > + // C++14 DR1467: >> > + // - Otherwise, if the initializer list has a single element of >> type E >> > + // [...references are handled above...], the object or >> reference is >> > + // initialized from that element (by copy-initialization for >> > + // copy-list-initialization, or by direct-initialization for >> > + // direct-list-initialization); if a narrowing conversion is >> required >> > + // to convert the element to T, the program is ill-formed. >> > + // >> > // Per core-24034, this is direct-initialization if we were >> performing >> > // direct-list-initialization and copy-initialization otherwise. >> > // We can't use InitListChecker for this, because it always >> performs >> > @@ -4408,8 +4469,7 @@ static void checkIndirectCopyRestoreSour >> > >> > /// \brief Determine whether we have compatible array types for the >> > /// purposes of GNU by-copy array initialization. >> > -static bool hasCompatibleArrayTypes(ASTContext &Context, >> > - const ArrayType *Dest, >> > +static bool hasCompatibleArrayTypes(ASTContext &Context, const >> ArrayType *Dest, >> > const ArrayType *Source) { >> > // If the source and destination array types are equivalent, we're >> > // done. >> > @@ -4668,7 +4728,7 @@ void InitializationSequence::InitializeF >> > return; >> > } >> > >> > - // Determine whether we should consider writeback conversions for >> > + // Determine whether we should consider writeback conversions for >> > // Objective-C ARC. >> > bool allowObjCWritebackConversion = S.getLangOpts().ObjCAutoRefCount >> && >> > Entity.isParameterKind(); >> > >> > Modified: cfe/trunk/test/CXX/drs/dr14xx.cpp >> > URL: >> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr14xx.cpp?rev=227022&r1=227021&r2=227022&view=diff >> > >> ============================================================================== >> > --- cfe/trunk/test/CXX/drs/dr14xx.cpp (original) >> > +++ cfe/trunk/test/CXX/drs/dr14xx.cpp Sat Jan 24 17:09:54 2015 >> > @@ -195,3 +195,126 @@ namespace dr1460 { // dr1460: 3.5 >> > } >> > #endif >> > } >> > + >> > +#if __cplusplus >= 201103L >> > +namespace std { >> > + typedef decltype(sizeof(int)) size_t; >> > + >> > + // libc++'s implementation >> > + template <class _E> >> > + class initializer_list >> > + { >> > + const _E* __begin_; >> > + size_t __size_; >> > + >> > + initializer_list(const _E* __b, size_t __s) >> > + : __begin_(__b), >> > + __size_(__s) >> > + {} >> > + >> > + public: >> > + typedef _E value_type; >> > + typedef const _E& reference; >> > + typedef const _E& const_reference; >> > + typedef size_t size_type; >> > + >> > + typedef const _E* iterator; >> > + typedef const _E* const_iterator; >> > + >> > + initializer_list() : __begin_(nullptr), __size_(0) {} >> > + >> > + size_t size() const {return __size_;} >> > + const _E* begin() const {return __begin_;} >> > + const _E* end() const {return __begin_ + __size_;} >> > + }; >> > +} // std >> >> Please put this at the top of the file. >> >> > + >> > +namespace dr1467 { >> >> This should be marked as " // dr1467: partial c++11" to indicate that >> we have partial support for this in trunk, for C++11 onwards. We have >> a script (www/make_cxx_dr_status) that automatically generates the >> cxx_dr_status page from these comments. >> > > Ok. > >> >> > + // List-initialization of aggregate from same-type object >> > + >> > + namespace basic0 { >> > + >> > + struct S { >> > + int i = 42; >> > + }; >> > + >> > + S a; >> > + S b(a); >> > + S c{a}; >> > + >> > + struct SS : public S { } x; >> > + S y(x); >> > + S z{x}; >> > + >> > + } // basic0 >> > + >> > + namespace basic1 { >> > + >> > + struct S { >> > + int i{42}; >> > + }; >> > + >> > + S a; >> > + S b(a); >> > + S c{a}; >> > + >> > + struct SS : public S { } x; >> > + S y(x); >> > + S z{x}; >> > + >> > + } // basic1 >> > + >> > + namespace basic2 { >> > + >> > + struct S { >> > + int i = {42}; >> > + }; >> > + >> > + S a; >> > + S b(a); >> > + S c{a}; >> > + >> > + struct SS : public S { } x; >> > + S y(x); >> > + S z{x}; >> > + >> > + } // basic2 >> > + >> > + namespace dr_example { >> > + struct OK { >> > + OK() = default; >> > + OK(const OK&) = default; >> > + OK(int) { } >> > + }; >> > + >> > + OK ok; >> > + OK ok2{ok}; >> > + >> > + >> > + struct X { >> > + X() = default; >> > + X(const X&) = default; >> > + }; >> > + >> > + X x; >> > + X x2{x}; >> > +#if __cplusplus == 201103L >> > + // expected-error@-2 {{excess elements in struct initializer}} >> > +#endif >> > + >> > + // TODO: Only Items 1 and 2 from DR1467 are covered for now. >> > + // Implement remaining items, and expand here as necessary. >> > + >> > + } // dr_example >> > + >> > +} // dr1467 >> > + >> > + >> > +namespace dr1490 { >> >> This should be marked "// dr1490: dup 1467". >> >> > + // List-initialization from a string literal >> > + >> > + char s[4]{"abc"}; // Ok >> > + std::initializer_list<char>{"abc"}; // expected-error {{expected >> unqualified-id}}} >> > + >> > +} // dr1490 >> > +#endif >> >> Can you add tests for dr1756, 1758, 1631 and 1589 (all resolved by >> 1467) too, please? >> > > I am still working on these cases. This patch does not handle those yet. > >
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
