r227022 - First steps in implementing DR1467: List-initialization of aggregate from same-type object.

Larisse Voufo lvoufo at google.com
Tue Jan 27 10:56:36 PST 2015


These should all be addressed by r227224.



On Mon, Jan 26, 2015 at 6:50 PM, Larisse Voufo <lvoufo at google.com> wrote:

>
>
> 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/20150127/65b4f926/attachment.html>


More information about the cfe-commits mailing list