diff options
-rw-r--r-- | include/clang/Analysis/AnalysisContext.h | 14 | ||||
-rw-r--r-- | lib/Analysis/AnalysisDeclContext.cpp | 17 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp | 16 | ||||
-rw-r--r-- | test/Analysis/NSString.m | 24 |
4 files changed, 68 insertions, 3 deletions
diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h index 168fc003dc..062af1bad1 100644 --- a/include/clang/Analysis/AnalysisContext.h +++ b/include/clang/Analysis/AnalysisContext.h @@ -133,7 +133,21 @@ public: void registerForcedBlockExpression(const Stmt *stmt); const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt); + /// \brief Get the body of the Declaration. Stmt *getBody() const; + + /// \brief Get the body of the Declaration. + /// \param IsAutosynthesized Output parameter that specifies if the body is + /// auto-generated by the BodyFarm. + Stmt *getBody(bool &IsAutosynthesized) const; + + /// \brief Checks if the body of the Decl is generated by the BodyFarm. + /// + /// Note, the lookup is not free. We are going to call getBody behind + /// the sceines. + /// \sa getBody + bool isBodyAutosynthesized() const; + CFG *getCFG(); CFGStmtMap *getCFGStmtMap(); diff --git a/lib/Analysis/AnalysisDeclContext.cpp b/lib/Analysis/AnalysisDeclContext.cpp index bcaad9b0db..20cc3d55f3 100644 --- a/lib/Analysis/AnalysisDeclContext.cpp +++ b/lib/Analysis/AnalysisDeclContext.cpp @@ -86,11 +86,13 @@ static BodyFarm &getBodyFarm(ASTContext &C) { return *BF; } -Stmt *AnalysisDeclContext::getBody() const { +Stmt *AnalysisDeclContext::getBody(bool &IsAutosynthesized) const { if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { Stmt *Body = FD->getBody(); - if (!Body && Manager && Manager->synthesizeBodies()) + if (!Body && Manager && Manager->synthesizeBodies()) { + IsAutosynthesized = true; return getBodyFarm(getASTContext()).getBody(FD); + } return Body; } else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) @@ -104,6 +106,17 @@ Stmt *AnalysisDeclContext::getBody() const { llvm_unreachable("unknown code decl"); } +Stmt *AnalysisDeclContext::getBody() const { + bool Tmp; + return getBody(Tmp); +} + +bool AnalysisDeclContext::isBodyAutosynthesized() const { + bool Tmp; + getBody(Tmp); + return Tmp; +} + const ImplicitParamDecl *AnalysisDeclContext::getSelfDecl() const { if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) return MD->getSelfDecl(); diff --git a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index 2c1f6c1d8f..1d006b09cc 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -733,13 +733,27 @@ void ExprEngine::conservativeEvalCall(const CallEvent &Call, NodeBuilder &Bldr, Bldr.generateNode(Call.getProgramPoint(), State, Pred); } +static bool isEssentialToInline(const CallEvent &Call) { + const Decl *D = Call.getDecl(); + if (D) { + AnalysisDeclContext *AD = + Call.getLocationContext()->getAnalysisDeclContext()-> + getManager()->getContext(D); + + // The auto-synthesized bodies are essential to inline as they are + // usually small and commonly used. + return AD->isBodyAutosynthesized(); + } + return false; +} + void ExprEngine::defaultEvalCall(NodeBuilder &Bldr, ExplodedNode *Pred, const CallEvent &CallTemplate) { // Make sure we have the most recent state attached to the call. ProgramStateRef State = Pred->getState(); CallEventRef<> Call = CallTemplate.cloneWithState(State); - if (HowToInline == Inline_None) { + if (HowToInline == Inline_None && !isEssentialToInline(CallTemplate)) { conservativeEvalCall(*Call, Bldr, Pred, State); return; } diff --git a/test/Analysis/NSString.m b/test/Analysis/NSString.m index 9339069f4c..e7ac730c72 100644 --- a/test/Analysis/NSString.m +++ b/test/Analysis/NSString.m @@ -404,3 +404,27 @@ void testOSCompareAndSwapXXBarrier_parameter_no_direct_release(NSString **old) { else return; } + +@interface AlwaysInlineBodyFarmBodies : NSObject { + NSString *_value; +} + - (NSString *)_value; + - (void)callValue; +@end + +@implementation AlwaysInlineBodyFarmBodies + +- (NSString *)_value { + if (!_value) { + NSString *s = [[NSString alloc] init]; + if (!OSAtomicCompareAndSwapPtr(0, s, (void**)&_value)) { + [s release]; + } + } + return _value; +} + +- (void)callValue { + [self _value]; +} +@end
\ No newline at end of file |