summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorArtem Dergachev <artem.dergachev@gmail.com>2019-04-30 03:01:02 +0000
committerArtem Dergachev <artem.dergachev@gmail.com>2019-04-30 03:01:02 +0000
commitc208eda5d902a10fcbc85024a06a60f72fbed767 (patch)
treeb07ebad2889f75d147d3c47c6b888e71e61a8023 /include
parent4ecb1e1c614b63724545e32904ca321e148e629c (diff)
[analyzer] Treat functions without run-time branches as "small".
Currently we always inline functions that have no branches, i.e. have exactly three CFG blocks: ENTRY, some code, EXIT. This makes sense because when there are no branches, it means that there's no exponential complexity introduced by inlining such function. Such functions also don't trigger various fundamental problems with our inlining mechanism, such as the problem of inlined defensive checks. Sometimes the CFG may contain more blocks, but in practice it still has linear structure because all directions (except, at most, one) of all branches turned out to be unreachable. When this happens, still treat the function as "small". This is useful, in particular, for dealing with C++17 if constexpr. Differential Revision: https://reviews.llvm.org/D61051 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@359531 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include')
-rw-r--r--include/clang/Analysis/CFG.h6
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h19
2 files changed, 25 insertions, 0 deletions
diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h
index dc83a99e66..5722cbee86 100644
--- a/include/clang/Analysis/CFG.h
+++ b/include/clang/Analysis/CFG.h
@@ -1172,6 +1172,12 @@ public:
/// implementation needs such an interface.
unsigned size() const { return NumBlockIDs; }
+ /// Returns true if the CFG has no branches. Usually it boils down to the CFG
+ /// having exactly three blocks (entry, the actual code, exit), but sometimes
+ /// more blocks appear due to having control flow that can be fully
+ /// resolved in compile time.
+ bool isLinear() const;
+
//===--------------------------------------------------------------------===//
// CFG Debugging: Pretty-Printing and Visualization.
//===--------------------------------------------------------------------===//
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index 185774b586..f0b01f182b 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -718,6 +718,25 @@ private:
AnalyzerOptions &Opts,
const EvalCallOptions &CallOpts);
+ /// See if the given AnalysisDeclContext is built for a function that we
+ /// should always inline simply because it's small enough.
+ /// Apart from "small" functions, we also have "large" functions
+ /// (cf. isLarge()), some of which are huge (cf. isHuge()), and we classify
+ /// the remaining functions as "medium".
+ bool isSmall(AnalysisDeclContext *ADC) const;
+
+ /// See if the given AnalysisDeclContext is built for a function that we
+ /// should inline carefully because it looks pretty large.
+ bool isLarge(AnalysisDeclContext *ADC) const;
+
+ /// See if the given AnalysisDeclContext is built for a function that we
+ /// should never inline because it's legit gigantic.
+ bool isHuge(AnalysisDeclContext *ADC) const;
+
+ /// See if the given AnalysisDeclContext is built for a function that we
+ /// should inline, just by looking at the declaration of the function.
+ bool mayInlineDecl(AnalysisDeclContext *ADC) const;
+
/// Checks our policies and decides weither the given call should be inlined.
bool shouldInlineCall(const CallEvent &Call, const Decl *D,
const ExplodedNode *Pred,