forked from OSchip/llvm-project
AST: support ObjC lifetime qualifiers in MS ABI
Adjust the ObjC protocol conformance workaround to be more extensible. Use a synthetic type for the protocol (`struct Protocol`). Embed this within a reserved namespace to permit extending the extended pointer type qualifiers similarly for ObjC lifetime qualifiers. Introduce additional special handling for `__autoreleasing`, `__strong`, and `__weak` Objective C lifetime qualifiers. We decorate these by creating an artificial template type `Autoreleasing`, `Strong`, or `Weak` in the `__ObjC` namespace. These are only considered in the template type specialization and not the function parameter. llvm-svn: 324701
This commit is contained in:
parent
0976cee8e9
commit
bbce34a8dd
|
@ -362,6 +362,10 @@ private:
|
|||
const TemplateArgumentList &TemplateArgs);
|
||||
void mangleTemplateArg(const TemplateDecl *TD, const TemplateArgument &TA,
|
||||
const NamedDecl *Parm);
|
||||
|
||||
void mangleObjCProtocol(const ObjCProtocolDecl *PD);
|
||||
void mangleObjCLifetime(const QualType T, Qualifiers Quals,
|
||||
SourceRange Range);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1456,6 +1460,47 @@ void MicrosoftCXXNameMangler::mangleTemplateArg(const TemplateDecl *TD,
|
|||
}
|
||||
}
|
||||
|
||||
void MicrosoftCXXNameMangler::mangleObjCProtocol(const ObjCProtocolDecl *PD) {
|
||||
llvm::SmallString<64> TemplateMangling;
|
||||
llvm::raw_svector_ostream Stream(TemplateMangling);
|
||||
MicrosoftCXXNameMangler Extra(Context, Stream);
|
||||
|
||||
Stream << "?$";
|
||||
Extra.mangleSourceName("Protocol");
|
||||
Extra.mangleArtificalTagType(TTK_Struct, PD->getName());
|
||||
|
||||
mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__ObjC"});
|
||||
}
|
||||
|
||||
void MicrosoftCXXNameMangler::mangleObjCLifetime(const QualType Type,
|
||||
Qualifiers Quals,
|
||||
SourceRange Range) {
|
||||
llvm::SmallString<64> TemplateMangling;
|
||||
llvm::raw_svector_ostream Stream(TemplateMangling);
|
||||
MicrosoftCXXNameMangler Extra(Context, Stream);
|
||||
|
||||
Stream << "?$";
|
||||
switch (Quals.getObjCLifetime()) {
|
||||
case Qualifiers::OCL_None:
|
||||
case Qualifiers::OCL_ExplicitNone:
|
||||
break;
|
||||
case Qualifiers::OCL_Autoreleasing:
|
||||
Extra.mangleSourceName("Autoreleasing");
|
||||
break;
|
||||
case Qualifiers::OCL_Strong:
|
||||
Extra.mangleSourceName("Strong");
|
||||
break;
|
||||
case Qualifiers::OCL_Weak:
|
||||
Extra.mangleSourceName("Weak");
|
||||
break;
|
||||
}
|
||||
Extra.manglePointerCVQualifiers(Quals);
|
||||
Extra.manglePointerExtQualifiers(Quals, Type);
|
||||
Extra.mangleType(Type, Range);
|
||||
|
||||
mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__ObjC"});
|
||||
}
|
||||
|
||||
void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals,
|
||||
bool IsMember) {
|
||||
// <cvr-qualifiers> ::= [E] [F] [I] <base-cvr-qualifiers>
|
||||
|
@ -1683,6 +1728,8 @@ void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,
|
|||
|
||||
switch (QMM) {
|
||||
case QMM_Drop:
|
||||
if (Quals.hasObjCLifetime())
|
||||
Quals = Quals.withoutObjCLifetime();
|
||||
break;
|
||||
case QMM_Mangle:
|
||||
if (const FunctionType *FT = dyn_cast<FunctionType>(T)) {
|
||||
|
@ -1701,6 +1748,8 @@ void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range,
|
|||
case QMM_Result:
|
||||
// Presence of __unaligned qualifier shouldn't affect mangling here.
|
||||
Quals.removeUnaligned();
|
||||
if (Quals.hasObjCLifetime())
|
||||
Quals = Quals.withoutObjCLifetime();
|
||||
if ((!IsPointer && Quals) || isa<TagType>(T)) {
|
||||
Out << '?';
|
||||
mangleQualifiers(Quals, false);
|
||||
|
@ -2334,6 +2383,15 @@ void MicrosoftCXXNameMangler::mangleType(const PointerType *T, Qualifiers Quals,
|
|||
void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T,
|
||||
Qualifiers Quals, SourceRange Range) {
|
||||
QualType PointeeType = T->getPointeeType();
|
||||
switch (Quals.getObjCLifetime()) {
|
||||
case Qualifiers::OCL_None:
|
||||
case Qualifiers::OCL_ExplicitNone:
|
||||
break;
|
||||
case Qualifiers::OCL_Autoreleasing:
|
||||
case Qualifiers::OCL_Strong:
|
||||
case Qualifiers::OCL_Weak:
|
||||
return mangleObjCLifetime(PointeeType, Quals, Range);
|
||||
}
|
||||
manglePointerCVQualifiers(Quals);
|
||||
manglePointerExtQualifiers(Quals, PointeeType);
|
||||
mangleType(PointeeType, Range);
|
||||
|
@ -2469,11 +2527,8 @@ void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T, Qualifiers,
|
|||
else
|
||||
mangleSourceName(T->getInterface()->getName());
|
||||
|
||||
for (const auto &Q : T->quals()) {
|
||||
Out << 'Y'; // cointerface
|
||||
mangleSourceName(Q->getName());
|
||||
Out << '@';
|
||||
}
|
||||
for (const auto &Q : T->quals())
|
||||
mangleObjCProtocol(Q);
|
||||
Out << '@';
|
||||
|
||||
Out << '@';
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
// RUN: %clang_cc1 -triple thumbv7-windows-msvc -fobjc-runtime=ios-6.0 -fobjc-arc -o - -emit-llvm %s | FileCheck %s
|
||||
|
||||
@protocol P;
|
||||
@protocol Q;
|
||||
|
||||
@class I;
|
||||
|
||||
void f(id<P>, id, id<P>, id) {}
|
||||
// CHECK-LABEL: "\01?f@@YAXPAU?$objc_object@U?$Protocol@UP@@@__ObjC@@@@PAUobjc_object@@01@Z"
|
||||
|
||||
void f(id, id<P>, id<P>, id) {}
|
||||
// CHECK-LABEL: "\01?f@@YAXPAUobjc_object@@PAU?$objc_object@U?$Protocol@UP@@@__ObjC@@@@10@Z"
|
||||
|
||||
void f(id<P>, id<P>) {}
|
||||
// CHECK-LABEL: "\01?f@@YAXPAU?$objc_object@U?$Protocol@UP@@@__ObjC@@@@0@Z"
|
||||
|
||||
void f(id<P>) {}
|
||||
// CHECK-LABEL: "\01?f@@YAXPAU?$objc_object@U?$Protocol@UP@@@__ObjC@@@@@Z"
|
||||
|
||||
void f(id<P, Q>) {}
|
||||
// CHECK-LABEL: "\01?f@@YAXPAU?$objc_object@U?$Protocol@UP@@@__ObjC@@U?$Protocol@UQ@@@2@@@@Z"
|
||||
|
||||
void f(Class<P>) {}
|
||||
// CHECK-LABEL: "\01?f@@YAXPAU?$objc_class@U?$Protocol@UP@@@__ObjC@@@@@Z"
|
||||
|
||||
void f(Class<P, Q>) {}
|
||||
// CHECK-LABEL: "\01?f@@YAXPAU?$objc_class@U?$Protocol@UP@@@__ObjC@@U?$Protocol@UQ@@@2@@@@Z"
|
||||
|
||||
void f(I<P> *) {}
|
||||
// CHECK-LABEL: "\01?f@@YAXPAU?$I@U?$Protocol@UP@@@__ObjC@@@@@Z"
|
||||
|
||||
void f(I<P, Q> *) {}
|
||||
// CHECK-LABEL: "\01?f@@YAXPAU?$I@U?$Protocol@UP@@@__ObjC@@U?$Protocol@UQ@@@2@@@@Z"
|
||||
|
||||
template <typename>
|
||||
struct S {};
|
||||
|
||||
void f(S<__unsafe_unretained id>) {}
|
||||
// CHECK-LABEL: "\01?f@@YAXU?$S@PAUobjc_object@@@@@Z"
|
||||
|
||||
void f(S<__autoreleasing id>) {}
|
||||
// CHECK-LABEL: "\01?f@@YAXU?$S@U?$Autoreleasing@PAUobjc_object@@@__ObjC@@@@@Z"
|
||||
|
||||
void f(S<__strong id>) {}
|
||||
// CHECK-LABEL: "\01?f@@YAXU?$S@U?$Strong@PAUobjc_object@@@__ObjC@@@@@Z"
|
||||
|
||||
void f(S<__weak id>) {}
|
||||
// CHECK-LABEL: "\01?f@@YAXU?$S@U?$Weak@PAUobjc_object@@@__ObjC@@@@@Z"
|
||||
|
||||
void w(__weak id) {}
|
||||
// CHECK-LABEL: "\01?w@@YAXPAUobjc_object@@@Z"
|
||||
|
||||
void s(__strong id) {}
|
||||
// CHECK-LABEL: "\01?s@@YAXPAUobjc_object@@@Z"
|
||||
|
||||
void a(__autoreleasing id) {}
|
||||
// CHECK-LABEL: "\01?a@@YAXPAUobjc_object@@@Z"
|
||||
|
||||
void u(__unsafe_unretained id) {}
|
||||
// CHECK-LABEL: "\01?u@@YAXPAUobjc_object@@@Z"
|
||||
|
||||
S<__autoreleasing id> g() { return S<__autoreleasing id>(); }
|
||||
// CHECK-LABEL: "\01?g@@YA?AU?$S@U?$Autoreleasing@PAUobjc_object@@@__ObjC@@@@XZ"
|
||||
|
||||
__autoreleasing id h() { return nullptr; }
|
||||
// CHECK-LABEL: "\01?h@@YAPAUobjc_object@@XZ"
|
|
@ -1,34 +0,0 @@
|
|||
// RUN: %clang_cc1 -triple thumbv7-windows-msvc -fobjc-runtime=ios-6.0 -o - -emit-llvm %s | FileCheck %s
|
||||
|
||||
@protocol P;
|
||||
@protocol Q;
|
||||
|
||||
@class I;
|
||||
|
||||
void f(id<P>, id, id<P>, id) {}
|
||||
// CHECK-LABEL: "\01?f@@YAXPAU?$objc_object@YP@@@@PAUobjc_object@@01@Z"
|
||||
|
||||
void f(id, id<P>, id<P>, id) {}
|
||||
// CHECK-LABEL: "\01?f@@YAXPAUobjc_object@@PAU?$objc_object@YP@@@@10@Z"
|
||||
|
||||
void f(id<P>, id<P>) {}
|
||||
// CHECK-LABEL: "\01?f@@YAXPAU?$objc_object@YP@@@@0@Z"
|
||||
|
||||
void f(id<P>) {}
|
||||
// CHECK-LABEL: "\01?f@@YAXPAU?$objc_object@YP@@@@@Z"
|
||||
|
||||
void f(id<P, Q>) {}
|
||||
// CHECK-LABEL: "\01?f@@YAXPAU?$objc_object@YP@@YQ@@@@@Z"
|
||||
|
||||
void f(Class<P>) {}
|
||||
// CHECK-LABEL: "\01?f@@YAXPAU?$objc_class@YP@@@@@Z"
|
||||
|
||||
void f(Class<P, Q>) {}
|
||||
// CHECK-LABEL: "\01?f@@YAXPAU?$objc_class@YP@@YQ@@@@@Z"
|
||||
|
||||
void f(I<P> *) {}
|
||||
// CHECK-LABEL: "\01?f@@YAXPAU?$I@YP@@@@@Z"
|
||||
|
||||
void f(I<P, Q> *) {}
|
||||
// CHECK-LABEL: "\01?f@@YAXPAU?$I@YP@@YQ@@@@@Z"
|
||||
|
Loading…
Reference in New Issue