[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