1 //===- unittests/Analysis/CFGTest.cpp - CFG tests -------------------------===// 2 // 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 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "CFGBuildResult.h" 10 #include "clang/ASTMatchers/ASTMatchFinder.h" 11 #include "clang/Analysis/CFG.h" 12 #include "clang/Tooling/Tooling.h" 13 #include "gtest/gtest.h" 14 #include <string> 15 #include <vector> 16 17 namespace clang { 18 namespace analysis { 19 namespace { 20 21 // Constructing a CFG for a range-based for over a dependent type fails (but 22 // should not crash). 23 TEST(CFG, RangeBasedForOverDependentType) { 24 const char *Code = "class Foo;\n" 25 "template <typename T>\n" 26 "void f(const T &Range) {\n" 27 " for (const Foo *TheFoo : Range) {\n" 28 " }\n" 29 "}\n"; 30 EXPECT_EQ(BuildResult::SawFunctionBody, BuildCFG(Code).getStatus()); 31 } 32 33 // Constructing a CFG containing a delete expression on a dependent type should 34 // not crash. 35 TEST(CFG, DeleteExpressionOnDependentType) { 36 const char *Code = "template<class T>\n" 37 "void f(T t) {\n" 38 " delete t;\n" 39 "}\n"; 40 EXPECT_EQ(BuildResult::BuiltCFG, BuildCFG(Code).getStatus()); 41 } 42 43 // Constructing a CFG on a function template with a variable of incomplete type 44 // should not crash. 45 TEST(CFG, VariableOfIncompleteType) { 46 const char *Code = "template<class T> void f() {\n" 47 " class Undefined;\n" 48 " Undefined u;\n" 49 "}\n"; 50 EXPECT_EQ(BuildResult::BuiltCFG, BuildCFG(Code).getStatus()); 51 } 52 53 TEST(CFG, IsLinear) { 54 auto expectLinear = [](bool IsLinear, const char *Code) { 55 BuildResult B = BuildCFG(Code); 56 EXPECT_EQ(BuildResult::BuiltCFG, B.getStatus()); 57 EXPECT_EQ(IsLinear, B.getCFG()->isLinear()); 58 }; 59 60 expectLinear(true, "void foo() {}"); 61 expectLinear(true, "void foo() { if (true) return; }"); 62 expectLinear(true, "void foo() { if constexpr (false); }"); 63 expectLinear(false, "void foo(bool coin) { if (coin) return; }"); 64 expectLinear(false, "void foo() { for(;;); }"); 65 expectLinear(false, "void foo() { do {} while (true); }"); 66 expectLinear(true, "void foo() { do {} while (false); }"); 67 expectLinear(true, "void foo() { foo(); }"); // Recursion is not our problem. 68 } 69 70 TEST(CFG, ElementRefIterator) { 71 const char *Code = R"(void f() { 72 int i; 73 int j; 74 i = 5; 75 i = 6; 76 j = 7; 77 })"; 78 79 BuildResult B = BuildCFG(Code); 80 EXPECT_EQ(BuildResult::BuiltCFG, B.getStatus()); 81 CFG *Cfg = B.getCFG(); 82 83 // [B2 (ENTRY)] 84 // Succs (1): B1 85 86 // [B1] 87 // 1: int i; 88 // 2: int j; 89 // 3: i = 5 90 // 4: i = 6 91 // 5: j = 7 92 // Preds (1): B2 93 // Succs (1): B0 94 95 // [B0 (EXIT)] 96 // Preds (1): B1 97 CFGBlock *MainBlock = *(Cfg->begin() + 1); 98 99 constexpr CFGBlock::ref_iterator::difference_type MainBlockSize = 4; 100 101 // The rest of this test looks totally insane, but there iterators are 102 // templates under the hood, to it's important to instantiate everything for 103 // proper converage. 104 105 // Non-reverse, non-const version 106 size_t Index = 0; 107 for (CFGBlock::CFGElementRef ElementRef : MainBlock->refs()) { 108 EXPECT_EQ(ElementRef.getParent(), MainBlock); 109 EXPECT_EQ(ElementRef.getIndexInBlock(), Index); 110 EXPECT_TRUE(ElementRef->getAs<CFGStmt>()); 111 EXPECT_TRUE((*ElementRef).getAs<CFGStmt>()); 112 EXPECT_EQ(ElementRef.getParent(), MainBlock); 113 ++Index; 114 } 115 EXPECT_TRUE(*MainBlock->ref_begin() < *(MainBlock->ref_begin() + 1)); 116 EXPECT_TRUE(*MainBlock->ref_begin() == *MainBlock->ref_begin()); 117 EXPECT_FALSE(*MainBlock->ref_begin() != *MainBlock->ref_begin()); 118 119 EXPECT_TRUE(MainBlock->ref_begin() < MainBlock->ref_begin() + 1); 120 EXPECT_TRUE(MainBlock->ref_begin() == MainBlock->ref_begin()); 121 EXPECT_FALSE(MainBlock->ref_begin() != MainBlock->ref_begin()); 122 EXPECT_EQ(MainBlock->ref_end() - MainBlock->ref_begin(), MainBlockSize + 1); 123 EXPECT_EQ(MainBlock->ref_end() - MainBlockSize - 1, MainBlock->ref_begin()); 124 EXPECT_EQ(MainBlock->ref_begin() + MainBlockSize + 1, MainBlock->ref_end()); 125 EXPECT_EQ(MainBlock->ref_begin()++, MainBlock->ref_begin()); 126 EXPECT_EQ(++(MainBlock->ref_begin()), MainBlock->ref_begin() + 1); 127 128 // Non-reverse, non-const version 129 const CFGBlock *CMainBlock = MainBlock; 130 Index = 0; 131 for (CFGBlock::ConstCFGElementRef ElementRef : CMainBlock->refs()) { 132 EXPECT_EQ(ElementRef.getParent(), CMainBlock); 133 EXPECT_EQ(ElementRef.getIndexInBlock(), Index); 134 EXPECT_TRUE(ElementRef->getAs<CFGStmt>()); 135 EXPECT_TRUE((*ElementRef).getAs<CFGStmt>()); 136 EXPECT_EQ(ElementRef.getParent(), MainBlock); 137 ++Index; 138 } 139 EXPECT_TRUE(*CMainBlock->ref_begin() < *(CMainBlock->ref_begin() + 1)); 140 EXPECT_TRUE(*CMainBlock->ref_begin() == *CMainBlock->ref_begin()); 141 EXPECT_FALSE(*CMainBlock->ref_begin() != *CMainBlock->ref_begin()); 142 143 EXPECT_TRUE(CMainBlock->ref_begin() < CMainBlock->ref_begin() + 1); 144 EXPECT_TRUE(CMainBlock->ref_begin() == CMainBlock->ref_begin()); 145 EXPECT_FALSE(CMainBlock->ref_begin() != CMainBlock->ref_begin()); 146 EXPECT_EQ(CMainBlock->ref_end() - CMainBlock->ref_begin(), MainBlockSize + 1); 147 EXPECT_EQ(CMainBlock->ref_end() - MainBlockSize - 1, CMainBlock->ref_begin()); 148 EXPECT_EQ(CMainBlock->ref_begin() + MainBlockSize + 1, CMainBlock->ref_end()); 149 EXPECT_EQ(CMainBlock->ref_begin()++, CMainBlock->ref_begin()); 150 EXPECT_EQ(++(CMainBlock->ref_begin()), CMainBlock->ref_begin() + 1); 151 152 // Reverse, non-const version 153 Index = MainBlockSize; 154 for (CFGBlock::CFGElementRef ElementRef : MainBlock->rrefs()) { 155 llvm::errs() << Index << '\n'; 156 EXPECT_EQ(ElementRef.getParent(), MainBlock); 157 EXPECT_EQ(ElementRef.getIndexInBlock(), Index); 158 EXPECT_TRUE(ElementRef->getAs<CFGStmt>()); 159 EXPECT_TRUE((*ElementRef).getAs<CFGStmt>()); 160 EXPECT_EQ(ElementRef.getParent(), MainBlock); 161 --Index; 162 } 163 EXPECT_FALSE(*MainBlock->rref_begin() < *(MainBlock->rref_begin() + 1)); 164 EXPECT_TRUE(*MainBlock->rref_begin() == *MainBlock->rref_begin()); 165 EXPECT_FALSE(*MainBlock->rref_begin() != *MainBlock->rref_begin()); 166 167 EXPECT_TRUE(MainBlock->rref_begin() < MainBlock->rref_begin() + 1); 168 EXPECT_TRUE(MainBlock->rref_begin() == MainBlock->rref_begin()); 169 EXPECT_FALSE(MainBlock->rref_begin() != MainBlock->rref_begin()); 170 EXPECT_EQ(MainBlock->rref_end() - MainBlock->rref_begin(), MainBlockSize + 1); 171 EXPECT_EQ(MainBlock->rref_end() - MainBlockSize - 1, MainBlock->rref_begin()); 172 EXPECT_EQ(MainBlock->rref_begin() + MainBlockSize + 1, MainBlock->rref_end()); 173 EXPECT_EQ(MainBlock->rref_begin()++, MainBlock->rref_begin()); 174 EXPECT_EQ(++(MainBlock->rref_begin()), MainBlock->rref_begin() + 1); 175 176 // Reverse, const version 177 Index = MainBlockSize; 178 for (CFGBlock::ConstCFGElementRef ElementRef : CMainBlock->rrefs()) { 179 EXPECT_EQ(ElementRef.getParent(), CMainBlock); 180 EXPECT_EQ(ElementRef.getIndexInBlock(), Index); 181 EXPECT_TRUE(ElementRef->getAs<CFGStmt>()); 182 EXPECT_TRUE((*ElementRef).getAs<CFGStmt>()); 183 EXPECT_EQ(ElementRef.getParent(), MainBlock); 184 --Index; 185 } 186 EXPECT_FALSE(*CMainBlock->rref_begin() < *(CMainBlock->rref_begin() + 1)); 187 EXPECT_TRUE(*CMainBlock->rref_begin() == *CMainBlock->rref_begin()); 188 EXPECT_FALSE(*CMainBlock->rref_begin() != *CMainBlock->rref_begin()); 189 190 EXPECT_TRUE(CMainBlock->rref_begin() < CMainBlock->rref_begin() + 1); 191 EXPECT_TRUE(CMainBlock->rref_begin() == CMainBlock->rref_begin()); 192 EXPECT_FALSE(CMainBlock->rref_begin() != CMainBlock->rref_begin()); 193 EXPECT_EQ(CMainBlock->rref_end() - CMainBlock->rref_begin(), 194 MainBlockSize + 1); 195 EXPECT_EQ(CMainBlock->rref_end() - MainBlockSize - 1, 196 CMainBlock->rref_begin()); 197 EXPECT_EQ(CMainBlock->rref_begin() + MainBlockSize + 1, 198 CMainBlock->rref_end()); 199 EXPECT_EQ(CMainBlock->rref_begin()++, CMainBlock->rref_begin()); 200 EXPECT_EQ(++(CMainBlock->rref_begin()), CMainBlock->rref_begin() + 1); 201 } 202 203 } // namespace 204 } // namespace analysis 205 } // namespace clang 206