1 //===- unittests/Analysis/IntervalPartitionTest.cpp -----------------------===// 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 "clang/Analysis/Analyses/IntervalPartition.h" 10 #include "CFGBuildResult.h" 11 #include "gmock/gmock.h" 12 #include "gtest/gtest.h" 13 14 namespace clang { 15 namespace analysis { 16 namespace { 17 18 TEST(BuildInterval, PartitionSimpleOneInterval) { 19 20 const char *Code = R"(void f() { 21 int x = 3; 22 int y = 7; 23 x = y + x; 24 })"; 25 BuildResult Result = BuildCFG(Code); 26 EXPECT_EQ(BuildResult::BuiltCFG, Result.getStatus()); 27 28 CFG *cfg = Result.getCFG(); 29 30 // Basic correctness checks. 31 ASSERT_EQ(cfg->size(), 3u); 32 33 auto &EntryBlock = cfg->getEntry(); 34 35 CFGInterval I = buildInterval(*cfg, EntryBlock); 36 EXPECT_EQ(I.Blocks.size(), 3u); 37 } 38 39 TEST(BuildInterval, PartitionIfThenOneInterval) { 40 41 const char *Code = R"(void f() { 42 int x = 3; 43 if (x > 3) 44 x = 2; 45 else 46 x = 7; 47 x = x + x; 48 })"; 49 BuildResult Result = BuildCFG(Code); 50 EXPECT_EQ(BuildResult::BuiltCFG, Result.getStatus()); 51 52 CFG *cfg = Result.getCFG(); 53 54 // Basic correctness checks. 55 ASSERT_EQ(cfg->size(), 6u); 56 57 auto &EntryBlock = cfg->getEntry(); 58 59 CFGInterval I = buildInterval(*cfg, EntryBlock); 60 EXPECT_EQ(I.Blocks.size(), 6u); 61 } 62 63 using ::testing::UnorderedElementsAre; 64 65 TEST(BuildInterval, PartitionWhileMultipleIntervals) { 66 67 const char *Code = R"(void f() { 68 int x = 3; 69 while (x >= 3) 70 --x; 71 x = x + x; 72 })"; 73 BuildResult Result = BuildCFG(Code); 74 ASSERT_EQ(BuildResult::BuiltCFG, Result.getStatus()); 75 76 CFG *cfg = Result.getCFG(); 77 ASSERT_EQ(cfg->size(), 7u); 78 79 auto *EntryBlock = &cfg->getEntry(); 80 CFGBlock *InitXBlock = *EntryBlock->succ_begin(); 81 CFGBlock *LoopHeadBlock = *InitXBlock->succ_begin(); 82 83 CFGInterval I1 = buildInterval(*cfg, *EntryBlock); 84 EXPECT_THAT(I1.Blocks, UnorderedElementsAre(EntryBlock, InitXBlock)); 85 86 CFGInterval I2 = buildInterval(*cfg, *LoopHeadBlock); 87 EXPECT_EQ(I2.Blocks.size(), 5u); 88 } 89 90 TEST(PartitionIntoIntervals, PartitionIfThenOneInterval) { 91 const char *Code = R"(void f() { 92 int x = 3; 93 if (x > 3) 94 x = 2; 95 else 96 x = 7; 97 x = x + x; 98 })"; 99 BuildResult Result = BuildCFG(Code); 100 ASSERT_EQ(BuildResult::BuiltCFG, Result.getStatus()); 101 102 CFG *cfg = Result.getCFG(); 103 ASSERT_EQ(cfg->size(), 6u); 104 105 auto Intervals = partitionIntoIntervals(*cfg); 106 EXPECT_EQ(Intervals.size(), 1u); 107 } 108 109 TEST(PartitionIntoIntervals, PartitionWhileTwoIntervals) { 110 const char *Code = R"(void f() { 111 int x = 3; 112 while (x >= 3) 113 --x; 114 x = x + x; 115 })"; 116 BuildResult Result = BuildCFG(Code); 117 ASSERT_EQ(BuildResult::BuiltCFG, Result.getStatus()); 118 119 CFG *cfg = Result.getCFG(); 120 ASSERT_EQ(cfg->size(), 7u); 121 122 auto Intervals = partitionIntoIntervals(*cfg); 123 EXPECT_EQ(Intervals.size(), 2u); 124 } 125 126 TEST(PartitionIntoIntervals, PartitionNestedWhileThreeIntervals) { 127 const char *Code = R"(void f() { 128 int x = 3; 129 while (x >= 3) { 130 --x; 131 int y = x; 132 while (y > 0) --y; 133 } 134 x = x + x; 135 })"; 136 BuildResult Result = BuildCFG(Code); 137 ASSERT_EQ(BuildResult::BuiltCFG, Result.getStatus()); 138 139 CFG *cfg = Result.getCFG(); 140 auto Intervals = partitionIntoIntervals(*cfg); 141 EXPECT_EQ(Intervals.size(), 3u); 142 } 143 144 TEST(PartitionIntoIntervals, PartitionSequentialWhileThreeIntervals) { 145 const char *Code = R"(void f() { 146 int x = 3; 147 while (x >= 3) { 148 --x; 149 } 150 x = x + x; 151 int y = x; 152 while (y > 0) --y; 153 })"; 154 BuildResult Result = BuildCFG(Code); 155 ASSERT_EQ(BuildResult::BuiltCFG, Result.getStatus()); 156 157 CFG *cfg = Result.getCFG(); 158 auto Intervals = partitionIntoIntervals(*cfg); 159 EXPECT_EQ(Intervals.size(), 3u); 160 } 161 162 } // namespace 163 } // namespace analysis 164 } // namespace clang 165