r227022 - First steps in implementing DR1467: List-initialization of aggregate from same-type object.
Larisse Voufo
lvoufo at google.com
Mon Jan 26 18:50:24 PST 2015
On Mon, Jan 26, 2015 at 11:31 AM, Richard Smith <richard at metafoo.co.uk>
wrote:
> On Sat, Jan 24, 2015 at 3:09 PM, Larisse Voufo <lvoufo at google.com> 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 at -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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20150126/52462f8b/attachment.html>
More information about the cfe-commits
mailing list