This was file against gcc a while back. Can you is this is still an issue and need be addressed in clang?
- Fariborz <rdar://problem/4368177> Allow id to participate in objective-c++ overload resolution On Nov 26, 2008, at 3:31 PM, Douglas Gregor wrote: > Author: dgregor > Date: Wed Nov 26 17:31:11 2008 > New Revision: 60130 > > URL: http://llvm.org/viewvc/llvm-project?rev=60130&view=rev > Log: > Implement implicit conversions for Objective-C specific types, e.g., > converting a pointer to one Objective-C interface into a pointer to > another > Objective-C interface, and conversions with 'id'. The semantics seems > to match GCC, although they seem somewhat ad hoc. > > Fixed a few cases where we assumed the C++ definition of isObjectType, > but were getting the C definition, causing failures in trouble with > conversions to void pointers. > > Added: > cfe/trunk/test/SemaObjCXX/overload.mm > Modified: > cfe/trunk/Driver/clang.cpp > cfe/trunk/lib/Sema/SemaOverload.cpp > > Modified: cfe/trunk/Driver/clang.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/clang.cpp? > rev=60130&r1=60129&r2=60130&view=diff > > ====================================================================== > ======== > --- cfe/trunk/Driver/clang.cpp (original) > +++ cfe/trunk/Driver/clang.cpp Wed Nov 26 17:31:11 2008 > @@ -573,7 +573,7 @@ > } > > if (Options.CPlusPlus) > - Options.Blocks = 0; > + Options.Blocks = 0; > } > > static llvm::cl::opt<bool> > > Modified: cfe/trunk/lib/Sema/SemaOverload.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/ > SemaOverload.cpp?rev=60130&r1=60129&r2=60130&view=diff > > ====================================================================== > ======== > --- cfe/trunk/lib/Sema/SemaOverload.cpp (original) > +++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Nov 26 17:31:11 2008 > @@ -709,6 +709,34 @@ > return false; > } > > +/// BuildSimilarlyQualifiedPointerType - In a pointer conversion from > +/// the pointer type FromPtr to a pointer to type ToPointee, with the > +/// same type qualifiers as FromPtr has on its pointee type. ToType, > +/// 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, > + QualType ToPointee, QualType > ToType, > + ASTContext &Context) { > + QualType CanonFromPointee = Context.getCanonicalType(FromPtr- > >getPointeeType()); > + QualType CanonToPointee = Context.getCanonicalType(ToPointee); > + unsigned Quals = CanonFromPointee.getCVRQualifiers(); > + > + // Exact qualifier match -> return the pointer type we're > converting to. > + if (CanonToPointee.getCVRQualifiers() == Quals) { > + // ToType is exactly what we need. Return it. > + if (ToType.getTypePtr()) > + return ToType; > + > + // Build a pointer to ToPointee. It has the right qualifiers > + // already. > + return Context.getPointerType(ToPointee); > + } > + > + // Just build a canonical type that has the right qualifiers. > + return Context.getPointerType(CanonToPointee.getQualifiedType > (Quals)); > +} > + > /// IsPointerConversion - Determines whether the conversion of the > /// expression From, which has the (possibly adjusted) type FromType, > /// can be converted to the type ToType via a pointer conversion (C++ > @@ -728,27 +756,20 @@ > return true; > } > > + // Beyond this point, both types need to be pointers. > + const PointerType *FromTypePtr = FromType->getAsPointerType(); > + if (!FromTypePtr) > + return false; > + > + QualType FromPointeeType = FromTypePtr->getPointeeType(); > + QualType ToPointeeType = ToTypePtr->getPointeeType(); > + > // An rvalue of type "pointer to cv T," where T is an object type, > // can be converted to an rvalue of type "pointer to cv void" (C++ > // 4.10p2). > - if (FromType->isPointerType() && > - FromType->getAsPointerType()->getPointeeType()->isObjectType > () && > - ToTypePtr->getPointeeType()->isVoidType()) { > - // We need to produce a pointer to cv void, where cv is the same > - // set of cv-qualifiers as we had on the incoming pointee type. > - QualType toPointee = ToTypePtr->getPointeeType(); > - unsigned Quals = Context.getCanonicalType(FromType)- > >getAsPointerType() > - ->getPointeeType().getCVRQualifiers(); > - > - if (Context.getCanonicalType(ToTypePtr->getPointeeType > ()).getCVRQualifiers() > - == Quals) { > - // ToType is exactly the type we want. Use it. > - ConvertedType = ToType; > - } else { > - // Build a new type with the right qualifiers. > - ConvertedType > - = Context.getPointerType(Context.VoidTy.getQualifiedType(Quals)); > - } > + if (FromPointeeType->isIncompleteOrObjectType() && ToPointeeType- > >isVoidType()) { > + ConvertedType = BuildSimilarlyQualifiedPointerType > (FromTypePtr, ToPointeeType, > + ToType, > Context); > return true; > } > > @@ -765,32 +786,32 @@ > // > // Note that we do not check for ambiguity or inaccessibility > // here. That is handled by CheckPointerConversion. > - if (const PointerType *FromPtrType = FromType->getAsPointerType()) > - if (const PointerType *ToPtrType = ToType->getAsPointerType()) { > - if (FromPtrType->getPointeeType()->isRecordType() && > - ToPtrType->getPointeeType()->isRecordType() && > - IsDerivedFrom(FromPtrType->getPointeeType(), > - ToPtrType->getPointeeType())) { > - // The conversion is okay. Now, we need to produce the type > - // that results from this conversion, which will have the > same > - // qualifiers as the incoming type. > - QualType CanonFromPointee > - = Context.getCanonicalType(FromPtrType->getPointeeType()); > - QualType ToPointee = ToPtrType->getPointeeType(); > - QualType CanonToPointee = Context.getCanonicalType > (ToPointee); > - unsigned Quals = CanonFromPointee.getCVRQualifiers(); > - > - if (CanonToPointee.getCVRQualifiers() == Quals) { > - // ToType is exactly the type we want. Use it. > - ConvertedType = ToType; > - } else { > - // Build a new type with the right qualifiers. > - ConvertedType > - = Context.getPointerType > (CanonToPointee.getQualifiedType(Quals)); > - } > - return true; > - } > - } > + if (FromPointeeType->isRecordType() && ToPointeeType- > >isRecordType() && > + IsDerivedFrom(FromPointeeType, ToPointeeType)) { > + ConvertedType = BuildSimilarlyQualifiedPointerType > (FromTypePtr, ToPointeeType, > + ToType, > Context); > + return true; > + } > + > + // Objective C++: We're able to convert from a pointer to an > + // interface to a pointer to a different interface. > + const ObjCInterfaceType* FromIface = FromPointeeType- > >getAsObjCInterfaceType(); > + const ObjCInterfaceType* ToIface = ToPointeeType- > >getAsObjCInterfaceType(); > + if (FromIface && ToIface && > + Context.canAssignObjCInterfaces(ToIface, FromIface)) { > + ConvertedType = BuildSimilarlyQualifiedPointerType > (FromTypePtr, ToPointeeType, > + ToType, > Context); > + return true; > + } > + > + // Objective C++: We're able to convert between "id" and a pointer > + // to any interface (in both directions). > + if ((FromIface && Context.isObjCIdType(ToPointeeType)) > + || (ToIface && Context.isObjCIdType(FromPointeeType))) { > + ConvertedType = BuildSimilarlyQualifiedPointerType > (FromTypePtr, ToPointeeType, > + ToType, > Context); > + return true; > + } > > return false; > } > @@ -1125,6 +1146,17 @@ > return ImplicitConversionSequence::Better; > else if (IsDerivedFrom(FromPointee1, FromPointee2)) > return ImplicitConversionSequence::Worse; > + > + // Objective-C++: If one interface is more specific than the > + // other, it is the better one. > + const ObjCInterfaceType* FromIface1 = FromPointee1- > >getAsObjCInterfaceType(); > + const ObjCInterfaceType* FromIface2 = FromPointee2- > >getAsObjCInterfaceType(); > + if (FromIface1 && FromIface1) { > + if (Context.canAssignObjCInterfaces(FromIface2, FromIface1)) > + return ImplicitConversionSequence::Better; > + else if (Context.canAssignObjCInterfaces(FromIface1, > FromIface2)) > + return ImplicitConversionSequence::Worse; > + } > } > > // Compare based on qualification conversions (C++ 13.3.3.2p3, > @@ -1247,7 +1279,9 @@ > > /// CompareDerivedToBaseConversions - Compares two standard > conversion > /// sequences to determine whether they can be ranked based on their > -/// various kinds of derived-to-base conversions (C++ > [over.ics.rank]p4b3). > +/// various kinds of derived-to-base conversions (C++ > +/// [over.ics.rank]p4b3). As part of these checks, we also look at > +/// conversions between Objective-C interface types. > ImplicitConversionSequence::CompareKind > Sema::CompareDerivedToBaseConversions(const > StandardConversionSequence& SCS1, > const > StandardConversionSequence& SCS2) { > @@ -1273,6 +1307,9 @@ > // > // If class B is derived directly or indirectly from class A and > // class C is derived directly or indirectly from B, > + // > + // For Objective-C, we let A, B, and C also be Objective-C > + // interfaces. > > // Compare based on pointer conversions. > if (SCS1.Second == ICK_Pointer_Conversion && > @@ -1285,12 +1322,25 @@ > = FromType2->getAsPointerType()->getPointeeType > ().getUnqualifiedType(); > QualType ToPointee2 > = ToType2->getAsPointerType()->getPointeeType > ().getUnqualifiedType(); > + > + const ObjCInterfaceType* FromIface1 = FromPointee1- > >getAsObjCInterfaceType(); > + const ObjCInterfaceType* FromIface2 = FromPointee2- > >getAsObjCInterfaceType(); > + const ObjCInterfaceType* ToIface1 = ToPointee1- > >getAsObjCInterfaceType(); > + const ObjCInterfaceType* ToIface2 = ToPointee2- > >getAsObjCInterfaceType(); > + > // -- conversion of C* to B* is better than conversion of C* > to A*, > if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) { > if (IsDerivedFrom(ToPointee1, ToPointee2)) > return ImplicitConversionSequence::Better; > else if (IsDerivedFrom(ToPointee2, ToPointee1)) > return ImplicitConversionSequence::Worse; > + > + if (ToIface1 && ToIface2) { > + if (Context.canAssignObjCInterfaces(ToIface2, ToIface1)) > + return ImplicitConversionSequence::Better; > + else if (Context.canAssignObjCInterfaces(ToIface1, ToIface2)) > + return ImplicitConversionSequence::Worse; > + } > } > > // -- conversion of B* to A* is better than conversion of C* > to A*, > @@ -1299,6 +1349,13 @@ > return ImplicitConversionSequence::Better; > else if (IsDerivedFrom(FromPointee1, FromPointee2)) > return ImplicitConversionSequence::Worse; > + > + if (FromIface1 && FromIface2) { > + if (Context.canAssignObjCInterfaces(FromIface1, FromIface2)) > + return ImplicitConversionSequence::Better; > + else if (Context.canAssignObjCInterfaces(FromIface2, > FromIface1)) > + return ImplicitConversionSequence::Worse; > + } > } > } > > @@ -2268,7 +2325,7 @@ > for (BuiltinCandidateTypeSet::iterator Ptr = > CandidateTypes.pointer_begin(); > Ptr != CandidateTypes.pointer_end(); ++Ptr) { > // Skip pointer types that aren't pointers to object types. > - if (!(*Ptr)->getAsPointerType()->getPointeeType()- > >isObjectType()) > + if (!(*Ptr)->getAsPointerType()->getPointeeType()- > >isIncompleteOrObjectType()) > continue; > > QualType ParamTypes[2] = { > > Added: cfe/trunk/test/SemaObjCXX/overload.mm > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/ > overload.mm?rev=60130&view=auto > > ====================================================================== > ======== > --- cfe/trunk/test/SemaObjCXX/overload.mm (added) > +++ cfe/trunk/test/SemaObjCXX/overload.mm Wed Nov 26 17:31:11 2008 > @@ -0,0 +1,39 @@ > +// RUN clang -fsyntax-only -verify %s > [EMAIL PROTECTED] A > [EMAIL PROTECTED] > + > [EMAIL PROTECTED] B : A > [EMAIL PROTECTED] > + > +int& f(A*); > +float& f(B*); > +void g(A*); > + > +int& h(A*); > +float& h(id); > + > +void test(A* a, B* b, id val) { > + int& i1 = f(a); > + float& f1 = f(b); > + float& f2 = f(val); > + g(a); > + g(b); > + g(val); > + int& i2 = h(a); > + float& f3 = h(val); > + // int& i3 = h(b); FIXME: we match GCC here, but shouldn't this > work? > +} > + > +int& cv(A*); > +float& cv(const A*); > +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); > + float &f2 = cv(bc); > + int& i3 = cv2(a); > + float& f3 = cv2(ac); > +} > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
