mirror of
https://github.com/intel/llvm.git
synced 2026-01-24 08:30:34 +08:00
Bring member pointer operands of the conditional operator to a common type. We're getting there ...
llvm-svn: 69548
This commit is contained in:
@@ -1311,8 +1311,61 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
|
||||
if (!Composite.isNull())
|
||||
return Composite;
|
||||
|
||||
// Fourth bullet is same for pointers-to-member.
|
||||
// FIXME: Handle this case where both are member pointers.
|
||||
// Fourth bullet is same for pointers-to-member. However, the possible
|
||||
// conversions are far more limited: we have null-to-pointer, upcast of
|
||||
// containing class, and second-level cv-ness.
|
||||
// cv-ness is not a union, but must match one of the two operands. (Which,
|
||||
// frankly, is stupid.)
|
||||
const MemberPointerType *LMemPtr = LTy->getAsMemberPointerType();
|
||||
const MemberPointerType *RMemPtr = RTy->getAsMemberPointerType();
|
||||
if (LMemPtr && RHS->isNullPointerConstant(Context)) {
|
||||
ImpCastExprToType(RHS, LTy);
|
||||
return LTy;
|
||||
}
|
||||
if (RMemPtr && LHS->isNullPointerConstant(Context)) {
|
||||
ImpCastExprToType(LHS, RTy);
|
||||
return RTy;
|
||||
}
|
||||
if (LMemPtr && RMemPtr) {
|
||||
QualType LPointee = LMemPtr->getPointeeType();
|
||||
QualType RPointee = RMemPtr->getPointeeType();
|
||||
// First, we check that the unqualified pointee type is the same. If it's
|
||||
// not, there's no conversion that will unify the two pointers.
|
||||
if (Context.getCanonicalType(LPointee).getUnqualifiedType() ==
|
||||
Context.getCanonicalType(RPointee).getUnqualifiedType()) {
|
||||
// Second, we take the greater of the two cv qualifications. If neither
|
||||
// is greater than the other, the conversion is not possible.
|
||||
unsigned Q = LPointee.getCVRQualifiers() | RPointee.getCVRQualifiers();
|
||||
if (Q == LPointee.getCVRQualifiers() || Q == RPointee.getCVRQualifiers()){
|
||||
// Third, we check if either of the container classes is derived from
|
||||
// the other.
|
||||
QualType LContainer(LMemPtr->getClass(), 0);
|
||||
QualType RContainer(RMemPtr->getClass(), 0);
|
||||
QualType MoreDerived;
|
||||
if (Context.getCanonicalType(LContainer) ==
|
||||
Context.getCanonicalType(RContainer))
|
||||
MoreDerived = LContainer;
|
||||
else if (IsDerivedFrom(LContainer, RContainer))
|
||||
MoreDerived = LContainer;
|
||||
else if (IsDerivedFrom(RContainer, LContainer))
|
||||
MoreDerived = RContainer;
|
||||
|
||||
if (!MoreDerived.isNull()) {
|
||||
// The type 'Q Pointee (MoreDerived::*)' is the common type.
|
||||
// We don't use ImpCastExprToType here because this could still fail
|
||||
// for ambiguous or inaccessible conversions.
|
||||
QualType Common = Context.getMemberPointerType(
|
||||
LPointee.getQualifiedType(Q), MoreDerived.getTypePtr());
|
||||
if (PerformImplicitConversion(LHS, Common, "converting"))
|
||||
return QualType();
|
||||
if (PerformImplicitConversion(RHS, Common, "converting"))
|
||||
return QualType();
|
||||
return Common;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands)
|
||||
<< LHS->getType() << RHS->getType()
|
||||
<< LHS->getSourceRange() << RHS->getSourceRange();
|
||||
|
||||
@@ -38,6 +38,14 @@ struct BadDerived : BadBase {};
|
||||
struct Fields {
|
||||
int i1, i2, b1 : 3, b2 : 3;
|
||||
};
|
||||
struct MixedFields {
|
||||
int i;
|
||||
volatile int vi;
|
||||
const int ci;
|
||||
const volatile int cvi;
|
||||
};
|
||||
struct MixedFieldsDerived : MixedFields {
|
||||
};
|
||||
|
||||
enum Enum { EVal };
|
||||
|
||||
@@ -148,11 +156,15 @@ void test()
|
||||
d1 = i1 ? 4.0 : 'c';
|
||||
Base *pb = i1 ? (Base*)0 : (Derived*)0;
|
||||
pb = i1 ? (Derived*)0 : (Base*)0;
|
||||
// FIXME: member pointer conversions don't work yet.
|
||||
//pfm = i1 ? &Base::fn1 : &Derived::fn2;
|
||||
//pfm = i1 ? &Derived::fn2 : &Base::fn1;
|
||||
//pfm = i1 ? &Derived::fn2 : 0;
|
||||
//pfm = i1 ? 0 : &Derived::fn2;
|
||||
pfm = i1 ? &Base::fn1 : &Derived::fn2;
|
||||
pfm = i1 ? &Derived::fn2 : &Base::fn1;
|
||||
pfm = i1 ? &Derived::fn2 : 0;
|
||||
pfm = i1 ? 0 : &Derived::fn2;
|
||||
const int (MixedFieldsDerived::*mp1) =
|
||||
i1 ? &MixedFields::ci : &MixedFieldsDerived::i;
|
||||
const volatile int (MixedFields::*mp2) =
|
||||
i1 ? &MixedFields::ci : &MixedFields::cvi;
|
||||
i1 ? &MixedFields::ci : &MixedFields::vi; // expected-error {{incompatible operand types}}
|
||||
// Conversion of primitives does not result in an lvalue.
|
||||
&(i1 ? i1 : d1); // expected-error {{address expression must be an lvalue or a function designator}}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user