summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Core
diff options
context:
space:
mode:
authorPeter Szecsi <szepet95@gmail.com>2017-07-19 23:50:00 +0000
committerPeter Szecsi <szepet95@gmail.com>2017-07-19 23:50:00 +0000
commitcb387b11df4290336129267df56620a48ee2b2cd (patch)
tree5b4b77e8cd41e9652e87721636a33d3f68db79d5 /clang/lib/StaticAnalyzer/Core
parent9b97a31870b4e2eb323d5ecca0052f1de19617a3 (diff)
downloadbcm5719-llvm-cb387b11df4290336129267df56620a48ee2b2cd.tar.gz
bcm5719-llvm-cb387b11df4290336129267df56620a48ee2b2cd.zip
This feature allows the analyzer to consider loops to completely unroll. New
requirements/rules (for unrolling) can be added easily via ASTMatchers. The current implementation is hidden behind a flag. Right now the blocks which belong to an unrolled loop are marked by the LoopVisitor which adds them to the ProgramState. Then whenever we encounter a CFGBlock in the processCFGBlockEntrance which is marked then we skip its investigating. That means, it won't be considered to be visited more than the maximal bound for visiting since it won't be checked. Differential Revision: https://reviews.llvm.org/D34260 llvm-svn: 308558
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core')
-rw-r--r--clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp6
-rw-r--r--clang/lib/StaticAnalyzer/Core/CMakeLists.txt2
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngine.cpp24
3 files changed, 31 insertions, 1 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
index 6f48fcb9e20..d5d6527f4fc 100644
--- a/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
+++ b/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
@@ -375,6 +375,12 @@ bool AnalyzerOptions::shouldWidenLoops() {
return WidenLoops.getValue();
}
+bool AnalyzerOptions::shouldUnrollLoops() {
+ if (!UnrollLoops.hasValue())
+ UnrollLoops = getBooleanOption("unroll-loops", /*Default=*/false);
+ return UnrollLoops.getValue();
+}
+
bool AnalyzerOptions::shouldDisplayNotesAsEvents() {
if (!DisplayNotesAsEvents.hasValue())
DisplayNotesAsEvents =
diff --git a/clang/lib/StaticAnalyzer/Core/CMakeLists.txt b/clang/lib/StaticAnalyzer/Core/CMakeLists.txt
index 85878f5e96e..5ac4f942f37 100644
--- a/clang/lib/StaticAnalyzer/Core/CMakeLists.txt
+++ b/clang/lib/StaticAnalyzer/Core/CMakeLists.txt
@@ -35,6 +35,7 @@ add_clang_library(clangStaticAnalyzerCore
ExprEngineObjC.cpp
FunctionSummary.cpp
HTMLDiagnostics.cpp
+ LoopUnrolling.cpp
LoopWidening.cpp
MemRegion.cpp
PathDiagnostic.cpp
@@ -54,6 +55,7 @@ add_clang_library(clangStaticAnalyzerCore
LINK_LIBS
clangAST
+ clangASTMatchers
clangAnalysis
clangBasic
clangLex
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index eee5400fe17..409fe173e26 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -17,6 +17,7 @@
#include "PrettyStackTraceLocationContext.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/ParentMap.h"
+#include "clang/Analysis/CFGStmtMap.h"
#include "clang/AST/StmtCXX.h"
#include "clang/AST/StmtObjC.h"
#include "clang/Basic/Builtins.h"
@@ -27,6 +28,7 @@
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/raw_ostream.h"
@@ -1497,6 +1499,27 @@ void ExprEngine::processCFGBlockEntrance(const BlockEdge &L,
NodeBuilderWithSinks &nodeBuilder,
ExplodedNode *Pred) {
PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
+ // If we reach a loop which has a known bound (and meets
+ // other constraints) then consider completely unrolling it.
+ if (AMgr.options.shouldUnrollLoops()) {
+ const CFGBlock *ActualBlock = nodeBuilder.getContext().getBlock();
+ const Stmt *Term = ActualBlock->getTerminator();
+ if (Term && shouldCompletelyUnroll(Term, AMgr.getASTContext())) {
+ ProgramStateRef UnrolledState =
+ markLoopAsUnrolled(Term, Pred->getState(),
+ Pred->getLocationContext()
+ ->getAnalysisDeclContext()
+ ->getCFGStmtMap());
+ if (UnrolledState != Pred->getState())
+ nodeBuilder.generateNode(UnrolledState, Pred);
+ return;
+ }
+
+ if (isUnrolledLoopBlock(ActualBlock, Pred))
+ return;
+ if (ActualBlock->empty())
+ return;
+ }
// If this block is terminated by a loop and it has already been visited the
// maximum number of times, widen the loop.
@@ -1664,7 +1687,6 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
const LocationContext *LCtx = Pred->getLocationContext();
PrettyStackTraceLocationContext StackCrashInfo(LCtx);
currBldrCtx = &BldCtx;
-
// Check for NULL conditions; e.g. "for(;;)"
if (!Condition) {
BranchNodeBuilder NullCondBldr(Pred, Dst, BldCtx, DstT, DstF);
OpenPOWER on IntegriCloud