From c2685f09703167912371d2663b35ca6afa3db24d Mon Sep 17 00:00:00 2001 From: Devin Coughlin Date: Mon, 28 Mar 2016 23:55:58 +0000 Subject: [PATCH] [analyzer] Use BodyFarm-synthesized body even when actual body available. 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 | 18 ++++++++++++------ test/Analysis/NSString.m | 15 ++++++++++++++- test/Analysis/properties.m | 19 +++++++++++++++++++ 3 files changed, 45 insertions(+), 7 deletions(-) diff --git a/lib/Analysis/AnalysisDeclContext.cpp b/lib/Analysis/AnalysisDeclContext.cpp index fe8021b796..6bbe8f86d4 100644 --- a/lib/Analysis/AnalysisDeclContext.cpp +++ b/lib/Analysis/AnalysisDeclContext.cpp @@ -94,19 +94,25 @@ Stmt *AnalysisDeclContext::getBody(bool &IsAutosynthesized) const { IsAutosynthesized = false; if (const FunctionDecl *FD = dyn_cast(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(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(D)) diff --git a/test/Analysis/NSString.m b/test/Analysis/NSString.m index e390033483..799f813022 100644 --- a/test/Analysis/NSString.m +++ b/test/Analysis/NSString.m @@ -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; diff --git a/test/Analysis/properties.m b/test/Analysis/properties.m index bda2149409..d79643f8b6 100644 --- a/test/Analysis/properties.m +++ b/test/Analysis/properties.m @@ -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. //------ -- 2.40.0