r184250 - Introduce a new mangling for protocol-qualified ObjC types in C++. This allows

jahanian fjahanian at apple.com
Tue Jun 18 16:33:25 PDT 2013


Great. We should forewarn our runtime folks about this. Please CC them in radar.

- Fariborz

On Jun 18, 2013, at 3:41 PM, Eli Friedman <eli.friedman at gmail.com> wrote:

> Author: efriedma
> Date: Tue Jun 18 17:41:37 2013
> New Revision: 184250
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=184250&view=rev
> Log:
> Introduce a new mangling for protocol-qualified ObjC types in C++.  This allows
> to provide proper overloading, and also prevents mangling conflicts with
> template arguments of protocol-qualified type.
> 
> This is a non-backward-compatible mangling change, but per discussion with
> John, the benefits outweigh this cost.
> 
> Fixes <rdar://problem/14074822>.
> 
> 
> Removed:
>    cfe/trunk/test/SemaObjCXX/overload-1.mm
> Modified:
>    cfe/trunk/lib/AST/ItaniumMangle.cpp
>    cfe/trunk/lib/Sema/SemaOverload.cpp
>    cfe/trunk/test/CodeGenObjCXX/catch-id-type.mm
>    cfe/trunk/test/CodeGenObjCXX/mangle.mm
>    cfe/trunk/test/CodeGenObjCXX/rtti.mm
>    cfe/trunk/test/SemaObjCXX/overload.mm
> 
> Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=184250&r1=184249&r2=184250&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
> +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Tue Jun 18 17:41:37 2013
> @@ -2164,8 +2164,19 @@ void CXXNameMangler::mangleType(const Ob
> }
> 
> void CXXNameMangler::mangleType(const ObjCObjectType *T) {
> -  // We don't allow overloading by different protocol qualification,
> -  // so mangling them isn't necessary.
> +  if (!T->qual_empty()) {
> +    // Mangle protocol qualifiers.
> +    SmallString<64> QualStr;
> +    llvm::raw_svector_ostream QualOS(QualStr);
> +    QualOS << "objcproto";
> +    ObjCObjectType::qual_iterator i = T->qual_begin(), e = T->qual_end();
> +    for ( ; i != e; ++i) {
> +      StringRef name = (*i)->getName();
> +      QualOS << name.size() << name;
> +    }
> +    QualOS.flush();
> +    Out << 'U' << QualStr.size() << QualStr;
> +  }
>   mangleType(T->getBaseType());
> }
> 
> 
> Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=184250&r1=184249&r2=184250&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaOverload.cpp Tue Jun 18 17:41:37 2013
> @@ -2603,48 +2603,15 @@ void Sema::HandleFunctionTypeMismatch(Pa
> 
> /// FunctionArgTypesAreEqual - This routine checks two function proto types
> /// for equality of their argument types. Caller has already checked that
> -/// they have same number of arguments. This routine assumes that Objective-C
> -/// pointer types which only differ in their protocol qualifiers are equal.
> -/// If the parameters are different, ArgPos will have the parameter index
> -/// of the first different parameter.
> +/// they have same number of arguments.  If the parameters are different,
> +/// ArgPos will have the parameter index of the first different parameter.
> bool Sema::FunctionArgTypesAreEqual(const FunctionProtoType *OldType,
>                                     const FunctionProtoType *NewType,
>                                     unsigned *ArgPos) {
> -  if (!getLangOpts().ObjC1) {
> -    for (FunctionProtoType::arg_type_iterator O = OldType->arg_type_begin(),
> -         N = NewType->arg_type_begin(),
> -         E = OldType->arg_type_end(); O && (O != E); ++O, ++N) {
> -      if (!Context.hasSameType(*O, *N)) {
> -        if (ArgPos) *ArgPos = O - OldType->arg_type_begin();
> -        return false;
> -      }
> -    }
> -    return true;
> -  }
> -
>   for (FunctionProtoType::arg_type_iterator O = OldType->arg_type_begin(),
>        N = NewType->arg_type_begin(),
>        E = OldType->arg_type_end(); O && (O != E); ++O, ++N) {
> -    QualType ToType = (*O);
> -    QualType FromType = (*N);
> -    if (!Context.hasSameType(ToType, FromType)) {
> -      if (const PointerType *PTTo = ToType->getAs<PointerType>()) {
> -        if (const PointerType *PTFr = FromType->getAs<PointerType>())
> -          if ((PTTo->getPointeeType()->isObjCQualifiedIdType() &&
> -               PTFr->getPointeeType()->isObjCQualifiedIdType()) ||
> -              (PTTo->getPointeeType()->isObjCQualifiedClassType() &&
> -               PTFr->getPointeeType()->isObjCQualifiedClassType()))
> -            continue;
> -      }
> -      else if (const ObjCObjectPointerType *PTTo =
> -                 ToType->getAs<ObjCObjectPointerType>()) {
> -        if (const ObjCObjectPointerType *PTFr =
> -              FromType->getAs<ObjCObjectPointerType>())
> -          if (Context.hasSameUnqualifiedType(
> -                PTTo->getObjectType()->getBaseType(),
> -                PTFr->getObjectType()->getBaseType()))
> -            continue;
> -      }
> +    if (!Context.hasSameType(*O, *N)) {
>       if (ArgPos) *ArgPos = O - OldType->arg_type_begin();
>       return false;
>     }
> 
> Modified: cfe/trunk/test/CodeGenObjCXX/catch-id-type.mm
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/catch-id-type.mm?rev=184250&r1=184249&r2=184250&view=diff
> ==============================================================================
> --- cfe/trunk/test/CodeGenObjCXX/catch-id-type.mm (original)
> +++ cfe/trunk/test/CodeGenObjCXX/catch-id-type.mm Tue Jun 18 17:41:37 2013
> @@ -31,7 +31,7 @@ id FUNC() {
>     catch( id error )
>     { 
>       // CHECK:      landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
> -      // CHECK-NEXT:   catch i8* bitcast ({ i8*, i8*, i32, i8* }* @_ZTIP4INTF to i8*)
> +      // CHECK-NEXT:   catch i8* bitcast ({ i8*, i8*, i32, i8* }* @_ZTIPU11objcproto1P4INTF to i8*)
>       // CHECK-NEXT:   catch i8* bitcast ({ i8*, i8*, i32, i8* }* @_ZTIP11objc_object to i8*)
>       // CHECK-NEXT:   catch i8* bitcast ({ i8*, i8*, i32, i8* }* @_ZTIP10objc_class to i8*)
>       error = error; 
> 
> Modified: cfe/trunk/test/CodeGenObjCXX/mangle.mm
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/mangle.mm?rev=184250&r1=184249&r2=184250&view=diff
> ==============================================================================
> --- cfe/trunk/test/CodeGenObjCXX/mangle.mm (original)
> +++ cfe/trunk/test/CodeGenObjCXX/mangle.mm Tue Jun 18 17:41:37 2013
> @@ -78,3 +78,23 @@ void test2(Test2 *t) {
>   Test2Template<decltype(t.dimension)> t1;
>   Test2Template<decltype(t->alt_axis)> t2;
> }
> +
> + at protocol P;
> +void overload1(A<P>*) {}
> +// CHECK: define void @_Z9overload1PU11objcproto1P1A
> +void overload1(const A<P>*) {}
> +// CHECK: define void @_Z9overload1PKU11objcproto1P1A
> +void overload1(A<P>**) {}
> +// CHECK: define void @_Z9overload1PPU11objcproto1P1A
> +void overload1(A<P>*const*) {}
> +// CHECK: define void @_Z9overload1PKPU11objcproto1P1A
> +void overload1(A<P>***) {}
> +// CHECK: define void @_Z9overload1PPPU11objcproto1P1A
> +void overload1(void (f)(A<P>*)) {}
> +// CHECK: define void @_Z9overload1PFvPU11objcproto1P1AE
> +
> +template<typename T> struct X { void f(); };
> +template<> void X<A*>::f() {}
> +// CHECK: define void @_ZN1XIP1AE1fEv
> +template<> void X<A<P>*>::f() {}
> +// CHECK: define void @_ZN1XIPU11objcproto1P1AE1fEv
> 
> Modified: cfe/trunk/test/CodeGenObjCXX/rtti.mm
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/rtti.mm?rev=184250&r1=184249&r2=184250&view=diff
> ==============================================================================
> --- cfe/trunk/test/CodeGenObjCXX/rtti.mm (original)
> +++ cfe/trunk/test/CodeGenObjCXX/rtti.mm Tue Jun 18 17:41:37 2013
> @@ -38,14 +38,14 @@ int main() {
>   const std::type_info &t5 = typeid(c);
>   const std::type_info &t6 = typeid(*c);
> 
> -  // CHECK: store {{.*}} @_ZTIP11objc_object
> -  // CHECK: store {{.*}} @_ZTI11objc_object
> +  // CHECK: store {{.*}} @_ZTIPU11objcproto1P11objc_object
> +  // CHECK: store {{.*}} @_ZTIU11objcproto1P11objc_object
>   id<P> i2 = 0;
>   const std::type_info &t7 = typeid(i2);
>   const std::type_info &t8 = typeid(*i2);
> 
> -  // CHECK: store {{.*}} @_ZTIP10objc_class
> -  // CHECK: store {{.*}} @_ZTI10objc_class
> +  // CHECK: store {{.*}} @_ZTIPU11objcproto1P10objc_class
> +  // CHECK: store {{.*}} @_ZTIU11objcproto1P10objc_class
>   Class<P> c2 = 0;
>   const std::type_info &t9 = typeid(c2);
>   const std::type_info &t10 = typeid(*c2);
> 
> Removed: cfe/trunk/test/SemaObjCXX/overload-1.mm
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/overload-1.mm?rev=184249&view=auto
> ==============================================================================
> --- cfe/trunk/test/SemaObjCXX/overload-1.mm (original)
> +++ cfe/trunk/test/SemaObjCXX/overload-1.mm (removed)
> @@ -1,25 +0,0 @@
> -// RUN: %clang_cc1 -fsyntax-only -verify %s
> -
> - at protocol Proto1 @end
> -
> - at protocol Proto2 @end
> -
> -void f(id<Proto1> *) { }		// expected-note {{previous definition is here}}
> -
> -void f(id<Proto1, Proto2> *) { }	// expected-error {{conflicting types for 'f'}}
> -
> -void f(Class<Proto1> *) { }		// expected-note {{previous definition is here}}
> -
> -void f(Class<Proto1, Proto2> *) { }	// expected-error {{conflicting types for 'f'}}
> -
> - at interface I @end
> -
> -void f(I<Proto1> *) { }		// expected-note {{previous definition is here}}
> -
> -void f(I<Proto1, Proto2> *) { }		// expected-error {{conflicting types for 'f'}}
> -
> - at interface I1 @end
> -
> -void f1(I<Proto1> *) { }
> -
> -void f1(I1<Proto1, Proto2> *) { }
> 
> Modified: cfe/trunk/test/SemaObjCXX/overload.mm
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/overload.mm?rev=184250&r1=184249&r2=184250&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaObjCXX/overload.mm (original)
> +++ cfe/trunk/test/SemaObjCXX/overload.mm Tue Jun 18 17:41:37 2013
> @@ -60,9 +60,8 @@ void test2(A** ap) {
>   bp = ap; // expected-warning{{incompatible pointer types assigning to 'B **' from 'A **'}}
> }
> 
> -// FIXME: we should either allow overloading here or give a better diagnostic
> -int& cv(A*); // expected-note {{previous declaration}} expected-note 2 {{not viable}}
> -float& cv(const A*); // expected-error {{cannot be overloaded}}
> +int& cv(A*);
> +float& cv(const A*);
> 
> int& cv2(void*);
> float& cv2(const void*);
> @@ -70,22 +69,20 @@ 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}}
> +  float &f1 = cv(ac);
> +  float &f2 = cv(bc);
>   int& i3 = cv2(a);
>   float& f3 = cv2(ac);
> }
> 
> -// We agree with GCC that these can't be overloaded.
> -int& qualid(id<P0>); // expected-note {{previous declaration}} expected-note {{not viable}}
> -float& qualid(id<P1>); // expected-error {{cannot be overloaded}}
> +int& qualid(id<P0>);
> +float& qualid(id<P1>);
> 
> void qualid_test(A *a, B *b, C *c) {
>   int& i1 = qualid(a);
>   int& i2 = qualid(b);
> 
> -  // This doesn't work only because the overload was rejected above.
> -  float& f1 = qualid(c); // expected-error {{no matching function}}
> +  float& f1 = qualid(c);
> 
>   id<P0> p1 = 0;
>   p1 = 0;
> 
> 
> _______________________________________________
> 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