[cfe-commits] r69548 - in /cfe/trunk: lib/Sema/SemaExprCXX.cpp test/SemaCXX/conditional-expr.cpp
Sebastian Redl
sebastian.redl at getdesigned.at
Sun Apr 19 14:15:27 PDT 2009
Author: cornedbee
Date: Sun Apr 19 16:15:26 2009
New Revision: 69548
URL: http://llvm.org/viewvc/llvm-project?rev=69548&view=rev
Log:
Bring member pointer operands of the conditional operator to a common type. We're getting there ...
Modified:
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/test/SemaCXX/conditional-expr.cpp
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=69548&r1=69547&r2=69548&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Sun Apr 19 16:15:26 2009
@@ -1311,8 +1311,61 @@
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();
Modified: cfe/trunk/test/SemaCXX/conditional-expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conditional-expr.cpp?rev=69548&r1=69547&r2=69548&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/conditional-expr.cpp (original)
+++ cfe/trunk/test/SemaCXX/conditional-expr.cpp Sun Apr 19 16:15:26 2009
@@ -38,6 +38,14 @@
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 @@
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}}
More information about the cfe-commits
mailing list