]> granicus.if.org Git - clang/commitdiff
[analyzer] Use BodyFarm-synthesized body even when actual body available.
authorDevin Coughlin <dcoughlin@apple.com>
Mon, 28 Mar 2016 23:55:58 +0000 (23:55 +0000)
committerDevin Coughlin <dcoughlin@apple.com>
Mon, 28 Mar 2016 23:55:58 +0000 (23:55 +0000)
Change body autosynthesis to use the BodyFarm-synthesized body even when
an actual body exists. This enables the analyzer to use the simpler,
analyzer-provided body to model the behavior of the function rather than trying
to understand the actual body. Further, this makes the analyzer robust against
changes in headers that expose the implementations of those bodies.

rdar://problem/25145950

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@264687 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/AnalysisDeclContext.cpp
test/Analysis/NSString.m
test/Analysis/properties.m

index fe8021b7966c804e51161515db13197fcbc1c727..6bbe8f86d48eaaa7670e39533c96b49792cf8bbb 100644 (file)
@@ -94,19 +94,25 @@ Stmt *AnalysisDeclContext::getBody(bool &IsAutosynthesized) const {
   IsAutosynthesized = false;
   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
     Stmt *Body = FD->getBody();
-    if (!Body && Manager && Manager->synthesizeBodies()) {
-      Body = getBodyFarm(getASTContext(), Manager->Injector.get()).getBody(FD);
-      if (Body)
+    if (Manager && Manager->synthesizeBodies()) {
+      Stmt *SynthesizedBody =
+          getBodyFarm(getASTContext(), Manager->Injector.get()).getBody(FD);
+      if (SynthesizedBody) {
+        Body = SynthesizedBody;
         IsAutosynthesized = true;
+      }
     }
     return Body;
   }
   else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
     Stmt *Body = MD->getBody();
-    if (!Body && Manager && Manager->synthesizeBodies()) {
-      Body = getBodyFarm(getASTContext(), Manager->Injector.get()).getBody(MD);
-      if (Body)
+    if (Manager && Manager->synthesizeBodies()) {
+      Stmt *SynthesizedBody =
+          getBodyFarm(getASTContext(), Manager->Injector.get()).getBody(MD);
+      if (SynthesizedBody) {
+        Body = SynthesizedBody;
         IsAutosynthesized = true;
+      }
     }
     return Body;
   } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
index e3900334831f50353a991a83dda8339988ff41dc..799f813022ebd30e4e586b2a25b69ef9aa6c70ff 100644 (file)
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount,alpha.core -analyzer-store=region -analyzer-constraints=range -verify -Wno-objc-root-class %s
 // RUN: %clang_cc1 -triple i386-apple-darwin10 -analyze -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount,alpha.core -analyzer-store=region -analyzer-constraints=range -analyzer-config mode=shallow -verify -Wno-objc-root-class %s
 // RUN: %clang_cc1 -DTEST_64 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount,alpha.core -analyzer-store=region -analyzer-constraints=range -verify -Wno-objc-root-class %s
-
+// RUN: %clang_cc1 -DOSATOMIC_USE_INLINED -triple i386-apple-darwin10 -analyze -analyzer-checker=core,osx.cocoa.NilArg,osx.cocoa.RetainCount,alpha.core -analyzer-store=region -analyzer-constraints=range -verify -Wno-objc-root-class %s
 
 //===----------------------------------------------------------------------===//
 // The following code is reduced using delta-debugging from
@@ -279,9 +279,22 @@ id testSharedClassFromFunction() {
   return [[SharedClass alloc] _init]; // no-warning
 }
 
+#if !(defined(OSATOMIC_USE_INLINED) && OSATOMIC_USE_INLINED)
 // Test OSCompareAndSwap
 _Bool OSAtomicCompareAndSwapPtr( void *__oldValue, void *__newValue, void * volatile *__theValue );
 extern BOOL objc_atomicCompareAndSwapPtr(id predicate, id replacement, volatile id *objectLocation);
+#else
+// Test that the body farm models are still used even when a body is available.
+_Bool opaque_OSAtomicCompareAndSwapPtr( void *__oldValue, void *__newValue, void * volatile *__theValue );
+_Bool OSAtomicCompareAndSwapPtr( void *__oldValue, void *__newValue, void * volatile *__theValue ) {
+  return opaque_OSAtomicCompareAndSwapPtr(__oldValue, __newValue, __theValue);
+}
+
+extern BOOL opaque_objc_atomicCompareAndSwapPtr(id predicate, id replacement, volatile id *objectLocation);
+extern BOOL objc_atomicCompareAndSwapPtr(id predicate, id replacement, volatile id *objectLocation) {
+  return opaque_objc_atomicCompareAndSwapPtr(predicate, replacement, objectLocation);
+}
+#endif
 
 void testOSCompareAndSwap() {
   NSString *old = 0;
index bda2149409c314399588fa023a372c6eea2cd8dc..d79643f8b606bf6479979a3578abd43505a08081 100644 (file)
@@ -247,6 +247,25 @@ void testConsistencyAssign(Person *p) {
 }
 @end
 
+@interface ClassWithSynthesizedPropertyAndGetter
+@property (readonly) int someProp;
+@end
+
+@implementation ClassWithSynthesizedPropertyAndGetter
+@synthesize someProp;
+
+// Make sure that the actual getter is inlined and not a getter created
+// by BodyFarm
+- (void)testBodyFarmGetterNotUsed {
+  int i = self.someProp;
+  clang_analyzer_eval(i == 22); // expected-warning {{TRUE}}
+}
+
+-(int)someProp {
+  return 22;
+}
+@end
+
 //------
 // Setter ivar invalidation.
 //------