aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArtem Dergachev <artem.dergachev@gmail.com>2019-01-18 22:52:13 +0000
committerArtem Dergachev <artem.dergachev@gmail.com>2019-01-18 22:52:13 +0000
commitc2c47f24f53a064d141eb5ea62ecd76d636edf77 (patch)
treeda7476b9093d0cb6ed2f0cf17e39e329359c5096
parent22039df5d17e5d5b6d87a70e01e9e86c54b0138e (diff)
downloadllvm-c2c47f24f53a064d141eb5ea62ecd76d636edf77.zip
llvm-c2c47f24f53a064d141eb5ea62ecd76d636edf77.tar.gz
llvm-c2c47f24f53a064d141eb5ea62ecd76d636edf77.tar.bz2
[analyzer] Do not try to body-farm Objective-C properties with custom accessors.
If a property is defined with a custom getter, we should not behave as if the getter simply returns an instance variable. We don't support setters, so they aren't affected. On top of being the right thing to do, this also fixes a crash on the newly added test - in which a property and its getter are defined in two separate categories. rdar://problem/47051544 Differential Revision: https://reviews.llvm.org/D56823 llvm-svn: 351609
-rw-r--r--clang/lib/Analysis/BodyFarm.cpp5
-rw-r--r--clang/test/Analysis/properties.m35
2 files changed, 40 insertions, 0 deletions
diff --git a/clang/lib/Analysis/BodyFarm.cpp b/clang/lib/Analysis/BodyFarm.cpp
index 35f0464..2a682a8 100644
--- a/clang/lib/Analysis/BodyFarm.cpp
+++ b/clang/lib/Analysis/BodyFarm.cpp
@@ -807,6 +807,11 @@ Stmt *BodyFarm::getBody(const ObjCMethodDecl *D) {
D = D->getCanonicalDecl();
+ // We should not try to synthesize explicitly redefined accessors.
+ // We do not know for sure how they behave.
+ if (!D->isImplicit())
+ return nullptr;
+
Optional<Stmt *> &Val = Bodies[D];
if (Val.hasValue())
return Val.getValue();
diff --git a/clang/test/Analysis/properties.m b/clang/test/Analysis/properties.m
index 461639f..17b1560 100644
--- a/clang/test/Analysis/properties.m
+++ b/clang/test/Analysis/properties.m
@@ -1005,3 +1005,38 @@ void testNoCrashWhenAccessPropertyAndThereAreNoDirectBindingsAtAll() {
#endif // non-ARC
+@interface ExplicitAccessorInCategory : NSObject
+@property(readonly) int normal;
+- (int)normal;
+@property(readonly) int no_custom_accessor;
+@end
+
+@interface ExplicitAccessorInCategory ()
+@property(readonly) int in_category;
+
+@property(readonly) int still_no_custom_accessor;
+// This is an ordinary method, not a getter.
+- (int)still_no_custom_accessor;
+@end
+
+@interface ExplicitAccessorInCategory ()
+- (int)in_category;
+
+// This is an ordinary method, not a getter.
+- (int)no_custom_accessor;
+@end
+
+@implementation ExplicitAccessorInCategory
+- (void)foo {
+ // Make sure we don't farm bodies for explicit accessors: in particular,
+ // we're not sure that the accessor always returns the same value.
+ clang_analyzer_eval(self.normal == self.normal); // expected-warning{{UNKNOWN}}
+ // Also this used to crash.
+ clang_analyzer_eval(self.in_category == self.in_category); // expected-warning{{UNKNOWN}}
+
+ // When there is no explicit accessor defined (even if it looks like there is),
+ // farm the getter body and see if it does actually always yield the same value.
+ clang_analyzer_eval(self.no_custom_accessor == self.no_custom_accessor); // expected-warning{{TRUE}}
+ clang_analyzer_eval(self.still_no_custom_accessor == self.still_no_custom_accessor); // expected-warning{{TRUE}}
+}
+@end