summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/StaticAnalyzer')
-rw-r--r--clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp24
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp22
2 files changed, 39 insertions, 7 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
index 29e27834763..5cbbb8d4628 100644
--- a/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
+++ b/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
@@ -16,6 +16,7 @@
#include "llvm/ADT/StringSwitch.h"
using namespace clang;
+using namespace llvm;
bool
AnalyzerOptions::mayInlineCXXMemberFunction(CXXInlineableMemberKind K) const {
@@ -80,3 +81,26 @@ bool AnalyzerOptions::mayInlineTemplateFunctions() const {
return *InlineTemplateFunctions;
}
+
+int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal) const {
+ std::string OptStr = Config.lookup(Name);
+ if (OptStr.empty())
+ return DefaultVal;
+
+ int Res = DefaultVal;
+ assert(StringRef(OptStr).getAsInteger(10, Res) == false &&
+ "analyzer-config option should be numeric.");
+
+ return Res;
+}
+
+unsigned AnalyzerOptions::getAlwaysInlineSize() const {
+ if (!AlwaysInlineSize.hasValue()) {
+ unsigned DefaultSize = 3;
+ Optional<unsigned> &MutableOption =
+ const_cast<Optional<unsigned> &>(AlwaysInlineSize);
+ MutableOption = getOptionAsInteger("ipa-always-inline-size", DefaultSize);
+ }
+
+ return AlwaysInlineSize.getValue();
+}
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index 9bf63c5b961..a4e1eb2f4cc 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -247,14 +247,18 @@ void ExprEngine::processCallExit(ExplodedNode *CEBNode) {
}
}
-static unsigned getNumberStackFrames(const LocationContext *LCtx) {
- unsigned count = 0;
+static void examineStackFrames(const Decl *D, const LocationContext *LCtx,
+ bool &IsRecursive, unsigned &StackDepth) {
+ IsRecursive = false;
+ StackDepth = 0;
while (LCtx) {
- if (isa<StackFrameContext>(LCtx))
- ++count;
+ if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(LCtx)) {
+ ++StackDepth;
+ if (SFC->getDecl() == D)
+ IsRecursive = true;
+ }
LCtx = LCtx->getParent();
}
- return count;
}
static bool IsInStdNamespace(const FunctionDecl *FD) {
@@ -282,8 +286,12 @@ bool ExprEngine::shouldInlineDecl(const Decl *D, ExplodedNode *Pred) {
if (!CalleeCFG)
return false;
- if (getNumberStackFrames(Pred->getLocationContext())
- == AMgr.options.InlineMaxStackDepth)
+ bool IsRecursive = false;
+ unsigned StackDepth = 0;
+ examineStackFrames(D, Pred->getLocationContext(), IsRecursive, StackDepth);
+ if ((StackDepth >= AMgr.options.InlineMaxStackDepth) &&
+ ((CalleeCFG->getNumBlockIDs() > AMgr.options.getAlwaysInlineSize())
+ || IsRecursive))
return false;
if (Engine.FunctionSummaries->hasReachedMaxBlockCount(D))
OpenPOWER on IntegriCloud