erik.pilkington created this revision. erik.pilkington added a reviewer: rsmith. erik.pilkington added a subscriber: cfe-commits.
Previously, when the 2 expressions passed to a ternary operator were xvalues and one inherits from the other, the resulting expression had type 'T', not 'T&&' as 5.16p3 dictates. For example: ` Base b; Derived d; typedef decltype(true ? static_cast<Base&&>(b) : static_cast<Derived&&>(d)) x; // x has type Base, not Base&&` PR: https://llvm.org/bugs/show_bug.cgi?id=26448 http://reviews.llvm.org/D17451 Files: lib/Sema/SemaExprCXX.cpp test/SemaCXX/conditional-expr.cpp Index: test/SemaCXX/conditional-expr.cpp =================================================================== --- test/SemaCXX/conditional-expr.cpp +++ test/SemaCXX/conditional-expr.cpp @@ -384,3 +384,12 @@ 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; +} Index: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -4671,7 +4671,7 @@ 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 @@ -4687,17 +4687,21 @@ 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 + // E1. + // -- 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: test/SemaCXX/conditional-expr.cpp =================================================================== --- test/SemaCXX/conditional-expr.cpp +++ test/SemaCXX/conditional-expr.cpp @@ -384,3 +384,12 @@ 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; +} Index: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -4671,7 +4671,7 @@ 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 @@ -4687,17 +4687,21 @@ 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 + // E1. + // -- 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);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits