CFGTest.cpp 8.1 KB

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