[cfe-commits] r120607 - in /cfe/trunk: lib/Sema/SemaOverload.cpp test/SemaObjCXX/objc-pointer-conv.mm test/SemaObjCXX/overload.mm

Douglas Gregor dgregor at apple.com
Wed Dec 1 13:43:59 PST 2010


Author: dgregor
Date: Wed Dec  1 15:43:58 2010
New Revision: 120607

URL: http://llvm.org/viewvc/llvm-project?rev=120607&view=rev
Log:
Improve our handling of cv-qualifiers in Objective-C pointer
conversions. Previously, we would end up collapsing qualification
conversions into the Objective-C pointer conversion step, including
(possibly) stripping qualifiers that shouldn't be removed.

This generalizes BuildSimilarlyQualifiedPointerType() to also work on
Objective-C object pointers, then eliminates the (redundant, not
totally correct) BuildSimilarlyQualifiedObjCObjectPointerType()
function.

Fixes <rdar://problem/8714395>.

Modified:
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/test/SemaObjCXX/objc-pointer-conv.mm
    cfe/trunk/test/SemaObjCXX/overload.mm

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=120607&r1=120606&r2=120607&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Dec  1 15:43:58 2010
@@ -1358,10 +1358,14 @@
 /// if non-empty, will be a pointer to ToType that may or may not have
 /// the right set of qualifiers on its pointee.
 static QualType
-BuildSimilarlyQualifiedPointerType(const PointerType *FromPtr,
+BuildSimilarlyQualifiedPointerType(const Type *FromPtr,
                                    QualType ToPointee, QualType ToType,
                                    ASTContext &Context) {
-  QualType CanonFromPointee = Context.getCanonicalType(FromPtr->getPointeeType());
+  assert((FromPtr->getTypeClass() == Type::Pointer ||
+          FromPtr->getTypeClass() == Type::ObjCObjectPointer) &&
+         "Invalid similarly-qualified pointer type");
+  QualType CanonFromPointee 
+    = Context.getCanonicalType(FromPtr->getPointeeType());
   QualType CanonToPointee = Context.getCanonicalType(ToPointee);
   Qualifiers Quals = CanonFromPointee.getQualifiers();
 
@@ -1373,32 +1377,18 @@
 
     // Build a pointer to ToPointee. It has the right qualifiers
     // already.
+    if (isa<ObjCObjectPointerType>(ToType))
+      return Context.getObjCObjectPointerType(ToPointee);
     return Context.getPointerType(ToPointee);
   }
 
   // Just build a canonical type that has the right qualifiers.
-  return Context.getPointerType(
-         Context.getQualifiedType(CanonToPointee.getLocalUnqualifiedType(), 
-                                  Quals));
-}
-
-/// BuildSimilarlyQualifiedObjCObjectPointerType - In a pointer conversion from
-/// the FromType, which is an objective-c pointer, to ToType, which may or may
-/// not have the right set of qualifiers.
-static QualType
-BuildSimilarlyQualifiedObjCObjectPointerType(QualType FromType,
-                                             QualType ToType,
-                                             ASTContext &Context) {
-  QualType CanonFromType = Context.getCanonicalType(FromType);
-  QualType CanonToType = Context.getCanonicalType(ToType);
-  Qualifiers Quals = CanonFromType.getQualifiers();
-    
-  // Exact qualifier match -> return the pointer type we're converting to.
-  if (CanonToType.getLocalQualifiers() == Quals)
-    return ToType;
+  QualType QualifiedCanonToPointee
+    = Context.getQualifiedType(CanonToPointee.getLocalUnqualifiedType(), Quals);
   
-  // Just build a canonical type that has the right qualifiers.
-  return Context.getQualifiedType(CanonToType.getLocalUnqualifiedType(), Quals);
+  if (isa<ObjCObjectPointerType>(ToType))
+    return Context.getObjCObjectPointerType(QualifiedCanonToPointee);
+  return Context.getPointerType(QualifiedCanonToPointee);
 }
   
 static bool isNullPointerConstantForConversion(Expr *Expr,
@@ -1482,10 +1472,11 @@
   // , including objective-c pointers.
   QualType ToPointeeType = ToTypePtr->getPointeeType();
   if (FromType->isObjCObjectPointerType() && ToPointeeType->isVoidType()) {
-    ConvertedType = BuildSimilarlyQualifiedObjCObjectPointerType(FromType,
+    ConvertedType = BuildSimilarlyQualifiedPointerType(
+                                      FromType->getAs<ObjCObjectPointerType>(),
+                                                       ToPointeeType,
                                                        ToType, Context);
     return true;
-    
   }
   const PointerType *FromTypePtr = FromType->getAs<PointerType>();
   if (!FromTypePtr)
@@ -1561,6 +1552,12 @@
     FromType->getAs<ObjCObjectPointerType>();
 
   if (ToObjCPtr && FromObjCPtr) {
+    // If the pointee types are the same (ignoring qualifications),
+    // then this is not a pointer conversion.
+    if (Context.hasSameUnqualifiedType(ToObjCPtr->getPointeeType(),
+                                       FromObjCPtr->getPointeeType()))
+      return false;
+
     // Objective C++: We're able to convert between "id" or "Class" and a
     // pointer to any interface (in both directions).
     if (ToObjCPtr->isObjCBuiltinType() && FromObjCPtr->isObjCBuiltinType()) {
@@ -1584,7 +1581,9 @@
           !ToObjCPtr->getPointeeType().isAtLeastAsQualifiedAs(
                                                 FromObjCPtr->getPointeeType()))
         return false;
-      ConvertedType = ToType;
+      ConvertedType = BuildSimilarlyQualifiedPointerType(FromObjCPtr, 
+                                                   ToObjCPtr->getPointeeType(),
+                                                         ToType, Context);
       return true;
     }
 
@@ -1593,7 +1592,9 @@
       // interfaces, which is permitted. However, we're going to
       // complain about it.
       IncompatibleObjC = true;
-      ConvertedType = FromType;
+      ConvertedType = BuildSimilarlyQualifiedPointerType(FromObjCPtr, 
+                                                   ToObjCPtr->getPointeeType(),
+                                                         ToType, Context);
       return true;
     }
   }
