aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaExprCXX.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-08-08 06:13:49 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-08-08 06:13:49 +0000
commit50d61c8ccfc633b13cdf594ea3cd3a217076debe (patch)
treef63370170c819067707d15dba92ee4c14362c712 /lib/Sema/SemaExprCXX.cpp
parent9a58584bb13d725ecb1ac70ce91c6ac52daa9484 (diff)
Implement final piece of DR963 and also DR587:
A conditional operator between glvalues of types cv1 T and cv2 T produces a glvalue if the expressions are of the same value kind and one of cv1 and cv2 is a subset of the other. A conditional operator between two null pointer constants is permitted if one of them is of type std::nullptr_t. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161476 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExprCXX.cpp')
-rw-r--r--lib/Sema/SemaExprCXX.cpp87
1 files changed, 60 insertions, 27 deletions
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 64a12a2039..37450e24c0 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -4100,8 +4100,9 @@ static bool ConvertForConditional(Sema &Self, ExprResult &E, QualType T) {
///
/// See C++ [expr.cond]. Note that LHS is never null, even for the GNU x ?: y
/// extension. In this case, LHS == Cond. (But they're not aliases.)
-QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, ExprResult &RHS,
- ExprValueKind &VK, ExprObjectKind &OK,
+QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
+ ExprResult &RHS, ExprValueKind &VK,
+ ExprObjectKind &OK,
SourceLocation QuestionLoc) {
// FIXME: Handle C99's complex types, vector types, block pointers and Obj-C++
// interface pointers.
@@ -4177,14 +4178,10 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, Ex
// Neither is void.
- // C++0x 5.16p3
+ // C++11 [expr.cond]p3
// Otherwise, if the second and third operand have different types, and
- // either has (cv) class type, and attempt is made to convert each of those
- // operands to the other.
- //
- // FIXME: In C++11, if both operands have the same value category and the same
- // type except for cv-qualification, the types are unified. This is valid:
- // volatile int a; int b; volatile int &c = x ? a : b;
+ // either has (cv) class type [...] an attempt is made to convert each of
+ // those operands to the type of the other.
if (!Context.hasSameType(LTy, RTy) &&
(LTy->isRecordType() || RTy->isRecordType())) {
ImplicitConversionSequence ICSLeftToRight, ICSRightToLeft;
@@ -4217,7 +4214,31 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, Ex
}
}
- // C++0x 5.16p4
+ // C++11 [expr.cond]p3
+ // if both are glvalues of the same value category and the same type except
+ // for cv-qualification, an attempt is made to convert each of those
+ // operands to the type of the other.
+ ExprValueKind LVK = LHS.get()->getValueKind();
+ ExprValueKind RVK = RHS.get()->getValueKind();
+ if (!Context.hasSameType(LTy, RTy) &&
+ Context.hasSameUnqualifiedType(LTy, RTy) &&
+ LVK == RVK && LVK != VK_RValue) {
+ // Since the unqualified types are reference-related and we require the
+ // result to be as if a reference bound directly, the only conversion
+ // we can perform is to add cv-qualifiers.
+ Qualifiers LCVR = Qualifiers::fromCVRMask(LTy.getCVRQualifiers());
+ Qualifiers RCVR = Qualifiers::fromCVRMask(RTy.getCVRQualifiers());
+ if (RCVR.isStrictSupersetOf(LCVR)) {
+ LHS = ImpCastExprToType(LHS.take(), RTy, CK_NoOp, LVK);
+ LTy = LHS.get()->getType();
+ }
+ else if (LCVR.isStrictSupersetOf(RCVR)) {
+ RHS = ImpCastExprToType(RHS.take(), LTy, CK_NoOp, RVK);
+ RTy = RHS.get()->getType();
+ }
+ }
+
+ // C++11 [expr.cond]p4
// If the second and third operands are glvalues of the same value
// category and have the same type, the result is of that type and
// value category and it is a bit-field if the second or the third
@@ -4225,9 +4246,7 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, Ex
// We only extend this to bitfields, not to the crazy other kinds of
// l-values.
bool Same = Context.hasSameType(LTy, RTy);
- if (Same &&
- LHS.get()->isGLValue() &&
- LHS.get()->getValueKind() == RHS.get()->getValueKind() &&
+ if (Same && LVK == RVK && LVK != VK_RValue &&
LHS.get()->isOrdinaryOrBitFieldObject() &&
RHS.get()->isOrdinaryOrBitFieldObject()) {
VK = LHS.get()->getValueKind();
@@ -4237,8 +4256,8 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, Ex
return LTy;
}
- // C++0x 5.16p5
- // Otherwise, the result is an rvalue. If the second and third operands
+ // C++11 [expr.cond]p5
+ // Otherwise, the result is a prvalue. If the second and third operands
// do not have the same type, and either has (cv) class type, ...
if (!Same && (LTy->isRecordType() || RTy->isRecordType())) {
// ... overload resolution is used to determine the conversions (if any)
@@ -4248,8 +4267,8 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, Ex
return QualType();
}
- // C++0x 5.16p6
- // LValue-to-rvalue, array-to-pointer, and function-to-pointer standard
+ // C++11 [expr.cond]p6
+ // Lvalue-to-rvalue, array-to-pointer, and function-to-pointer standard
// conversions are performed on the second and third operands.
LHS = DefaultFunctionArrayLvalueConversion(LHS.take());
RHS = DefaultFunctionArrayLvalueConversion(RHS.take());
@@ -4302,9 +4321,11 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, Ex
}
// -- The second and third operands have pointer type, or one has pointer
- // type and the other is a null pointer constant; pointer conversions
- // and qualification conversions are performed to bring them to their
- // composite pointer type. The result is of the composite pointer type.
+ // type and the other is a null pointer constant, or both are null
+ // pointer constants, at least one of which is non-integral; pointer
+ // conversions and qualification conversions are performed to bring them
+ // to their composite pointer type. The result is of the composite
+ // pointer type.
// -- The second and third operands have pointer to member type, or one has
// pointer to member type and the other is a null pointer constant;
// pointer to member conversions and qualification conversions are
@@ -4342,7 +4363,7 @@ QualType Sema::CXXCheckConditionalOperands(ExprResult &Cond, ExprResult &LHS, Ex
/// \brief Find a merged pointer type and convert the two expressions to it.
///
/// This finds the composite pointer type (or member pointer type) for @p E1
-/// and @p E2 according to C++0x 5.9p2. It converts both expressions to this
+/// and @p E2 according to C++11 5.9p2. It converts both expressions to this
/// type and returns it.
/// It does not emit diagnostics.
///
@@ -4362,15 +4383,27 @@ QualType Sema::FindCompositePointerType(SourceLocation Loc,
assert(getLangOpts().CPlusPlus && "This function assumes C++");
QualType T1 = E1->getType(), T2 = E2->getType();
- if (!T1->isAnyPointerType() && !T1->isMemberPointerType() &&
- !T2->isAnyPointerType() && !T2->isMemberPointerType())
- return QualType();
-
- // C++0x 5.9p2
+ // C++11 5.9p2
// Pointer conversions and qualification conversions are performed on
// pointer operands to bring them to their composite pointer type. If
// one operand is a null pointer constant, the composite pointer type is
- // the type of the other operand.
+ // std::nullptr_t if the other operand is also a null pointer constant or,
+ // if the other operand is a pointer, the type of the other operand.
+ if (!T1->isAnyPointerType() && !T1->isMemberPointerType() &&
+ !T2->isAnyPointerType() && !T2->isMemberPointerType()) {
+ if (T1->isNullPtrType() &&
+ E2->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
+ E2 = ImpCastExprToType(E2, T1, CK_NullToPointer).take();
+ return T1;
+ }
+ if (T2->isNullPtrType() &&
+ E1->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
+ E1 = ImpCastExprToType(E1, T2, CK_NullToPointer).take();
+ return T2;
+ }
+ return QualType();
+ }
+
if (E1->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
if (T2->isMemberPointerType())
E1 = ImpCastExprToType(E1, T2, CK_NullToMemberPointer).take();