return const_cast<ObjCMethodDecl*>(this)->getClassInterface();
}
+ /// If this method is declared or implemented in a category, return
+ /// that category.
+ ObjCCategoryDecl *getCategory();
+ const ObjCCategoryDecl *getCategory() const {
+ return const_cast<ObjCMethodDecl*>(this)->getCategory();
+ }
+
Selector getSelector() const { return getDeclName().getObjCSelector(); }
QualType getReturnType() const { return MethodDeclType; }
llvm_unreachable("unknown method context");
}
+ObjCCategoryDecl *ObjCMethodDecl::getCategory() {
+ if (auto *CD = dyn_cast<ObjCCategoryDecl>(getDeclContext()))
+ return CD;
+ if (auto *IMD = dyn_cast<ObjCCategoryImplDecl>(getDeclContext()))
+ return IMD->getCategoryDecl();
+ return nullptr;
+}
+
SourceRange ObjCMethodDecl::getReturnTypeSourceRange() const {
const auto *TSI = getReturnTypeSourceInfo();
if (TSI)
raw_ostream &OS,
bool includePrefixByte,
bool includeCategoryNamespace) {
+ if (getASTContext().getLangOpts().ObjCRuntime.isGNUFamily()) {
+ // This is the mangling we've always used on the GNU runtimes, but it
+ // has obvious collisions in the face of underscores within class
+ // names, category names, and selectors; maybe we should improve it.
+
+ OS << (MD->isClassMethod() ? "_c_" : "_i_")
+ << MD->getClassInterface()->getName() << '_';
+
+ if (includeCategoryNamespace) {
+ if (auto category = MD->getCategory())
+ OS << category->getName();
+ }
+ OS << '_';
+
+ auto selector = MD->getSelector();
+ for (unsigned slotIndex = 0,
+ numArgs = selector.getNumArgs(),
+ slotEnd = std::max(numArgs, 1U);
+ slotIndex != slotEnd; ++slotIndex) {
+ if (auto name = selector.getIdentifierInfoForSlot(slotIndex))
+ OS << name->getName();
+
+ // Replace all the positions that would've been ':' with '_'.
+ // That's after each slot except that a unary selector doesn't
+ // end in ':'.
+ if (numArgs)
+ OS << '_';
+ }
+
+ return;
+ }
+
// \01+[ContainerName(CategoryName) SelectorName]
if (includePrefixByte) {
OS << '\01';
}
OS << (MD->isInstanceMethod() ? '-' : '+') << '[';
- if (const auto *CID = dyn_cast<ObjCCategoryImplDecl>(MD->getDeclContext())) {
+ if (const auto *CID = MD->getCategory()) {
OS << CID->getClassInterface()->getName();
if (includeCategoryNamespace) {
OS << '(' << *CID << ')';
namespace {
-std::string SymbolNameForMethod( StringRef ClassName,
- StringRef CategoryName, const Selector MethodName,
- bool isClassMethod) {
- std::string MethodNameColonStripped = MethodName.getAsString();
- std::replace(MethodNameColonStripped.begin(), MethodNameColonStripped.end(),
- ':', '_');
- return (Twine(isClassMethod ? "_c_" : "_i_") + ClassName + "_" +
- CategoryName + "_" + MethodNameColonStripped).str();
-}
-
/// Class that lazily initialises the runtime function. Avoids inserting the
/// types and the function declaration into a module if they're not used, and
/// avoids constructing the type more than once if it's used more than once.
ASTContext &Context = CGM.getContext();
for (const auto *OMD : Methods) {
llvm::Constant *FnPtr =
- TheModule.getFunction(SymbolNameForMethod(ClassName, CategoryName,
- OMD->getSelector(),
- isClassMethodList));
+ TheModule.getFunction(getSymbolNameForMethod(OMD));
assert(FnPtr && "Can't generate metadata for method that doesn't exist");
auto Method = MethodArray.beginStruct(ObjCMethodTy);
if (isV2ABI) {
llvm::Function *CGObjCGNU::GenerateMethod(const ObjCMethodDecl *OMD,
const ObjCContainerDecl *CD) {
- const ObjCCategoryImplDecl *OCD =
- dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext());
- StringRef CategoryName = OCD ? OCD->getName() : "";
- StringRef ClassName = CD->getName();
- Selector MethodName = OMD->getSelector();
- bool isClassMethod = !OMD->isInstanceMethod();
-
CodeGenTypes &Types = CGM.getTypes();
llvm::FunctionType *MethodTy =
Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
- std::string FunctionName = SymbolNameForMethod(ClassName, CategoryName,
- MethodName, isClassMethod);
+ std::string FunctionName = getSymbolNameForMethod(OMD);
llvm::Function *Method
= llvm::Function::Create(MethodTy,
void EmitImageInfo();
public:
- CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
- CGObjCRuntime(cgm), VMContext(cgm.getLLVMContext()) { }
+ CGObjCCommonMac(CodeGen::CodeGenModule &cgm)
+ : CGObjCRuntime(cgm), VMContext(cgm.getLLVMContext()) {}
bool isNonFragileABI() const {
return ObjCABI == 2;
if (OMD->isDirectMethod()) {
Method = GenerateDirectMethod(OMD, CD);
} else {
- SmallString<256> Name;
- llvm::raw_svector_ostream OS(Name);
- const auto &MC = CGM.getContext().createMangleContext();
- MC->mangleObjCMethodName(OMD, OS, /*includePrefixByte=*/true,
- /*includeCategoryNamespace=*/true);
+ auto Name = getSymbolNameForMethod(OMD);
CodeGenTypes &Types = CGM.getTypes();
llvm::FunctionType *MethodTy =
Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
Method =
llvm::Function::Create(MethodTy, llvm::GlobalValue::InternalLinkage,
- Name.str(), &CGM.getModule());
+ Name, &CGM.getModule());
}
MethodDefinitions.insert(std::make_pair(OMD, Method));
// Replace the cached function in the map.
I->second = Fn;
} else {
- SmallString<256> Name;
- llvm::raw_svector_ostream OS(Name);
- const auto &MC = CGM.getContext().createMangleContext();
- MC->mangleObjCMethodName(OMD, OS, /*includePrefixByte=*/true,
- /*includeCategoryNamespace=*/false);
+ auto Name = getSymbolNameForMethod(OMD, /*include category*/ false);
Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
- Name.str(), &CGM.getModule());
+ Name, &CGM.getModule());
DirectMethodDefinitions.insert(std::make_pair(COMD, Fn));
}
const ObjCProtocolDecl *protocol) {
return CGM.getObjCRuntime().GetOrEmitProtocol(protocol);
}
+
+std::string CGObjCRuntime::getSymbolNameForMethod(const ObjCMethodDecl *OMD,
+ bool includeCategoryName) {
+ std::string buffer;
+ llvm::raw_string_ostream out(buffer);
+ CGM.getCXXABI().getMangleContext().mangleObjCMethodName(OMD, out,
+ /*includePrefixByte=*/true,
+ includeCategoryName);
+ return buffer;
+}
public:
virtual ~CGObjCRuntime();
+ std::string getSymbolNameForMethod(const ObjCMethodDecl *method,
+ bool includeCategoryName = true);
+
/// Generate the function required to register all Objective-C components in
/// this compilation unit with the runtime library.
virtual llvm::Function *ModuleInitFunction() = 0;
// CHECK-NEXT: }
// CHECK-NEXT: },
// CHECK-NEXT: "name": "bar",
-// CHECK-NEXT: "mangledName": "-[TestObjCCategoryDecl bar]",
+// CHECK-NEXT: "mangledName": "-[TestObjCClass(TestObjCCategoryDecl) bar]",
// CHECK-NEXT: "returnType": {
// CHECK-NEXT: "qualType": "void"
// CHECK-NEXT: },
return Translation;
// Objective-C symbols for the MachO symbol table start with a \1. Please see
- // `CGObjCCommonMac::GetNameForMethod` in clang.
+ // `MangleContext::mangleObjCMethodName` in clang.
if (Translation[0] == 1)
return StringRef(Translation).drop_front();