]> granicus.if.org Git - clang/commitdiff
Implement support for conditional between xvalues of reference-compatible
authorRichard Smith <richard-llvm@metafoo.co.uk>
Mon, 25 Apr 2016 19:30:37 +0000 (19:30 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Mon, 25 Apr 2016 19:30:37 +0000 (19:30 +0000)
types. Patch by Erik Pilkington!

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

lib/Sema/SemaExprCXX.cpp
test/SemaCXX/conditional-expr.cpp

index 4c677e33e9760fe3441e27b4984fcd115be1c061..88f2bc798a27ac6c5fe6c3735822bcfe6197fcd9 100644 (file)
@@ -4795,7 +4795,7 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS,
   return Result;
 }
 
-/// \brief Try to convert a type to another according to C++0x 5.16p3.
+/// \brief Try to convert a type to another according to C++11 5.16p3.
 ///
 /// This is part of the parameter validation for the ? operator. If either
 /// value operand is a class type, the two operands are attempted to be
@@ -4811,17 +4811,21 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To,
 
   InitializationKind Kind = InitializationKind::CreateCopy(To->getLocStart(),
                                                            SourceLocation());
-  // C++0x 5.16p3
+  // C++11 5.16p3
   //   The process for determining whether an operand expression E1 of type T1
   //   can be converted to match an operand expression E2 of type T2 is defined
   //   as follows:
-  //   -- If E2 is an lvalue:
-  bool ToIsLvalue = To->isLValue();
-  if (ToIsLvalue) {
-    //   E1 can be converted to match E2 if E1 can be implicitly converted to
-    //   type "lvalue reference to T2", subject to the constraint that in the
-    //   conversion the reference must bind directly to E1.
-    QualType T = Self.Context.getLValueReferenceType(ToType);
+  //   -- If E2 is an lvalue: E1 can be converted to match E2 if E1 can be
+  //      implicitly converted to type "lvalue reference to T2", subject to the
+  //      constraint that in the conversion the reference must bind directly to
+  //      an lvalue.
+  //   -- If E2 is an xvalue: E1 can be converted to match E2 if E1 can be
+  //      implicitly conveted to the type "rvalue reference to R2", subject to
+  //      the constraint that the reference must bind directly.
+  if (To->isLValue() || To->isXValue()) {
+    QualType T = To->isLValue() ? Self.Context.getLValueReferenceType(ToType)
+                                : Self.Context.getRValueReferenceType(ToType);
+
     InitializedEntity Entity = InitializedEntity::InitializeTemporary(T);
 
     InitializationSequence InitSeq(Self, Entity, Kind, From);
index 538de5847de81da75be76e15ac2b253709a8de63..c12efc0be7ef87620d7bff5aeb84aaf60c9326ed 100644 (file)
@@ -384,3 +384,12 @@ namespace PR17052 {
     int &test() { return b_ ? i_ : throw 1; }
   };
 }
+
+namespace PR26448 {
+struct Base {};
+struct Derived : Base {};
+Base b;
+Derived d;
+typedef decltype(true ? static_cast<Base&&>(b) : static_cast<Derived&&>(d)) x;
+typedef Base &&x;
+}