1 //===- unittests/Analysis/CFGTest.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/AST/Decl.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 #include "clang/Analysis/AnalysisDeclContext.h"
13 #include "clang/Analysis/CFG.h"
14 #include "clang/Analysis/FlowSensitive/DataflowWorklist.h"
15 #include "clang/Tooling/Tooling.h"
16 #include "gtest/gtest.h"
25 // Constructing a CFG for a range-based for over a dependent type fails (but
27 TEST(CFG
, RangeBasedForOverDependentType
) {
28 const char *Code
= "class Foo;\n"
29 "template <typename T>\n"
30 "void f(const T &Range) {\n"
31 " for (const Foo *TheFoo : Range) {\n"
34 EXPECT_EQ(BuildResult::SawFunctionBody
, BuildCFG(Code
).getStatus());
37 TEST(CFG
, StaticInitializerLastCondition
) {
38 const char *Code
= "void f() {\n"
40 " static int j = 3 ;\n"
42 CFG::BuildOptions Options
;
43 Options
.AddStaticInitBranches
= true;
44 Options
.setAllAlwaysAdd();
45 BuildResult B
= BuildCFG(Code
, Options
);
46 EXPECT_EQ(BuildResult::BuiltCFG
, B
.getStatus());
47 EXPECT_EQ(1u, B
.getCFG()->getEntry().succ_size());
48 CFGBlock
*Block
= *B
.getCFG()->getEntry().succ_begin();
49 EXPECT_TRUE(isa
<DeclStmt
>(Block
->getTerminatorStmt()));
50 EXPECT_EQ(nullptr, Block
->getLastCondition());
53 // Constructing a CFG containing a delete expression on a dependent type should
55 TEST(CFG
, DeleteExpressionOnDependentType
) {
56 const char *Code
= "template<class T>\n"
60 EXPECT_EQ(BuildResult::BuiltCFG
, BuildCFG(Code
).getStatus());
63 // Constructing a CFG on a function template with a variable of incomplete type
65 TEST(CFG
, VariableOfIncompleteType
) {
66 const char *Code
= "template<class T> void f() {\n"
70 EXPECT_EQ(BuildResult::BuiltCFG
, BuildCFG(Code
).getStatus());
74 auto expectLinear
= [](bool IsLinear
, const char *Code
) {
75 BuildResult B
= BuildCFG(Code
);
76 EXPECT_EQ(BuildResult::BuiltCFG
, B
.getStatus());
77 EXPECT_EQ(IsLinear
, B
.getCFG()->isLinear());
80 expectLinear(true, "void foo() {}");
81 expectLinear(true, "void foo() { if (true) return; }");
82 expectLinear(true, "void foo() { if constexpr (false); }");
83 expectLinear(false, "void foo(bool coin) { if (coin) return; }");
84 expectLinear(false, "void foo() { for(;;); }");
85 expectLinear(false, "void foo() { do {} while (true); }");
86 expectLinear(true, "void foo() { do {} while (false); }");
87 expectLinear(true, "void foo() { foo(); }"); // Recursion is not our problem.
90 TEST(CFG
, ElementRefIterator
) {
91 const char *Code
= R
"(void f() {
99 BuildResult B
= BuildCFG(Code
);
100 EXPECT_EQ(BuildResult::BuiltCFG
, B
.getStatus());
101 CFG
*Cfg
= B
.getCFG();
117 CFGBlock
*MainBlock
= *(Cfg
->begin() + 1);
119 constexpr CFGBlock::ref_iterator::difference_type MainBlockSize
= 4;
121 // The rest of this test looks totally insane, but there iterators are
122 // templates under the hood, to it's important to instantiate everything for
125 // Non-reverse, non-const version
127 for (CFGBlock::CFGElementRef ElementRef
: MainBlock
->refs()) {
128 EXPECT_EQ(ElementRef
.getParent(), MainBlock
);
129 EXPECT_EQ(ElementRef
.getIndexInBlock(), Index
);
130 EXPECT_TRUE(ElementRef
->getAs
<CFGStmt
>());
131 EXPECT_TRUE((*ElementRef
).getAs
<CFGStmt
>());
132 EXPECT_EQ(ElementRef
.getParent(), MainBlock
);
135 EXPECT_TRUE(*MainBlock
->ref_begin() < *(MainBlock
->ref_begin() + 1));
136 EXPECT_TRUE(*MainBlock
->ref_begin() == *MainBlock
->ref_begin());
137 EXPECT_FALSE(*MainBlock
->ref_begin() != *MainBlock
->ref_begin());
139 EXPECT_TRUE(MainBlock
->ref_begin() < MainBlock
->ref_begin() + 1);
140 EXPECT_TRUE(MainBlock
->ref_begin() == MainBlock
->ref_begin());
141 EXPECT_FALSE(MainBlock
->ref_begin() != MainBlock
->ref_begin());
142 EXPECT_EQ(MainBlock
->ref_end() - MainBlock
->ref_begin(), MainBlockSize
+ 1);
143 EXPECT_EQ(MainBlock
->ref_end() - MainBlockSize
- 1, MainBlock
->ref_begin());
144 EXPECT_EQ(MainBlock
->ref_begin() + MainBlockSize
+ 1, MainBlock
->ref_end());
145 EXPECT_EQ(MainBlock
->ref_begin()++, MainBlock
->ref_begin());
146 EXPECT_EQ(++(MainBlock
->ref_begin()), MainBlock
->ref_begin() + 1);
148 // Non-reverse, non-const version
149 const CFGBlock
*CMainBlock
= MainBlock
;
151 for (CFGBlock::ConstCFGElementRef ElementRef
: CMainBlock
->refs()) {
152 EXPECT_EQ(ElementRef
.getParent(), CMainBlock
);
153 EXPECT_EQ(ElementRef
.getIndexInBlock(), Index
);
154 EXPECT_TRUE(ElementRef
->getAs
<CFGStmt
>());
155 EXPECT_TRUE((*ElementRef
).getAs
<CFGStmt
>());
156 EXPECT_EQ(ElementRef
.getParent(), MainBlock
);
159 EXPECT_TRUE(*CMainBlock
->ref_begin() < *(CMainBlock
->ref_begin() + 1));
160 EXPECT_TRUE(*CMainBlock
->ref_begin() == *CMainBlock
->ref_begin());
161 EXPECT_FALSE(*CMainBlock
->ref_begin() != *CMainBlock
->ref_begin());
163 EXPECT_TRUE(CMainBlock
->ref_begin() < CMainBlock
->ref_begin() + 1);
164 EXPECT_TRUE(CMainBlock
->ref_begin() == CMainBlock
->ref_begin());
165 EXPECT_FALSE(CMainBlock
->ref_begin() != CMainBlock
->ref_begin());
166 EXPECT_EQ(CMainBlock
->ref_end() - CMainBlock
->ref_begin(), MainBlockSize
+ 1);
167 EXPECT_EQ(CMainBlock
->ref_end() - MainBlockSize
- 1, CMainBlock
->ref_begin());
168 EXPECT_EQ(CMainBlock
->ref_begin() + MainBlockSize
+ 1, CMainBlock
->ref_end());
169 EXPECT_EQ(CMainBlock
->ref_begin()++, CMainBlock
->ref_begin());
170 EXPECT_EQ(++(CMainBlock
->ref_begin()), CMainBlock
->ref_begin() + 1);
172 // Reverse, non-const version
173 Index
= MainBlockSize
;
174 for (CFGBlock::CFGElementRef ElementRef
: MainBlock
->rrefs()) {
175 llvm::errs() << Index
<< '\n';
176 EXPECT_EQ(ElementRef
.getParent(), MainBlock
);
177 EXPECT_EQ(ElementRef
.getIndexInBlock(), Index
);
178 EXPECT_TRUE(ElementRef
->getAs
<CFGStmt
>());
179 EXPECT_TRUE((*ElementRef
).getAs
<CFGStmt
>());
180 EXPECT_EQ(ElementRef
.getParent(), MainBlock
);
183 EXPECT_FALSE(*MainBlock
->rref_begin() < *(MainBlock
->rref_begin() + 1));
184 EXPECT_TRUE(*MainBlock
->rref_begin() == *MainBlock
->rref_begin());
185 EXPECT_FALSE(*MainBlock
->rref_begin() != *MainBlock
->rref_begin());
187 EXPECT_TRUE(MainBlock
->rref_begin() < MainBlock
->rref_begin() + 1);
188 EXPECT_TRUE(MainBlock
->rref_begin() == MainBlock
->rref_begin());
189 EXPECT_FALSE(MainBlock
->rref_begin() != MainBlock
->rref_begin());
190 EXPECT_EQ(MainBlock
->rref_end() - MainBlock
->rref_begin(), MainBlockSize
+ 1);
191 EXPECT_EQ(MainBlock
->rref_end() - MainBlockSize
- 1, MainBlock
->rref_begin());
192 EXPECT_EQ(MainBlock
->rref_begin() + MainBlockSize
+ 1, MainBlock
->rref_end());
193 EXPECT_EQ(MainBlock
->rref_begin()++, MainBlock
->rref_begin());
194 EXPECT_EQ(++(MainBlock
->rref_begin()), MainBlock
->rref_begin() + 1);
196 // Reverse, const version
197 Index
= MainBlockSize
;
198 for (CFGBlock::ConstCFGElementRef ElementRef
: CMainBlock
->rrefs()) {
199 EXPECT_EQ(ElementRef
.getParent(), CMainBlock
);
200 EXPECT_EQ(ElementRef
.getIndexInBlock(), Index
);
201 EXPECT_TRUE(ElementRef
->getAs
<CFGStmt
>());
202 EXPECT_TRUE((*ElementRef
).getAs
<CFGStmt
>());
203 EXPECT_EQ(ElementRef
.getParent(), MainBlock
);
206 EXPECT_FALSE(*CMainBlock
->rref_begin() < *(CMainBlock
->rref_begin() + 1));
207 EXPECT_TRUE(*CMainBlock
->rref_begin() == *CMainBlock
->rref_begin());
208 EXPECT_FALSE(*CMainBlock
->rref_begin() != *CMainBlock
->rref_begin());
210 EXPECT_TRUE(CMainBlock
->rref_begin() < CMainBlock
->rref_begin() + 1);
211 EXPECT_TRUE(CMainBlock
->rref_begin() == CMainBlock
->rref_begin());
212 EXPECT_FALSE(CMainBlock
->rref_begin() != CMainBlock
->rref_begin());
213 EXPECT_EQ(CMainBlock
->rref_end() - CMainBlock
->rref_begin(),
215 EXPECT_EQ(CMainBlock
->rref_end() - MainBlockSize
- 1,
216 CMainBlock
->rref_begin());
217 EXPECT_EQ(CMainBlock
->rref_begin() + MainBlockSize
+ 1,
218 CMainBlock
->rref_end());
219 EXPECT_EQ(CMainBlock
->rref_begin()++, CMainBlock
->rref_begin());
220 EXPECT_EQ(++(CMainBlock
->rref_begin()), CMainBlock
->rref_begin() + 1);
223 TEST(CFG
, Worklists
) {
224 const char *Code
= "int f(bool cond) {\n"
230 BuildResult B
= BuildCFG(Code
);
231 EXPECT_EQ(BuildResult::BuiltCFG
, B
.getStatus());
232 const FunctionDecl
*Func
= B
.getFunc();
233 AnalysisDeclContext
AC(nullptr, Func
);
234 auto *CFG
= AC
.getCFG();
236 std::vector
<const CFGBlock
*> ReferenceOrder
;
237 for (const auto *B
: *AC
.getAnalysis
<PostOrderCFGView
>())
238 ReferenceOrder
.push_back(B
);
241 ForwardDataflowWorklist
ForwardWorklist(*CFG
, AC
);
242 for (const auto *B
: *CFG
)
243 ForwardWorklist
.enqueueBlock(B
);
245 std::vector
<const CFGBlock
*> ForwardNodes
;
246 while (const CFGBlock
*B
= ForwardWorklist
.dequeue())
247 ForwardNodes
.push_back(B
);
249 EXPECT_EQ(ForwardNodes
.size(), ReferenceOrder
.size());
250 EXPECT_TRUE(std::equal(ReferenceOrder
.begin(), ReferenceOrder
.end(),
251 ForwardNodes
.begin()));
254 std::reverse(ReferenceOrder
.begin(), ReferenceOrder
.end());
257 BackwardDataflowWorklist
BackwardWorklist(*CFG
, AC
);
258 for (const auto *B
: *CFG
)
259 BackwardWorklist
.enqueueBlock(B
);
261 std::vector
<const CFGBlock
*> BackwardNodes
;
262 while (const CFGBlock
*B
= BackwardWorklist
.dequeue())
263 BackwardNodes
.push_back(B
);
265 EXPECT_EQ(BackwardNodes
.size(), ReferenceOrder
.size());
266 EXPECT_TRUE(std::equal(ReferenceOrder
.begin(), ReferenceOrder
.end(),
267 BackwardNodes
.begin()));
272 } // namespace analysis