]> granicus.if.org Git - clang/commitdiff
[Sema] Add lvalue-to-rvalue cast in direct-list-initialization of enum
authorVedant Kumar <vsk@apple.com>
Thu, 16 Feb 2017 01:20:00 +0000 (01:20 +0000)
committerVedant Kumar <vsk@apple.com>
Thu, 16 Feb 2017 01:20:00 +0000 (01:20 +0000)
After r264564, we allowed direct-list-initialization of an enum from an
integral value in C++1z mode, so long as that value can convert to the
enum's underlying type.

In this kind of initialization, we need a lvalue-to-rvalue conversion
for the initializer value if it is not a rvalue. This lets us accept the
following code:

  enum class A : unsigned {};
  A foo(unsigned x) { return A{x}; }

Differential Revision: https://reviews.llvm.org/D29723

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@295266 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaInit.cpp
test/CXX/dcl.decl/dcl.init/dcl.init.list/p3.cpp

index a455717c4d60768890fa9794aec3ed23b80e2129..151b974b41094924da88d34f3b2f15efb2408db8 100644 (file)
@@ -3981,6 +3981,8 @@ static void TryListInitialization(Sema &S,
       ImplicitConversionSequence ICS;
       ICS.setStandard();
       ICS.Standard.setAsIdentityConversion();
+      if (!E->isRValue())
+        ICS.Standard.First = ICK_Lvalue_To_Rvalue;
       // 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.
index f381ed708f702ecac152c1905e243042c457b8eb..ade327485773eeba7f74afd60a6eed4a8afdc6ca 100644 (file)
@@ -150,35 +150,44 @@ namespace cxx1z_direct_enum_init {
 
     void f(T);
     f(T{0});
+
+    char c;
+    auto t3 = T{c};
   }
 #if __cplusplus <= 201402L
-  // expected-error@-15 5{{cannot initialize}}
-  // expected-error@-15 5{{cannot initialize}}
-  // expected-error@-15 5{{cannot initialize}}
+  // expected-error@-18 5{{cannot initialize}}
+  // expected-error@-18 5{{cannot initialize}}
+  // expected-error@-18 5{{cannot initialize}}
+  //
   //
+  // expected-error@-18 5{{cannot initialize}}
   //
-  // expected-error@-15 5{{cannot initialize}}
+  // expected-error@-18 5{{cannot initialize}}
   //
-  // expected-error@-15 5{{cannot initialize}}
+  // expected-error@-18 5{{cannot initialize}}
   //
-  // expected-error@-15 5{{cannot initialize}}
   //
+  // expected-error@-18 5{{cannot initialize}}
   //
-  // expected-error@-15 5{{cannot initialize}}
+  //
+  // expected-error@-18 5{{cannot initialize}}
 #else
-  // expected-error@-29 {{cannot initialize}}
-  // expected-error@-29 {{cannot initialize}}
-  // expected-error@-29 {{cannot initialize}}
+  // expected-error@-35 {{cannot initialize}}
+  // expected-error@-35 {{cannot initialize}}
+  // expected-error@-35 {{cannot initialize}}
+  //
   //
+  // expected-error@-35 {{cannot initialize}}
   //
-  // expected-error@-29 {{cannot initialize}}
+  // expected-error@-35 {{cannot initialize}}
   //
-  // expected-error@-29 {{cannot initialize}}
+  // expected-error@-35 {{cannot initialize}}
   //
-  // expected-error@-29 {{cannot initialize}}
   //
+  // expected-error@-35 {{cannot initialize}}
   //
-  // expected-error@-29 {{cannot initialize}}
+  //
+  // expected-error@-35 {{cannot initialize}}
 #endif
 
   template<typename T> void bad() {
@@ -252,4 +261,12 @@ namespace cxx1z_direct_enum_init {
     (void)B{0.0}; // expected-error {{type 'double' cannot be narrowed}}
 #endif
   }
+
+#if __cplusplus > 201402L
+  enum class F : unsigned {};
+  F f1(unsigned x) { return F{x}; }
+  F f2(const unsigned x) { return F{x}; }
+  F f3(bool x) { return F{x}; }
+  F f4(const bool x) { return F{x}; }
+#endif
 }