[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