summaryrefslogtreecommitdiffstats
path: root/clang/unittests/Analysis/CFGDominatorTree.cpp
diff options
context:
space:
mode:
authorKristof Umann <dkszelethus@gmail.com>2019-07-05 12:17:44 +0000
committerKristof Umann <dkszelethus@gmail.com>2019-07-05 12:17:44 +0000
commit5e17ee1e35e4535b51c749186ffbec694b06494b (patch)
treeaba47f3dfb78d06f7cb78c41b711b8b8773de907 /clang/unittests/Analysis/CFGDominatorTree.cpp
parent6884d5e0403cb082b52e560459687c9e5db61718 (diff)
downloadbcm5719-llvm-5e17ee1e35e4535b51c749186ffbec694b06494b.tar.gz
bcm5719-llvm-5e17ee1e35e4535b51c749186ffbec694b06494b.zip
[analyzer][IDF] Add a control dependency calculator + a new debug checker
I intend to improve the analyzer's bug reports by tracking condition expressions. 01 bool b = messyComputation(); 02 int i = 0; 03 if (b) // control dependency of the bug site, let's explain why we assume val 04 // to be true 05 10 / i; // warn: division by zero I'll detail this heuristic in the followup patch, strictly related to this one however: * Create the new ControlDependencyCalculator class that uses llvm::IDFCalculator to (lazily) calculate control dependencies for Clang's CFG. * A new debug checker debug.DumpControlDependencies is added for lit tests * Add unittests Differential Revision: https://reviews.llvm.org/D62619 llvm-svn: 365197
Diffstat (limited to 'clang/unittests/Analysis/CFGDominatorTree.cpp')
-rw-r--r--clang/unittests/Analysis/CFGDominatorTree.cpp91
1 files changed, 91 insertions, 0 deletions
diff --git a/clang/unittests/Analysis/CFGDominatorTree.cpp b/clang/unittests/Analysis/CFGDominatorTree.cpp
index 1df8c2f7d05..8cbd72c94e6 100644
--- a/clang/unittests/Analysis/CFGDominatorTree.cpp
+++ b/clang/unittests/Analysis/CFGDominatorTree.cpp
@@ -98,6 +98,97 @@ TEST(CFGDominatorTree, DomTree) {
EXPECT_TRUE(PostDom.dominates(nullptr, ExitBlock));
}
+TEST(CFGDominatorTree, ControlDependency) {
+ const char *Code = R"(bool coin();
+
+ void funcWithBranch() {
+ int x = 0;
+ if (coin()) {
+ if (coin()) {
+ x = 5;
+ }
+ int j = 10 / x;
+ (void)j;
+ }
+ };)";
+ BuildResult Result = BuildCFG(Code);
+ EXPECT_EQ(BuildResult::BuiltCFG, Result.getStatus());
+
+ // 1st if 2nd if
+ // [B5 (ENTRY)] -> [B4] -> [B3] -> [B2] -> [B1] -> [B0 (EXIT)]
+ // \ \ / /
+ // \ -------------> /
+ // ------------------------------>
+
+ CFG *cfg = Result.getCFG();
+
+ // Sanity checks.
+ EXPECT_EQ(cfg->size(), 6u);
+
+ CFGBlock *ExitBlock = *cfg->begin();
+ EXPECT_EQ(ExitBlock, &cfg->getExit());
+
+ CFGBlock *NullDerefBlock = *(cfg->begin() + 1);
+
+ CFGBlock *SecondThenBlock = *(cfg->begin() + 2);
+
+ CFGBlock *SecondIfBlock = *(cfg->begin() + 3);
+
+ CFGBlock *FirstIfBlock = *(cfg->begin() + 4);
+
+ CFGBlock *EntryBlock = *(cfg->begin() + 5);
+ EXPECT_EQ(EntryBlock, &cfg->getEntry());
+
+ ControlDependencyCalculator Control(cfg);
+
+ EXPECT_TRUE(Control.isControlDependent(SecondThenBlock, SecondIfBlock));
+ EXPECT_TRUE(Control.isControlDependent(SecondIfBlock, FirstIfBlock));
+ EXPECT_FALSE(Control.isControlDependent(NullDerefBlock, SecondIfBlock));
+}
+
+TEST(CFGDominatorTree, ControlDependencyWithLoops) {
+ const char *Code = R"(int test3() {
+ int x,y,z;
+
+ x = y = z = 1;
+ if (x > 0) {
+ while (x >= 0){
+ while (y >= x) {
+ x = x-1;
+ y = y/2;
+ }
+ }
+ }
+ z = y;
+
+ return 0;
+ })";
+ BuildResult Result = BuildCFG(Code);
+ EXPECT_EQ(BuildResult::BuiltCFG, Result.getStatus());
+
+ // <- [B2] <-
+ // / \
+ // [B8 (ENTRY)] -> [B7] -> [B6] ---> [B5] -> [B4] -> [B3]
+ // \ | \ /
+ // \ | <-------------
+ // \ \
+ // --------> [B1] -> [B0 (EXIT)]
+
+ CFG *cfg = Result.getCFG();
+
+ ControlDependencyCalculator Control(cfg);
+
+ auto GetBlock = [cfg] (unsigned Index) -> CFGBlock * {
+ assert(Index < cfg->size());
+ return *(cfg->begin() + Index);
+ };
+
+ // While not immediately obvious, the second block in fact post dominates the
+ // fifth, hence B5 is not a control dependency of 2.
+ EXPECT_FALSE(Control.isControlDependent(GetBlock(5), GetBlock(2)));
+}
+
+
} // namespace
} // namespace analysis
} // namespace clang
OpenPOWER on IntegriCloud