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());
73 // Constructing a CFG with a dependent base should not crash.
74 TEST(CFG
, DependantBaseAddImplicitDtors
) {
75 const char *Code
= R
"(
82 struct Derived : public Base<T> {
86 CFG::BuildOptions Options
;
87 Options
.AddImplicitDtors
= true;
88 Options
.setAllAlwaysAdd();
89 EXPECT_EQ(BuildResult::BuiltCFG
,
90 BuildCFG(Code
, Options
, ast_matchers::hasName("~Derived<T>"))
95 auto expectLinear
= [](bool IsLinear
, const char *Code
) {
96 BuildResult B
= BuildCFG(Code
);
97 EXPECT_EQ(BuildResult::BuiltCFG
, B
.getStatus());
98 EXPECT_EQ(IsLinear
, B
.getCFG()->isLinear());
101 expectLinear(true, "void foo() {}");
102 expectLinear(true, "void foo() { if (true) return; }");
103 expectLinear(true, "void foo() { if constexpr (false); }");
104 expectLinear(false, "void foo(bool coin) { if (coin) return; }");
105 expectLinear(false, "void foo() { for(;;); }");
106 expectLinear(false, "void foo() { do {} while (true); }");
107 expectLinear(true, "void foo() { do {} while (false); }");
108 expectLinear(true, "void foo() { foo(); }"); // Recursion is not our problem.
111 TEST(CFG
, ElementRefIterator
) {
112 const char *Code
= R
"(void f() {
120 BuildResult B
= BuildCFG(Code
);
121 EXPECT_EQ(BuildResult::BuiltCFG
, B
.getStatus());
122 CFG
*Cfg
= B
.getCFG();
138 CFGBlock
*MainBlock
= *(Cfg
->begin() + 1);
140 constexpr CFGBlock::ref_iterator::difference_type MainBlockSize
= 4;
142 // The rest of this test looks totally insane, but there iterators are
143 // templates under the hood, to it's important to instantiate everything for
146 // Non-reverse, non-const version
148 for (CFGBlock::CFGElementRef ElementRef
: MainBlock
->refs()) {
149 EXPECT_EQ(ElementRef
.getParent(), MainBlock
);
150 EXPECT_EQ(ElementRef
.getIndexInBlock(), Index
);
151 EXPECT_TRUE(ElementRef
->getAs
<CFGStmt
>());
152 EXPECT_TRUE((*ElementRef
).getAs
<CFGStmt
>());
153 EXPECT_EQ(ElementRef
.getParent(), MainBlock
);
156 EXPECT_TRUE(*MainBlock
->ref_begin() < *(MainBlock
->ref_begin() + 1));
157 EXPECT_TRUE(*MainBlock
->ref_begin() == *MainBlock
->ref_begin());
158 EXPECT_FALSE(*MainBlock
->ref_begin() != *MainBlock
->ref_begin());
160 EXPECT_TRUE(MainBlock
->ref_begin() < MainBlock
->ref_begin() + 1);
161 EXPECT_TRUE(MainBlock
->ref_begin() == MainBlock
->ref_begin());
162 EXPECT_FALSE(MainBlock
->ref_begin() != MainBlock
->ref_begin());
163 EXPECT_EQ(MainBlock
->ref_end() - MainBlock
->ref_begin(), MainBlockSize
+ 1);
164 EXPECT_EQ(MainBlock
->ref_end() - MainBlockSize
- 1, MainBlock
->ref_begin());
165 EXPECT_EQ(MainBlock
->ref_begin() + MainBlockSize
+ 1, MainBlock
->ref_end());
166 EXPECT_EQ(MainBlock
->ref_begin()++, MainBlock
->ref_begin());
167 EXPECT_EQ(++(MainBlock
->ref_begin()), MainBlock
->ref_begin() + 1);
169 // Non-reverse, non-const version
170 const CFGBlock
*CMainBlock
= MainBlock
;
172 for (CFGBlock::ConstCFGElementRef ElementRef
: CMainBlock
->refs()) {
173 EXPECT_EQ(ElementRef
.getParent(), CMainBlock
);
174 EXPECT_EQ(ElementRef
.getIndexInBlock(), Index
);
175 EXPECT_TRUE(ElementRef
->getAs
<CFGStmt
>());
176 EXPECT_TRUE((*ElementRef
).getAs
<CFGStmt
>());
177 EXPECT_EQ(ElementRef
.getParent(), MainBlock
);
180 EXPECT_TRUE(*CMainBlock
->ref_begin() < *(CMainBlock
->ref_begin() + 1));
181 EXPECT_TRUE(*CMainBlock
->ref_begin() == *CMainBlock
->ref_begin());
182 EXPECT_FALSE(*CMainBlock
->ref_begin() != *CMainBlock
->ref_begin());
184 EXPECT_TRUE(CMainBlock
->ref_begin() < CMainBlock
->ref_begin() + 1);
185 EXPECT_TRUE(CMainBlock
->ref_begin() == CMainBlock
->ref_begin());
186 EXPECT_FALSE(CMainBlock
->ref_begin() != CMainBlock
->ref_begin());
187 EXPECT_EQ(CMainBlock
->ref_end() - CMainBlock
->ref_begin(), MainBlockSize
+ 1);
188 EXPECT_EQ(CMainBlock
->ref_end() - MainBlockSize
- 1, CMainBlock
->ref_begin());
189 EXPECT_EQ(CMainBlock
->ref_begin() + MainBlockSize
+ 1, CMainBlock
->ref_end());
190 EXPECT_EQ(CMainBlock
->ref_begin()++, CMainBlock
->ref_begin());
191 EXPECT_EQ(++(CMainBlock
->ref_begin()), CMainBlock
->ref_begin() + 1);
193 // Reverse, non-const version
194 Index
= MainBlockSize
;
195 for (CFGBlock::CFGElementRef ElementRef
: MainBlock
->rrefs()) {
196 llvm::errs() << Index
<< '\n';
197 EXPECT_EQ(ElementRef
.getParent(), MainBlock
);
198 EXPECT_EQ(ElementRef
.getIndexInBlock(), Index
);
199 EXPECT_TRUE(ElementRef
->getAs
<CFGStmt
>());
200 EXPECT_TRUE((*ElementRef
).getAs
<CFGStmt
>());
201 EXPECT_EQ(ElementRef
.getParent(), MainBlock
);
204 EXPECT_FALSE(*MainBlock
->rref_begin() < *(MainBlock
->rref_begin() + 1));
205 EXPECT_TRUE(*MainBlock
->rref_begin() == *MainBlock
->rref_begin());
206 EXPECT_FALSE(*MainBlock
->rref_begin() != *MainBlock
->rref_begin());
208 EXPECT_TRUE(MainBlock
->rref_begin() < MainBlock
->rref_begin() + 1);
209 EXPECT_TRUE(MainBlock
->rref_begin() == MainBlock
->rref_begin());
210 EXPECT_FALSE(MainBlock
->rref_begin() != MainBlock
->rref_begin());
211 EXPECT_EQ(MainBlock
->rref_end() - MainBlock
->rref_begin(), MainBlockSize
+ 1);
212 EXPECT_EQ(MainBlock
->rref_end() - MainBlockSize
- 1, MainBlock
->rref_begin());
213 EXPECT_EQ(MainBlock
->rref_begin() + MainBlockSize
+ 1, MainBlock
->rref_end());
214 EXPECT_EQ(MainBlock
->rref_begin()++, MainBlock
->rref_begin());
215 EXPECT_EQ(++(MainBlock
->rref_begin()), MainBlock
->rref_begin() + 1);
217 // Reverse, const version
218 Index
= MainBlockSize
;
219 for (CFGBlock::ConstCFGElementRef ElementRef
: CMainBlock
->rrefs()) {
220 EXPECT_EQ(ElementRef
.getParent(), CMainBlock
);
221 EXPECT_EQ(ElementRef
.getIndexInBlock(), Index
);
222 EXPECT_TRUE(ElementRef
->getAs
<CFGStmt
>());
223 EXPECT_TRUE((*ElementRef
).getAs
<CFGStmt
>());
224 EXPECT_EQ(ElementRef
.getParent(), MainBlock
);
227 EXPECT_FALSE(*CMainBlock
->rref_begin() < *(CMainBlock
->rref_begin() + 1));
228 EXPECT_TRUE(*CMainBlock
->rref_begin() == *CMainBlock
->rref_begin());
229 EXPECT_FALSE(*CMainBlock
->rref_begin() != *CMainBlock
->rref_begin());
231 EXPECT_TRUE(CMainBlock
->rref_begin() < CMainBlock
->rref_begin() + 1);
232 EXPECT_TRUE(CMainBlock
->rref_begin() == CMainBlock
->rref_begin());
233 EXPECT_FALSE(CMainBlock
->rref_begin() != CMainBlock
->rref_begin());
234 EXPECT_EQ(CMainBlock
->rref_end() - CMainBlock
->rref_begin(),
236 EXPECT_EQ(CMainBlock
->rref_end() - MainBlockSize
- 1,
237 CMainBlock
->rref_begin());
238 EXPECT_EQ(CMainBlock
->rref_begin() + MainBlockSize
+ 1,
239 CMainBlock
->rref_end());
240 EXPECT_EQ(CMainBlock
->rref_begin()++, CMainBlock
->rref_begin());
241 EXPECT_EQ(++(CMainBlock
->rref_begin()), CMainBlock
->rref_begin() + 1);
244 TEST(CFG
, Worklists
) {
245 const char *Code
= "int f(bool cond) {\n"
251 BuildResult B
= BuildCFG(Code
);
252 EXPECT_EQ(BuildResult::BuiltCFG
, B
.getStatus());
253 const FunctionDecl
*Func
= B
.getFunc();
254 AnalysisDeclContext
AC(nullptr, Func
);
255 auto *CFG
= AC
.getCFG();
257 std::vector
<const CFGBlock
*> ReferenceOrder
;
258 for (const auto *B
: *AC
.getAnalysis
<PostOrderCFGView
>())
259 ReferenceOrder
.push_back(B
);
262 ForwardDataflowWorklist
ForwardWorklist(*CFG
, AC
);
263 for (const auto *B
: *CFG
)
264 ForwardWorklist
.enqueueBlock(B
);
266 std::vector
<const CFGBlock
*> ForwardNodes
;
267 while (const CFGBlock
*B
= ForwardWorklist
.dequeue())
268 ForwardNodes
.push_back(B
);
270 EXPECT_EQ(ForwardNodes
.size(), ReferenceOrder
.size());
271 EXPECT_TRUE(std::equal(ReferenceOrder
.begin(), ReferenceOrder
.end(),
272 ForwardNodes
.begin()));
275 std::reverse(ReferenceOrder
.begin(), ReferenceOrder
.end());
278 BackwardDataflowWorklist
BackwardWorklist(*CFG
, AC
);
279 for (const auto *B
: *CFG
)
280 BackwardWorklist
.enqueueBlock(B
);
282 std::vector
<const CFGBlock
*> BackwardNodes
;
283 while (const CFGBlock
*B
= BackwardWorklist
.dequeue())
284 BackwardNodes
.push_back(B
);
286 EXPECT_EQ(BackwardNodes
.size(), ReferenceOrder
.size());
287 EXPECT_TRUE(std::equal(ReferenceOrder
.begin(), ReferenceOrder
.end(),
288 BackwardNodes
.begin()));
293 } // namespace analysis