I made the test pass in r264642 with a triple. We should deal with this properly at some point, though.
On Sun, Mar 27, 2016 at 11:08 PM, Richard Smith via cfe-commits < cfe-commits@lists.llvm.org> wrote: > Author: rsmith > Date: Mon Mar 28 01:08:37 2016 > New Revision: 264564 > > URL: http://llvm.org/viewvc/llvm-project?rev=264564&view=rev > Log: > P0138R2: Allow direct-list-initialization of an enumeration from an > integral > value that can convert to the enum's underlying type. > > Added: > cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3.cpp > - copied, changed from r264563, > cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3-0x.cpp > Removed: > cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3-0x.cpp > Modified: > cfe/trunk/lib/Sema/SemaInit.cpp > cfe/trunk/lib/Sema/SemaOverload.cpp > cfe/trunk/www/cxx_status.html > > Modified: cfe/trunk/lib/Sema/SemaInit.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=264564&r1=264563&r2=264564&view=diff > > ============================================================================== > --- cfe/trunk/lib/Sema/SemaInit.cpp (original) > +++ cfe/trunk/lib/Sema/SemaInit.cpp Mon Mar 28 01:08:37 2016 > @@ -3862,8 +3862,48 @@ static void TryListInitialization(Sema & > } > > if (S.getLangOpts().CPlusPlus && !DestType->isAggregateType() && > - InitList->getNumInits() == 1 && > - InitList->getInit(0)->getType()->isRecordType()) { > + InitList->getNumInits() == 1) { > + Expr *E = InitList->getInit(0); > + > + // - Otherwise, if T is an enumeration with a fixed underlying type, > + // the initializer-list has a single element v, and the > initialization > + // is direct-list-initialization, the object is initialized with > the > + // value T(v); if a narrowing conversion is required to convert v > to > + // the underlying type of T, the program is ill-formed. > + auto *ET = DestType->getAs<EnumType>(); > + if (S.getLangOpts().CPlusPlus1z && > + Kind.getKind() == InitializationKind::IK_DirectList && > + ET && ET->getDecl()->isFixed() && > + !S.Context.hasSameUnqualifiedType(E->getType(), DestType) && > + (E->getType()->isIntegralOrEnumerationType() || > + E->getType()->isFloatingType())) { > + // There are two ways that T(v) can work when T is an enumeration > type. > + // If there is either an implicit conversion sequence from v to T or > + // a conversion function that can convert from v to T, then we use > that. > + // Otherwise, if v is of integral, enumeration, or floating-point > type, > + // it is converted to the enumeration type via its underlying type. > + // There is no overlap possible between these two cases (except > when the > + // source value is already of the destination type), and the first > + // case is handled by the general case for single-element lists > below. > + ImplicitConversionSequence ICS; > + ICS.setStandard(); > + ICS.Standard.setAsIdentityConversion(); > + // If E is of a floating-point type, then the conversion is > ill-formed > + // due to narrowing, but go through the motions in order to produce > the > + // right diagnostic. > + ICS.Standard.Second = E->getType()->isFloatingType() > + ? ICK_Floating_Integral > + : ICK_Integral_Conversion; > + ICS.Standard.setFromType(E->getType()); > + ICS.Standard.setToType(0, E->getType()); > + ICS.Standard.setToType(1, DestType); > + ICS.Standard.setToType(2, DestType); > + Sequence.AddConversionSequenceStep(ICS, ICS.Standard.getToType(2), > + /*TopLevelOfInitList*/true); > + Sequence.RewrapReferenceInitList(Entity.getType(), InitList); > + return; > + } > + > // - 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 > @@ -3877,19 +3917,21 @@ static void TryListInitialization(Sema & > // copy-initialization. This only matters if we might use an > 'explicit' > // conversion operator, so we only need to handle the cases where the > source > // is of record type. > - InitializationKind SubKind = > - Kind.getKind() == InitializationKind::IK_DirectList > - ? InitializationKind::CreateDirect(Kind.getLocation(), > - InitList->getLBraceLoc(), > - InitList->getRBraceLoc()) > - : Kind; > - Expr *SubInit[1] = { InitList->getInit(0) }; > - Sequence.InitializeFrom(S, Entity, SubKind, SubInit, > - /*TopLevelOfInitList*/true, > - TreatUnavailableAsInvalid); > - if (Sequence) > - Sequence.RewrapReferenceInitList(Entity.getType(), InitList); > - return; > + if (InitList->getInit(0)->getType()->isRecordType()) { > + InitializationKind SubKind = > + Kind.getKind() == InitializationKind::IK_DirectList > + ? InitializationKind::CreateDirect(Kind.getLocation(), > + InitList->getLBraceLoc(), > + InitList->getRBraceLoc()) > + : Kind; > + Expr *SubInit[1] = { InitList->getInit(0) }; > + Sequence.InitializeFrom(S, Entity, SubKind, SubInit, > + /*TopLevelOfInitList*/true, > + TreatUnavailableAsInvalid); > + if (Sequence) > + Sequence.RewrapReferenceInitList(Entity.getType(), InitList); > + return; > + } > } > > InitListChecker CheckInitList(S, Entity, InitList, > > Modified: cfe/trunk/lib/Sema/SemaOverload.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=264564&r1=264563&r2=264564&view=diff > > ============================================================================== > --- cfe/trunk/lib/Sema/SemaOverload.cpp (original) > +++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon Mar 28 01:08:37 2016 > @@ -293,6 +293,13 @@ StandardConversionSequence::getNarrowing > // A narrowing conversion is an implicit conversion ... > QualType FromType = getToType(0); > QualType ToType = getToType(1); > + > + // A conversion to an enumeration type is narrowing if the conversion to > + // the underlying type is narrowing. This only arises for expressions of > + // the form 'Enum{init}'. > + if (auto *ET = ToType->getAs<EnumType>()) > + ToType = ET->getDecl()->getIntegerType(); > + > switch (Second) { > // 'bool' is an integral type; dispatch to the right place to handle it. > case ICK_Boolean_Conversion: > > Removed: cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3-0x.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3-0x.cpp?rev=264563&view=auto > > ============================================================================== > --- cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3-0x.cpp (original) > +++ cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3-0x.cpp (removed) > @@ -1,127 +0,0 @@ > -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s > - > -namespace std { > - typedef decltype(sizeof(int)) size_t; > - > - template <typename E> > - struct initializer_list > - { > - const E *p; > - size_t n; > - initializer_list(const E *p, size_t n) : p(p), n(n) {} > - }; > - > - struct string { > - string(const char *); > - }; > - > - template<typename A, typename B> > - struct pair { > - pair(const A&, const B&); > - }; > -} > - > -namespace bullet1 { > - double ad[] = { 1, 2.0 }; > - int ai[] = { 1, 2.0 }; // expected-error {{type 'double' cannot be > narrowed to 'int' in initializer list}} expected-note {{silence}} > - > - struct S2 { > - int m1; > - double m2, m3; > - }; > - > - S2 s21 = { 1, 2, 3.0 }; > - S2 s22 { 1.0, 2, 3 }; // expected-error {{type 'double' cannot be > narrowed to 'int' in initializer list}} expected-note {{silence}} > - S2 s23 { }; > -} > - > -namespace bullet4_example1 { > - struct S { > - S(std::initializer_list<double> d) {} > - S(std::initializer_list<int> i) {} > - S() {} > - }; > - > - S s1 = { 1.0, 2.0, 3.0 }; > - S s2 = { 1, 2, 3 }; > - S s3 = { }; > -} > - > -namespace bullet4_example2 { > - struct Map { > - Map(std::initializer_list<std::pair<std::string,int>>) {} > - }; > - > - Map ship = {{"Sophie",14}, {"Surprise",28}}; > -} > - > -namespace bullet4_example3 { > - struct S { > - S(int, double, double) {} > - S() {} > - }; > - > - S s1 = { 1, 2, 3.0 }; > - S s2 { 1.0, 2, 3 }; // expected-error {{type 'double' cannot be > narrowed to 'int' in initializer list}} expected-note {{silence}} > - S s3 {}; > -} > - > -namespace bullet5 { > - int x1 {2}; > - int x2 {2.0}; // expected-error {{type 'double' cannot be narrowed to > 'int' in initializer list}} expected-note {{silence}} > -} > - > -namespace bullet6 { > - struct S { > - S(std::initializer_list<double>) {} > - S(const std::string &) {} > - }; > - > - const S& r1 = { 1, 2, 3.0 }; > - const S& r2 = { "Spinach" }; > - S& r3 = { 1, 2, 3 }; // expected-error {{non-const lvalue reference to > type 'bullet6::S' cannot bind to an initializer list temporary}} > - const int& i1 = { 1 }; > - const int& i2 = { 1.1 }; // expected-error {{type 'double' cannot be > narrowed to 'int' in initializer list}} expected-note {{silence}} > expected-warning {{implicit conversion}} > - const int (&iar)[2] = { 1, 2 }; > -} > - > -namespace bullet7 { > - int** pp {}; > -} > - > -namespace bullet8 { > - struct A { int i; int j; }; > - A a1 { 1, 2 }; > - A a2 { 1.2 }; // expected-error {{type 'double' cannot be narrowed to > 'int' in initializer list}} expected-note {{silence}} expected-warning > {{implicit conversion}} > - > - struct B { > - B(std::initializer_list<int> i) {} > - }; > - B b1 { 1, 2 }; > - B b2 { 1, 2.0 }; // expected-error {{type 'double' cannot be narrowed > to 'int' in initializer list}} expected-note {{silence}} > - > - struct C { > - C(int i, double j) {} > - }; > - C c1 = { 1, 2.2 }; > - // FIXME: Suppress the narrowing warning in the cases where we issue a > narrowing error. > - C c2 = { 1.1, 2 }; // expected-error {{type 'double' cannot be narrowed > to 'int' in initializer list}} expected-note {{silence}} expected-warning > {{implicit conversion}} > - > - int j { 1 }; > - int k { }; > -} > - > -namespace rdar13395022 { > - struct MoveOnly { // expected-note {{candidate}} > - MoveOnly(MoveOnly&&); // expected-note 2{{copy constructor is > implicitly deleted because}} expected-note {{candidate}} > - }; > - > - void test(MoveOnly mo) { > - auto &&list1 = {mo}; // expected-error {{call to implicitly-deleted > copy constructor}} expected-note {{in initialization of temporary of type > 'std::initializer_list}} > - MoveOnly (&&list2)[1] = {mo}; // expected-error {{call to > implicitly-deleted copy constructor}} expected-note {{in initialization of > temporary of type 'rdar13395022::MoveOnly [1]'}} > - std::initializer_list<MoveOnly> &&list3 = {}; > - MoveOnly (&&list4)[1] = {}; // expected-error {{no matching > constructor}} > - // expected-note@-1 {{in implicit initialization of array element 0 > with omitted initializer}} > - // expected-note@-2 {{in initialization of temporary of type > 'rdar13395022::MoveOnly [1]' created to list-initialize this reference}} > - } > -} > > Copied: cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3.cpp (from > r264563, cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3-0x.cpp) > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3.cpp?p2=cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3.cpp&p1=cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3-0x.cpp&r1=264563&r2=264564&rev=264564&view=diff > > ============================================================================== > --- cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3-0x.cpp (original) > +++ cfe/trunk/test/CXX/dcl.decl/dcl.init/dcl.init.list/p3.cpp Mon Mar 28 > 01:08:37 2016 > @@ -1,4 +1,6 @@ > // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s > +// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s > +// RUN: %clang_cc1 -std=c++1z -fsyntax-only -verify %s > > namespace std { > typedef decltype(sizeof(int)) size_t; > @@ -125,3 +127,128 @@ namespace rdar13395022 { > // expected-note@-2 {{in initialization of temporary of type > 'rdar13395022::MoveOnly [1]' created to list-initialize this reference}} > } > } > + > +namespace cxx1z_direct_enum_init { > + enum A {}; > + enum B : char {}; > + enum class C {}; > + enum class D : char {}; > + enum class E : char { k = 5 }; > + > + template<typename T> void good() { > + (void)T{0}; > + T t1{0}; > + T t2 = T{0}; > + > + struct S { T t; }; > + S s{T{0}}; > + > + struct U { T t{0}; } u; // expected-note 0+{{instantiation of}} > + > + struct V { T t; V() : t{0} {} }; // expected-note 0+{{instantiation > of}} > + > + void f(T); > + f(T{0}); > + } > +#if __cplusplus <= 201402L > + // expected-error@-15 5{{cannot initialize}} > + // expected-error@-15 5{{cannot initialize}} > + // expected-error@-15 5{{cannot initialize}} > + // > + // > + // expected-error@-15 5{{cannot initialize}} > + // > + // expected-error@-15 5{{cannot initialize}} > + // > + // expected-error@-15 5{{cannot initialize}} > + // > + // > + // expected-error@-15 5{{cannot initialize}} > +#else > + // expected-error@-29 {{cannot initialize}} > + // expected-error@-29 {{cannot initialize}} > + // expected-error@-29 {{cannot initialize}} > + // > + // > + // expected-error@-29 {{cannot initialize}} > + // > + // expected-error@-29 {{cannot initialize}} > + // > + // expected-error@-29 {{cannot initialize}} > + // > + // > + // expected-error@-29 {{cannot initialize}} > +#endif > + > + template<typename T> void bad() { > + T t = {0}; > + > + struct S { T t; }; > + S s1{0}; > + S s2{{0}}; > + > + struct U { T t = {0}; } u; // expected-note 0+{{instantiation of}} > + > + struct V { T t; V() : t({0}) {} }; // expected-note 0+{{instantiation > of}} > + > + void f(T); // expected-note 0+{{passing argument}} > + f({0}); > + } > + // expected-error@-13 5{{cannot initialize}} > + // > + // > + // expected-error@-13 5{{cannot initialize}} > + // expected-error@-13 5{{cannot initialize}} > + // > + // expected-error@-13 5{{cannot initialize}} > + // > + // expected-error@-13 5{{cannot initialize}} > + // > + // > + // expected-error@-13 5{{cannot initialize}} > + > + template<typename T> void ugly() { > + extern char c; > + T t1{char('0' + c)}; > + T t2{'0' + c}; > + T t3{1234}; > + } > +#if __cplusplus <= 201402L > + // expected-error@-5 4{{cannot initialize}} > + // expected-error@-5 4{{cannot initialize}} > + // expected-error@-5 4{{cannot initialize}} > +#else > + // expected-error@-8 3{{non-constant-expression cannot be narrowed}} > + // expected-error@-8 3{{constant expression evaluates to 1234 which > cannot be narrowed}} expected-warning@-8 {{changes value}} > +#endif > + > + void test() { > + good<A>(); // expected-note 4{{instantiation of}} > + good<B>(); > + good<C>(); > + good<D>(); > + good<E>(); > +#if __cplusplus <= 201402L > + // expected-note@-5 4{{instantiation of}} > + // expected-note@-5 4{{instantiation of}} > + // expected-note@-5 4{{instantiation of}} > + // expected-note@-5 4{{instantiation of}} > +#endif > + > + bad<A>(); // expected-note 4{{instantiation of}} > + bad<B>(); // expected-note 4{{instantiation of}} > + bad<C>(); // expected-note 4{{instantiation of}} > + bad<D>(); // expected-note 4{{instantiation of}} > + bad<E>(); // expected-note 4{{instantiation of}} > + > + ugly<B>(); // expected-note {{instantiation of}} > + ugly<C>(); // ok > + ugly<D>(); // expected-note {{instantiation of}} > + ugly<E>(); // expected-note {{instantiation of}} > +#if __cplusplus <= 201402L > + // expected-note@-4 {{instantiation of}} > +#else > + (void)B{0.0}; // expected-error {{type 'double' cannot be narrowed}} > +#endif > + } > +} > > Modified: cfe/trunk/www/cxx_status.html > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=264564&r1=264563&r2=264564&view=diff > > ============================================================================== > --- cfe/trunk/www/cxx_status.html (original) > +++ cfe/trunk/www/cxx_status.html Mon Mar 28 01:08:37 2016 > @@ -664,7 +664,7 @@ as the draft C++1z standard evolves.</p> > <tr> > <td>Direct-list-initialization of <tt>enum</tt>s</td> > <td><a href="http://wg21.link/p0138r2">P0138R2</a></td> > - <td class="none" align="center">No</td> > + <td class="svn" align="center">SVN</td> > </tr> > <tr> > <td>Hexadecimal floating-point literals</td> > > > _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits