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);
};
}
}
}
+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>
switch (QMM) {
case QMM_Drop:
+ if (Quals.hasObjCLifetime())
+ Quals = Quals.withoutObjCLifetime();
break;
case QMM_Mangle:
if (const FunctionType *FT = dyn_cast<FunctionType>(T)) {
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);
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);
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 << '@';
--- /dev/null
+// 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"
+++ /dev/null
-// 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"
-