summaryrefslogtreecommitdiff
path: root/clang/lib/AST/DeclObjC.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/DeclObjC.cpp')
-rw-r--r--clang/lib/AST/DeclObjC.cpp66
1 files changed, 46 insertions, 20 deletions
diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp
index bf748fbab8e9..9a84e3c4a510 100644
--- a/clang/lib/AST/DeclObjC.cpp
+++ b/clang/lib/AST/DeclObjC.cpp
@@ -775,14 +775,12 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupPrivateMethod(
// ObjCMethodDecl
//===----------------------------------------------------------------------===//
-ObjCMethodDecl::ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc,
- Selector SelInfo, QualType T,
- TypeSourceInfo *ReturnTInfo,
- DeclContext *contextDecl, bool isInstance,
- bool isVariadic, bool isPropertyAccessor,
- bool isImplicitlyDeclared, bool isDefined,
- ImplementationControl impControl,
- bool HasRelatedResultType)
+ObjCMethodDecl::ObjCMethodDecl(
+ SourceLocation beginLoc, SourceLocation endLoc, Selector SelInfo,
+ QualType T, TypeSourceInfo *ReturnTInfo, DeclContext *contextDecl,
+ bool isInstance, bool isVariadic, bool isPropertyAccessor,
+ bool isSynthesizedAccessorStub, bool isImplicitlyDeclared, bool isDefined,
+ ImplementationControl impControl, bool HasRelatedResultType)
: NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo),
DeclContext(ObjCMethod), MethodDeclType(T), ReturnTInfo(ReturnTInfo),
DeclEndLoc(endLoc) {
@@ -793,6 +791,7 @@ ObjCMethodDecl::ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc,
setInstanceMethod(isInstance);
setVariadic(isVariadic);
setPropertyAccessor(isPropertyAccessor);
+ setSynthesizedAccessorStub(isSynthesizedAccessorStub);
setDefined(isDefined);
setIsRedeclaration(false);
setHasRedeclaration(false);
@@ -810,12 +809,13 @@ ObjCMethodDecl *ObjCMethodDecl::Create(
ASTContext &C, SourceLocation beginLoc, SourceLocation endLoc,
Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
DeclContext *contextDecl, bool isInstance, bool isVariadic,
- bool isPropertyAccessor, bool isImplicitlyDeclared, bool isDefined,
- ImplementationControl impControl, bool HasRelatedResultType) {
+ bool isPropertyAccessor, bool isSynthesizedAccessorStub,
+ bool isImplicitlyDeclared, bool isDefined, ImplementationControl impControl,
+ bool HasRelatedResultType) {
return new (C, contextDecl) ObjCMethodDecl(
beginLoc, endLoc, SelInfo, T, ReturnTInfo, contextDecl, isInstance,
- isVariadic, isPropertyAccessor, isImplicitlyDeclared, isDefined,
- impControl, HasRelatedResultType);
+ isVariadic, isPropertyAccessor, isSynthesizedAccessorStub,
+ isImplicitlyDeclared, isDefined, impControl, HasRelatedResultType);
}
ObjCMethodDecl *ObjCMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
@@ -823,6 +823,10 @@ ObjCMethodDecl *ObjCMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
Selector(), QualType(), nullptr, nullptr);
}
+bool ObjCMethodDecl::isDirectMethod() const {
+ return hasAttr<ObjCDirectAttr>();
+}
+
bool ObjCMethodDecl::isThisDeclarationADesignatedInitializer() const {
return getMethodFamily() == OMF_init &&
hasAttr<ObjCDesignatedInitializerAttr>();
@@ -952,24 +956,32 @@ ObjCMethodDecl *ObjCMethodDecl::getNextRedeclarationImpl() {
ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() {
auto *CtxD = cast<Decl>(getDeclContext());
+ const auto &Sel = getSelector();
if (auto *ImplD = dyn_cast<ObjCImplementationDecl>(CtxD)) {
- if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface())
- if (ObjCMethodDecl *MD = IFD->getMethod(getSelector(),
- isInstanceMethod()))
+ if (ObjCInterfaceDecl *IFD = ImplD->getClassInterface()) {
+ // When the container is the ObjCImplementationDecl (the primary
+ // @implementation), then the canonical Decl is either in
+ // the class Interface, or in any of its extension.
+ //
+ // So when we don't find it in the ObjCInterfaceDecl,
+ // sift through extensions too.
+ if (ObjCMethodDecl *MD = IFD->getMethod(Sel, isInstanceMethod()))
return MD;
+ for (auto *Ext : IFD->known_extensions())
+ if (ObjCMethodDecl *MD = Ext->getMethod(Sel, isInstanceMethod()))
+ return MD;
+ }
} else if (auto *CImplD = dyn_cast<ObjCCategoryImplDecl>(CtxD)) {
if (ObjCCategoryDecl *CatD = CImplD->getCategoryDecl())
- if (ObjCMethodDecl *MD = CatD->getMethod(getSelector(),
- isInstanceMethod()))
+ if (ObjCMethodDecl *MD = CatD->getMethod(Sel, isInstanceMethod()))
return MD;
}
if (isRedeclaration()) {
// It is possible that we have not done deserializing the ObjCMethod yet.
ObjCMethodDecl *MD =
- cast<ObjCContainerDecl>(CtxD)->getMethod(getSelector(),
- isInstanceMethod());
+ cast<ObjCContainerDecl>(CtxD)->getMethod(Sel, isInstanceMethod());
return MD ? MD : this;
}
@@ -1077,7 +1089,7 @@ ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const {
QualType ObjCMethodDecl::getSelfType(ASTContext &Context,
const ObjCInterfaceDecl *OID,
bool &selfIsPseudoStrong,
- bool &selfIsConsumed) {
+ bool &selfIsConsumed) const {
QualType selfTy;
selfIsPseudoStrong = false;
selfIsConsumed = false;
@@ -1306,6 +1318,11 @@ ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const {
if (isPropertyAccessor()) {
const auto *Container = cast<ObjCContainerDecl>(getParent());
+ // For accessor stubs, go back to the interface.
+ if (auto *ImplDecl = dyn_cast<ObjCImplDecl>(Container))
+ if (isSynthesizedAccessorStub())
+ Container = ImplDecl->getClassInterface();
+
bool IsGetter = (NumArgs == 0);
bool IsInstance = isInstanceMethod();
@@ -1358,6 +1375,15 @@ ObjCMethodDecl::findPropertyDecl(bool CheckOverrides) const {
}
}
+ assert(isSynthesizedAccessorStub() && "expected an accessor stub");
+ for (const auto *Cat : ClassDecl->known_categories()) {
+ if (Cat == Container)
+ continue;
+
+ if (const auto *Found = findMatchingProperty(Cat))
+ return Found;
+ }
+
llvm_unreachable("Marked as a property accessor but no property found!");
}