forked from OSchip/llvm-project
[analyzer] Prefer accessor method in extension over category in CallEvent.
In ObjCMethodCall:getRuntimeDefinition(), if the method is an accessor in a category, and it doesn't have a self declaration, first try to find the method in a class extension. This works around a bug in Sema where multiple accessors are synthesized for properties in class extensions that are redeclared in a category. The implicit parameters are not filled in for the method on the category, which causes a crash when trying to synthesize a getter for the property in BodyFarm. The Sema bug is tracked as rdar://problem/25481164. rdar://problem/25056531 llvm-svn: 265103
This commit is contained in:
parent
85fb9e058e
commit
c239dd1349
|
@ -958,8 +958,30 @@ RuntimeDefinition ObjCMethodCall::getRuntimeDefinition() const {
|
|||
// even if we don't actually have an implementation.
|
||||
if (!*Val)
|
||||
if (const ObjCMethodDecl *CompileTimeMD = E->getMethodDecl())
|
||||
if (CompileTimeMD->isPropertyAccessor())
|
||||
Val = IDecl->lookupInstanceMethod(Sel);
|
||||
if (CompileTimeMD->isPropertyAccessor()) {
|
||||
if (!CompileTimeMD->getSelfDecl() &&
|
||||
isa<ObjCCategoryDecl>(CompileTimeMD->getDeclContext())) {
|
||||
// If the method is an accessor in a category, and it doesn't
|
||||
// have a self declaration, first
|
||||
// try to find the method in a class extension. This
|
||||
// works around a bug in Sema where multiple accessors
|
||||
// are synthesized for properties in class
|
||||
// extensions that are redeclared in a category and the
|
||||
// the implicit parameters are not filled in for
|
||||
// the method on the category.
|
||||
// This ensures we find the accessor in the extension, which
|
||||
// has the implicit parameters filled in.
|
||||
auto *ID = CompileTimeMD->getClassInterface();
|
||||
for (auto *CatDecl : ID->visible_extensions()) {
|
||||
Val = CatDecl->getMethod(Sel,
|
||||
CompileTimeMD->isInstanceMethod());
|
||||
if (*Val)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!*Val)
|
||||
Val = IDecl->lookupInstanceMethod(Sel);
|
||||
}
|
||||
}
|
||||
|
||||
const ObjCMethodDecl *MD = Val.getValue();
|
||||
|
|
|
@ -247,6 +247,55 @@ void testConsistencyAssign(Person *p) {
|
|||
}
|
||||
@end
|
||||
|
||||
// Tests for the analyzer fix that works around a Sema bug
|
||||
// where multiple methods are created for properties in class extensions that
|
||||
// are redeclared in a category method.
|
||||
// The Sema bug is tracked as <rdar://problem/25481164>.
|
||||
@interface ClassWithRedeclaredPropertyInExtensionFollowedByCategory
|
||||
@end
|
||||
|
||||
@interface ClassWithRedeclaredPropertyInExtensionFollowedByCategory ()
|
||||
@end
|
||||
|
||||
@interface ClassWithRedeclaredPropertyInExtensionFollowedByCategory ()
|
||||
@property (readwrite) int someProp;
|
||||
@property (readonly) int otherProp;
|
||||
@end
|
||||
|
||||
@interface ClassWithRedeclaredPropertyInExtensionFollowedByCategory (MyCat)
|
||||
@property (readonly) int someProp;
|
||||
@property (readonly) int otherProp;
|
||||
@end
|
||||
|
||||
@implementation ClassWithRedeclaredPropertyInExtensionFollowedByCategory
|
||||
- (void)testSynthesisForRedeclaredProperties; {
|
||||
clang_analyzer_eval(self.someProp == self.someProp); // expected-warning{{TRUE}}
|
||||
clang_analyzer_eval([self someProp] == self.someProp); // expected-warning{{TRUE}}
|
||||
|
||||
clang_analyzer_eval(self.otherProp == self.otherProp); // expected-warning{{TRUE}}
|
||||
clang_analyzer_eval([self otherProp] == self.otherProp); // expected-warning{{TRUE}}
|
||||
}
|
||||
@end
|
||||
|
||||
// The relative order of the extension and the category matter, so test both.
|
||||
@interface ClassWithRedeclaredPropertyInCategoryFollowedByExtension
|
||||
@end
|
||||
|
||||
@interface ClassWithRedeclaredPropertyInCategoryFollowedByExtension ()
|
||||
@property (readwrite) int someProp;
|
||||
@end
|
||||
|
||||
@interface ClassWithRedeclaredPropertyInCategoryFollowedByExtension (MyCat)
|
||||
@property (readonly) int someProp;
|
||||
@end
|
||||
|
||||
@implementation ClassWithRedeclaredPropertyInCategoryFollowedByExtension
|
||||
- (void)testSynthesisForRedeclaredProperties; {
|
||||
clang_analyzer_eval(self.someProp == self.someProp); // expected-warning{{TRUE}}
|
||||
clang_analyzer_eval([self someProp] == self.someProp); // expected-warning{{TRUE}}
|
||||
}
|
||||
@end
|
||||
|
||||
@interface ClassWithSynthesizedPropertyAndGetter
|
||||
@property (readonly) int someProp;
|
||||
@end
|
||||
|
|
Loading…
Reference in New Issue