Fix mangled name of method with ns_consumed parameters.

When a function/method use a parameter with "ns_consumed" attribute,
ensure that the mangled name is the same whether -fobjc-arc is used
or not.

Since "ns_consumed" attribute is generally used to inform ARC that
a function/method does sink the reference, it mean it is usually
implemented in a compilation unit compiled without -fobjc-arc but
used form a compilation unit compiled with it.

Originally found while trying to use "ns_consumed" attribute in an
Objective-C++ file in Chromium (http://crbug.com/599980) where it
caused a linker error.

Regression introduced by revision 262278 (previously the attribute
was incorrectly not part of the mangled name).

Patch from Sylvain Defresne <sdefresne@chromium.org>!
http://reviews.llvm.org/D20113

llvm-svn: 270702
This commit is contained in:
Nico Weber 2016-05-25 14:15:08 +00:00
parent 0e871f0b66
commit fb42078d7c
4 changed files with 21 additions and 10 deletions

View File

@ -2243,7 +2243,7 @@ void CXXNameMangler::mangleBareFunctionType(const FunctionProtoType *Proto,
FunctionTypeDepth.enterResultType();
// Mangle ns_returns_retained as an order-sensitive qualifier here.
if (Proto->getExtInfo().getProducesResult())
if (Proto->getExtInfo().getProducesResult() && FD == nullptr)
mangleVendorQualifier("ns_returns_retained");
// Mangle the return type without any direct ARC ownership qualifiers.
@ -2269,7 +2269,7 @@ void CXXNameMangler::mangleBareFunctionType(const FunctionProtoType *Proto,
assert(!FD || FD->getNumParams() == Proto->getNumParams());
for (unsigned I = 0, E = Proto->getNumParams(); I != E; ++I) {
// Mangle extended parameter info as order-sensitive qualifiers here.
if (Proto->hasExtParameterInfos()) {
if (Proto->hasExtParameterInfos() && FD == nullptr) {
mangleExtParameterInfo(Proto->getExtParameterInfo(I));
}
@ -3819,7 +3819,7 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A) {
Out << 'L';
// References to external entities use the mangled name; if the name would
// not normally be manged then mangle it as unqualified.
// not normally be mangled then mangle it as unqualified.
mangle(D);
Out << 'E';

View File

@ -12,7 +12,7 @@ void sanityTest() {
id x = makeObject1();
// CHECK-NEXT: [[OBJ2:%.*]] = call i8* @_Z11makeObject2v()
// CHECK-NEXT: call void @_Z13releaseObjectU11ns_consumedP11objc_object(i8* [[OBJ2]])
// CHECK-NEXT: call void @_Z13releaseObjectP11objc_object(i8* [[OBJ2]])
releaseObject(makeObject2());
// CHECK-NEXT: call void @objc_storeStrong(i8** [[X]], i8* null)
@ -31,16 +31,16 @@ void releaseObjectT(__attribute__((ns_consumed)) T);
// CHECK-LABEL: define void @_Z12templateTestv
void templateTest() {
// CHECK: [[X:%.*]] = alloca i8*, align 8
// CHECK-NEXT: [[OBJ1:%.*]] = call i8* @_Z12makeObjectT1IU8__strongP11objc_objectEU19ns_returns_retainedT_v()
// CHECK-NEXT: [[OBJ1:%.*]] = call i8* @_Z12makeObjectT1IU8__strongP11objc_objectET_v()
// CHECK-NEXT: store i8* [[OBJ1]], i8** [[X]], align 8
id x = makeObjectT1<id>();
// CHECK-NEXT: [[OBJ2:%.*]] = call i8* @_Z12makeObjectT2IU8__strongP11objc_objectEU19ns_returns_retainedT_v()
// CHECK-NEXT: call void @_Z13releaseObjectU11ns_consumedP11objc_object(i8* [[OBJ2]])
// CHECK-NEXT: [[OBJ2:%.*]] = call i8* @_Z12makeObjectT2IU8__strongP11objc_objectET_v()
// CHECK-NEXT: call void @_Z13releaseObjectP11objc_object(i8* [[OBJ2]])
releaseObject(makeObjectT2<id>());
// CHECK-NEXT: [[OBJ3:%.*]] = call i8* @_Z11makeObject1v()
// CHECK-NEXT: call void @_Z14releaseObjectTIU8__strongP11objc_objectEvU11ns_consumedT_(i8* [[OBJ3]])
// CHECK-NEXT: call void @_Z14releaseObjectTIU8__strongP11objc_objectEvT_(i8* [[OBJ3]])
releaseObjectT(makeObject1());
// CHECK-NEXT: call void @objc_storeStrong(i8** [[X]], i8* null)

View File

@ -1,4 +1,4 @@
// RUN: %clang_cc1 -fobjc-arc -fobjc-runtime-has-weak -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -fobjc-arc -fobjc-runtime-has-weak -triple %itanium_abi_triple -emit-llvm -fblocks -o - %s | FileCheck %s
// CHECK-LABEL: define {{.*}}void @_Z1fPU8__strongP11objc_object(i8**)
void f(__strong id *) {}
@ -18,10 +18,14 @@ void f(const __autoreleasing id *) {}
void f(const __unsafe_unretained id *) {}
// CHECK-LABEL: define {{.*}}void @_Z1fPFU19ns_returns_retainedP11objc_objectvE
void f(__attribute__((ns_returns_retained)) id (*fn)()) {}
// CHECK-LABEL: define {{.*}}void @_Z1fP11objc_object
void f(__attribute__((ns_consumed)) id) {}
// CHECK-LABEL: define {{.*}}void @_Z1fPFP11objc_objectU11ns_consumedS0_S0_E
void f(id (*fn)(__attribute__((ns_consumed)) id, id)) {}
// CHECK-LABEL: define {{.*}}void @_Z1fPFP11objc_objectS0_U11ns_consumedS0_E
void f(__strong id (*fn)(id, __attribute__((ns_consumed)) id)) {}
// CHECK-LABEL: define {{.*}}void @_Z1fU13block_pointerFvU11ns_consumedP11objc_objectE
void f(void (^)(__attribute__((ns_consumed)) id)) {}
template<unsigned N> struct unsigned_c { };

View File

@ -1,4 +1,4 @@
// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -std=c++11 -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -std=c++11 -emit-llvm -fblocks -o - | FileCheck %s
// CHECK: @"_ZZ11+[A shared]E1a" = internal global
// CHECK: @"_ZZ11-[A(Foo) f]E1a" = internal global
@ -113,3 +113,10 @@ void parameterized_test2(__kindof Parameterized<A *, Test *> *p) {}
// CHECK-LABEL: define void @_Z19parameterized_test3P13Parameterized
void parameterized_test3(Parameterized *p) {}
// CHECK-LABEL: define {{.*}}void @_Z1fP11objc_object
void f(__attribute__((ns_consumed)) id) {}
// CHECK-LABEL: define {{.*}}void @_Z1fPFP11objc_objectS0_S0_E
void f(id (*fn)(__attribute__((ns_consumed)) id, id)) {}
// CHECK-LABEL: define {{.*}}void @_Z1fU13block_pointerFvP11objc_objectE
void f(void (^)(__attribute__((ns_consumed)) id)) {}