aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Analysis/AnalysisContext.h14
-rw-r--r--lib/Analysis/AnalysisDeclContext.cpp17
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp16
-rw-r--r--test/Analysis/NSString.m24
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