1 //===- unittests/Analysis/CFGDominatorTree.cpp - CFG tests ----------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "CFGBuildResult.h"
10 #include "clang/Analysis/Analyses/Dominators.h"
11 #include "gtest/gtest.h"
17 TEST(CFGDominatorTree
, DomTree
) {
18 const char *Code
= R
"(enum Kind {
28 BuildResult Result
= BuildCFG(Code
);
29 EXPECT_EQ(BuildResult::BuiltCFG
, Result
.getStatus());
31 // [B3 (ENTRY)] -> [B1] -> [B2] -> [B0 (EXIT)]
34 CFG
*cfg
= Result
.getCFG();
36 // Basic correctness checks.
37 EXPECT_EQ(cfg
->size(), 4u);
39 CFGBlock
*ExitBlock
= *cfg
->begin();
40 EXPECT_EQ(ExitBlock
, &cfg
->getExit());
42 CFGBlock
*SwitchBlock
= *(cfg
->begin() + 1);
44 CFGBlock
*CaseABlock
= *(cfg
->begin() + 2);
46 CFGBlock
*EntryBlock
= *(cfg
->begin() + 3);
47 EXPECT_EQ(EntryBlock
, &cfg
->getEntry());
49 // Test the dominator tree.
51 Dom
.buildDominatorTree(cfg
);
53 EXPECT_TRUE(Dom
.dominates(ExitBlock
, ExitBlock
));
54 EXPECT_FALSE(Dom
.properlyDominates(ExitBlock
, ExitBlock
));
55 EXPECT_TRUE(Dom
.dominates(CaseABlock
, ExitBlock
));
56 EXPECT_TRUE(Dom
.dominates(SwitchBlock
, ExitBlock
));
57 EXPECT_TRUE(Dom
.dominates(EntryBlock
, ExitBlock
));
59 EXPECT_TRUE(Dom
.dominates(CaseABlock
, CaseABlock
));
60 EXPECT_FALSE(Dom
.properlyDominates(CaseABlock
, CaseABlock
));
61 EXPECT_TRUE(Dom
.dominates(SwitchBlock
, CaseABlock
));
62 EXPECT_TRUE(Dom
.dominates(EntryBlock
, CaseABlock
));
64 EXPECT_TRUE(Dom
.dominates(SwitchBlock
, SwitchBlock
));
65 EXPECT_FALSE(Dom
.properlyDominates(SwitchBlock
, SwitchBlock
));
66 EXPECT_TRUE(Dom
.dominates(EntryBlock
, SwitchBlock
));
68 EXPECT_TRUE(Dom
.dominates(EntryBlock
, EntryBlock
));
69 EXPECT_FALSE(Dom
.properlyDominates(EntryBlock
, EntryBlock
));
71 // Test the post dominator tree.
73 CFGPostDomTree PostDom
;
74 PostDom
.buildDominatorTree(cfg
);
76 EXPECT_TRUE(PostDom
.dominates(ExitBlock
, EntryBlock
));
77 EXPECT_TRUE(PostDom
.dominates(CaseABlock
, EntryBlock
));
78 EXPECT_TRUE(PostDom
.dominates(SwitchBlock
, EntryBlock
));
79 EXPECT_TRUE(PostDom
.dominates(EntryBlock
, EntryBlock
));
80 EXPECT_FALSE(Dom
.properlyDominates(EntryBlock
, EntryBlock
));
82 EXPECT_TRUE(PostDom
.dominates(ExitBlock
, SwitchBlock
));
83 EXPECT_TRUE(PostDom
.dominates(CaseABlock
, SwitchBlock
));
84 EXPECT_TRUE(PostDom
.dominates(SwitchBlock
, SwitchBlock
));
85 EXPECT_FALSE(Dom
.properlyDominates(SwitchBlock
, SwitchBlock
));
87 EXPECT_TRUE(PostDom
.dominates(ExitBlock
, CaseABlock
));
88 EXPECT_TRUE(PostDom
.dominates(CaseABlock
, CaseABlock
));
89 EXPECT_FALSE(Dom
.properlyDominates(CaseABlock
, CaseABlock
));
91 EXPECT_TRUE(PostDom
.dominates(ExitBlock
, ExitBlock
));
92 EXPECT_FALSE(Dom
.properlyDominates(ExitBlock
, ExitBlock
));
94 // Tests for the post dominator tree's virtual root.
95 EXPECT_TRUE(PostDom
.dominates(nullptr, EntryBlock
));
96 EXPECT_TRUE(PostDom
.dominates(nullptr, SwitchBlock
));
97 EXPECT_TRUE(PostDom
.dominates(nullptr, CaseABlock
));
98 EXPECT_TRUE(PostDom
.dominates(nullptr, ExitBlock
));
101 TEST(CFGDominatorTree
, ControlDependency
) {
102 const char *Code
= R
"(bool coin();
104 void funcWithBranch() {
114 BuildResult Result
= BuildCFG(Code
);
115 EXPECT_EQ(BuildResult::BuiltCFG
, Result
.getStatus());
118 // [B5 (ENTRY)] -> [B4] -> [B3] -> [B2] -> [B1] -> [B0 (EXIT)]
120 // \ -------------> /
121 // ------------------------------>
123 CFG
*cfg
= Result
.getCFG();
125 // Basic correctness checks.
126 EXPECT_EQ(cfg
->size(), 6u);
128 CFGBlock
*ExitBlock
= *cfg
->begin();
129 EXPECT_EQ(ExitBlock
, &cfg
->getExit());
131 CFGBlock
*NullDerefBlock
= *(cfg
->begin() + 1);
133 CFGBlock
*SecondThenBlock
= *(cfg
->begin() + 2);
135 CFGBlock
*SecondIfBlock
= *(cfg
->begin() + 3);
137 CFGBlock
*FirstIfBlock
= *(cfg
->begin() + 4);
139 CFGBlock
*EntryBlock
= *(cfg
->begin() + 5);
140 EXPECT_EQ(EntryBlock
, &cfg
->getEntry());
142 ControlDependencyCalculator
Control(cfg
);
144 EXPECT_TRUE(Control
.isControlDependent(SecondThenBlock
, SecondIfBlock
));
145 EXPECT_TRUE(Control
.isControlDependent(SecondIfBlock
, FirstIfBlock
));
146 EXPECT_FALSE(Control
.isControlDependent(NullDerefBlock
, SecondIfBlock
));
149 TEST(CFGDominatorTree
, ControlDependencyWithLoops
) {
150 const char *Code
= R
"(int test3() {
166 BuildResult Result
= BuildCFG(Code
);
167 EXPECT_EQ(BuildResult::BuiltCFG
, Result
.getStatus());
171 // [B8 (ENTRY)] -> [B7] -> [B6] ---> [B5] -> [B4] -> [B3]
173 // \ | <-------------
175 // --------> [B1] -> [B0 (EXIT)]
177 CFG
*cfg
= Result
.getCFG();
179 ControlDependencyCalculator
Control(cfg
);
181 auto GetBlock
= [cfg
] (unsigned Index
) -> CFGBlock
* {
182 assert(Index
< cfg
->size());
183 return *(cfg
->begin() + Index
);
186 // While not immediately obvious, the second block in fact post dominates the
187 // fifth, hence B5 is not a control dependency of 2.
188 EXPECT_FALSE(Control
.isControlDependent(GetBlock(5), GetBlock(2)));
193 } // namespace analysis