@@ -1636,7 +1637,7 @@
                               IncompatibleObjC)) {
     // We always complain about this conversion.
     IncompatibleObjC = true;
-    ConvertedType = ToType;
+    ConvertedType = Context.getPointerType(ConvertedType);
     return true;
   }
   // Allow conversion of pointee being objective-c pointer to another one;
@@ -1645,7 +1646,7 @@
       ToPointeeType->getAs<ObjCObjectPointerType>() &&
       isObjCPointerConversion(FromPointeeType, ToPointeeType, ConvertedType,
                               IncompatibleObjC)) {
-    ConvertedType = ToType;
+    ConvertedType = Context.getPointerType(ConvertedType);
     return true;
   }
   

Modified: cfe/trunk/test/SemaObjCXX/objc-pointer-conv.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/objc-pointer-conv.mm?rev=120607&r1=120606&r2=120607&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/objc-pointer-conv.mm (original)
+++ cfe/trunk/test/SemaObjCXX/objc-pointer-conv.mm Wed Dec  1 15:43:58 2010
@@ -39,8 +39,8 @@
 @interface DerivedFromI : I
 @end
 
-void accept_derived(DerivedFromI*); // expected-note{{candidate function not viable: cannot convert from superclass 'I *' to subclass 'DerivedFromI *' for 1st argument}}
+void accept_derived(DerivedFromI*);
 
 void test_base_to_derived(I* i) {
-  accept_derived(i); // expected-error{{no matching function for call to 'accept_derived'}}
+  accept_derived(i); // expected-warning{{incompatible pointer types converting 'I *' to type 'DerivedFromI *'}}
 }

Modified: cfe/trunk/test/SemaObjCXX/overload.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/overload.mm?rev=120607&r1=120606&r2=120607&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/overload.mm (original)
+++ cfe/trunk/test/SemaObjCXX/overload.mm Wed Dec  1 15:43:58 2010
@@ -31,8 +31,8 @@
 float& f(B*); // expected-note {{candidate}}
 void g(A*);
 
-int& h(A*);
-float& h(id);
+int& h(A*); // expected-note{{candidate}}
+float& h(id); // expected-note{{candidate}}
 
 void test0(A* a, B* b, id val) {
   int& i1 = f(a);
@@ -46,13 +46,14 @@
   g(val);
   int& i2 = h(a);
   float& f3 = h(val);
-  //  int& i3 = h(b); FIXME: we match GCC here, but shouldn't this work?
+
+  // FIXME: we match GCC here, but shouldn't this work?
+  int& i3 = h(b); // expected-error{{call to 'h' is ambiguous}}
 }
 
-// We make these errors instead of warnings.  Is that okay?
 void test1(A* a) {
-  B* b = a; // expected-error{{cannot initialize a variable of type 'B *' with an lvalue of type 'A *'}}
-  B *c; c = a; // expected-error{{assigning to 'B *' from incompatible type 'A *'}}
+  B* b = a; // expected-warning{{incompatible pointer types converting 'A *' to type 'B *'}}
+  B *c; c = a; // expected-warning{{incompatible pointer types assigning to 'A *' from 'B *'}}
 }
 
 void test2(A** ap) {
@@ -64,18 +65,16 @@
 int& cv(A*); // expected-note {{previous declaration}} expected-note 2 {{not viable}}
 float& cv(const A*); // expected-error {{cannot be overloaded}}
 
-int& cv2(void*); // expected-note 2 {{candidate}}
-float& cv2(const void*); // expected-note 2 {{candidate}}
+int& cv2(void*);
+float& cv2(const void*);
 
 void cv_test(A* a, B* b, const A* ac, const B* bc) {
   int &i1 = cv(a);
   int &i2 = cv(b);
   float &f1 = cv(ac); // expected-error {{no matching function}}
   float &f2 = cv(bc); // expected-error {{no matching function}}
-
-  // FIXME: these should not be ambiguous
-  int& i3 = cv2(a); // expected-error {{ambiguous}}
-  float& f3 = cv2(ac); // expected-error {{ambiguous}}
+  int& i3 = cv2(a);
+  float& f3 = cv2(ac);
 }
 
 // We agree with GCC that these can't be overloaded.
@@ -124,3 +123,22 @@
     foo(b); // expected-error {{call to 'foo' is ambiguous}}
   }
 }
+
+namespace rdar8714395 {
+  int &f(const void*);
+  float &f(const Foo*);
+
+  int &f2(const void*);
+  float &f2(Foo const* const *);
+
+  int &f3(const void*);
+  float &f3(Foo const**);
+
+  void g(Foo *p) {
+    float &fr = f(p);
+    float &fr2 = f2(&p);
+    int &ir = f3(&p);
+  }
+
+  
+}





More information about the cfe-commits mailing list