r227022 - First steps in implementing DR1467: List-initialization of aggregate from same-type object.
Larisse Voufo
lvoufo at google.com
Sat Jan 24 15:09:54 PST 2015
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) {
+ 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
+
+namespace dr1467 {
+ // 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 {
+ // List-initialization from a string literal
+
+ char s[4]{"abc"}; // Ok
+ std::initializer_list<char>{"abc"}; // expected-error {{expected unqualified-id}}}
+
+} // dr1490
+#endif
More information about the cfe-commits
mailing list