[AST] Fix crashes caused by redeclarations in hidden prototypes

ObjCContainerDecl.getMethod returns a nullptr by default when the
container is a hidden prototype. Callsites where the method is being
looked up on the redeclaration's own container should skip this check
since they (rightly) expect a valid method to be found.

Resolves rdar://69444243

Reviewed By: akyrtzi

Differential Revision: https://reviews.llvm.org/D89024
This commit is contained in:
Ben Barham 2020-10-08 19:48:33 -07:00 committed by Argyrios Kyrtzidis
parent 8a5858c8fd
commit fbb499ef25
5 changed files with 37 additions and 4 deletions

View File

@ -950,7 +950,8 @@ ObjCMethodDecl *ObjCMethodDecl::getNextRedeclarationImpl() {
if (!Redecl && isRedeclaration()) { if (!Redecl && isRedeclaration()) {
// This is the last redeclaration, go back to the first method. // This is the last redeclaration, go back to the first method.
return cast<ObjCContainerDecl>(CtxD)->getMethod(getSelector(), return cast<ObjCContainerDecl>(CtxD)->getMethod(getSelector(),
isInstanceMethod()); isInstanceMethod(),
/*AllowHidden=*/true);
} }
return Redecl ? Redecl : this; return Redecl ? Redecl : this;
@ -983,7 +984,8 @@ ObjCMethodDecl *ObjCMethodDecl::getCanonicalDecl() {
if (isRedeclaration()) { if (isRedeclaration()) {
// It is possible that we have not done deserializing the ObjCMethod yet. // It is possible that we have not done deserializing the ObjCMethod yet.
ObjCMethodDecl *MD = ObjCMethodDecl *MD =
cast<ObjCContainerDecl>(CtxD)->getMethod(Sel, isInstanceMethod()); cast<ObjCContainerDecl>(CtxD)->getMethod(Sel, isInstanceMethod(),
/*AllowHidden=*/true);
return MD ? MD : this; return MD ? MD : this;
} }
@ -1308,8 +1310,9 @@ void ObjCMethodDecl::getOverriddenMethods(
const ObjCMethodDecl *Method = this; const ObjCMethodDecl *Method = this;
if (Method->isRedeclaration()) { if (Method->isRedeclaration()) {
Method = cast<ObjCContainerDecl>(Method->getDeclContext())-> Method = cast<ObjCContainerDecl>(Method->getDeclContext())
getMethod(Method->getSelector(), Method->isInstanceMethod()); ->getMethod(Method->getSelector(), Method->isInstanceMethod(),
/*AllowHidden=*/true);
} }
if (Method->isOverriding()) { if (Method->isOverriding()) {

View File

@ -0,0 +1,7 @@
@protocol P1
- (void)p1_method;
- (void)p1_method;
@end
@interface Foo (SubP1) <P1>
@end

View File

@ -0,0 +1,3 @@
@interface Foo
- (void)parent_method;
@end

View File

@ -20,3 +20,11 @@ module PreambleWithImplicitImport {
export * export *
} }
} }
module hidden_redecls {
header "hidden-redecls.h"
explicit module sub {
header "hidden-redecls-sub.h"
}
}

View File

@ -0,0 +1,12 @@
@import hidden_redecls;
@interface Foo (Top)
- (void)top_method;
@end
// p1_method in protocol P1 is hidden since module_redecls.sub hasn't been
// imported yet. Check it is still indexed.
// RUN: c-index-test -index-file-full %s -isystem %S/Inputs -fmodules -target x86_64-apple-macosx10.7 | FileCheck %s
// CHECK: [indexDeclaration]: kind: objc-instance-method | name: p1_method | {{.*}} | loc: {{.*}}hidden-redecls-sub.h:2:9 | {{.*}} | isRedecl: 0
// CHECK: [indexDeclaration]: kind: objc-instance-method | name: p1_method | {{.*}} | loc: {{.*}}hidden-redecls-sub.h:3:9 | {{.*}} | isRedecl: 1