This commit sets the Self and Imp declarations for ObjC method declarations,
in addition to the definitions. It also fixes
a bunch of code in clang that had wrong assumptions about when getSelfDecl() would be set:
- CGDebugInfo::getObjCMethodName and AnalysisConsumer::getFunctionName would assume that it was
set for method declarations part of a protocol, which they never were,
and that self would be a Class type, which it isn't as it is id for a protocol.
Also use the Canonical Decl to index the set of Direct methods so that
when calls and implementations interleave, the same llvm::Function is
used and the same symbol name emitted.
Radar-Id: rdar://problem/
57661767
Patch by: Pierre Habouzit
Differential Revision: https://reviews.llvm.org/D71091
}
} else if (const auto *OCD = dyn_cast<ObjCCategoryImplDecl>(DC)) {
OS << OCD->getClassInterface()->getName() << '(' << OCD->getName() << ')';
- } else if (isa<ObjCProtocolDecl>(DC)) {
- // We can extract the type of the class from the self pointer.
- if (ImplicitParamDecl *SelfDecl = OMD->getSelfDecl()) {
- QualType ClassTy =
- cast<ObjCObjectPointerType>(SelfDecl->getType())->getPointeeType();
- ClassTy.print(OS, PrintingPolicy(LangOptions()));
- }
}
OS << ' ' << OMD->getSelector().getAsString() << ']';
llvm::Function *
CGObjCCommonMac::GenerateDirectMethod(const ObjCMethodDecl *OMD,
const ObjCContainerDecl *CD) {
- auto I = DirectMethodDefinitions.find(OMD);
+ auto I = DirectMethodDefinitions.find(OMD->getCanonicalDecl());
if (I != DirectMethodDefinitions.end())
return I->second;
llvm::Function *Method =
llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
Name.str(), &CGM.getModule());
- DirectMethodDefinitions.insert(std::make_pair(OMD, Method));
+ DirectMethodDefinitions.insert(std::make_pair(OMD->getCanonicalDecl(), Method));
return Method;
}
}
}
+ // Insert the invisible arguments, self and _cmd!
+ ObjCMethod->createImplicitParams(Context, ObjCMethod->getClassInterface());
+
ActOnDocumentableDecl(ObjCMethod);
return ObjCMethod;
// definitions rarely show up in headers.
Reader.PendingBodies[MD] = GetCurrentCursorOffset();
HasPendingBody = true;
- MD->setSelfDecl(ReadDeclAs<ImplicitParamDecl>());
- MD->setCmdDecl(ReadDeclAs<ImplicitParamDecl>());
}
+ MD->setSelfDecl(ReadDeclAs<ImplicitParamDecl>());
+ MD->setCmdDecl(ReadDeclAs<ImplicitParamDecl>());
MD->setInstanceMethod(Record.readInt());
MD->setVariadic(Record.readInt());
MD->setPropertyAccessor(Record.readInt());
VisitNamedDecl(D);
// FIXME: convert to LazyStmtPtr?
// Unlike C/C++, method bodies will never be in header files.
- bool HasBodyStuff = D->getBody() != nullptr ||
- D->getSelfDecl() != nullptr || D->getCmdDecl() != nullptr;
+ bool HasBodyStuff = D->getBody() != nullptr;
Record.push_back(HasBodyStuff);
if (HasBodyStuff) {
Record.AddStmt(D->getBody());
- Record.AddDeclRef(D->getSelfDecl());
- Record.AddDeclRef(D->getCmdDecl());
}
+ Record.AddDeclRef(D->getSelfDecl());
+ Record.AddDeclRef(D->getCmdDecl());
Record.push_back(D->isInstanceMethod());
Record.push_back(D->isVariadic());
Record.push_back(D->isPropertyAccessor());
} else if (const auto *OCD = dyn_cast<ObjCCategoryImplDecl>(DC)) {
OS << OCD->getClassInterface()->getName() << '('
<< OCD->getName() << ')';
- } else if (isa<ObjCProtocolDecl>(DC)) {
- // We can extract the type of the class from the self pointer.
- if (ImplicitParamDecl *SelfDecl = OMD->getSelfDecl()) {
- QualType ClassTy =
- cast<ObjCObjectPointerType>(SelfDecl->getType())->getPointeeType();
- ClassTy.print(OS, PrintingPolicy(LangOptions()));
- }
}
OS << ' ' << OMD->getSelector().getAsString() << ']';
__attribute__((objc_root_class))
@interface Root
+- (int)getInt __attribute__((objc_direct));
+@property(direct, readonly) int intProperty;
+@property(direct, readonly) int intProperty2;
@end
@implementation Root
+// CHECK-LABEL: define hidden i32 @"\01-[Root intProperty2]"
+- (int)intProperty2 {
+ return 42;
+}
+
// CHECK-LABEL: define hidden i32 @"\01-[Root getInt]"(
- (int)getInt __attribute__((objc_direct)) {
// loading parameters
}
@end
+// CHECK-LABEL: define hidden i32 @"\01-[Root intProperty]"
@interface Foo : Root {
id __strong _cause_cxx_destruct;
// CHECK-LABEL: define hidden void @"\01-[Foo setGetDynamic_setDirect:]"(
// CHECK-LABEL: define internal void @"\01-[Foo .cxx_destruct]"(
@end
+
+int useRoot(Root *r) {
+ // CHECK-LABEL: define i32 @useRoot
+ // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root getInt]"
+ // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root intProperty]"
+ // CHECK: %{{[^ ]*}} = call i32 bitcast {{.*}} @"\01-[Root intProperty2]"
+ return [r getInt] + [r intProperty] + [r intProperty2];
+}