[cfe-commits] r60130 - in /cfe/trunk: Driver/clang.cpp lib/Sema/SemaOverload.cpp test/SemaObjCXX/overload.mm
fjahanian
fjahanian at apple.com
Wed Nov 26 18:29:23 PST 2008
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
> + at interface A
> + at end
> +
> + at interface B : A
> + at end
> +
> +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
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
More information about the cfe-commits
mailing list