summaryrefslogtreecommitdiffstats
path: root/clang/unittests/Analysis/CFGTest.cpp
diff options
context:
space:
mode:
authorKristof Umann <dkszelethus@gmail.com>2019-07-05 09:52:00 +0000
committerKristof Umann <dkszelethus@gmail.com>2019-07-05 09:52:00 +0000
commitd5c9d9b6820f269f105ac278ba26d040630fe901 (patch)
treedaede4e4d2277e433a17ce6bc0e9f5d8a8387e32 /clang/unittests/Analysis/CFGTest.cpp
parentbb7e97d783efae225c97758f2ff186436ac8d86d (diff)
downloadbcm5719-llvm-d5c9d9b6820f269f105ac278ba26d040630fe901.tar.gz
bcm5719-llvm-d5c9d9b6820f269f105ac278ba26d040630fe901.zip
[CFG] Add a new function to get the proper condition of a CFGBlock
getTerminatorCondition() returned a condition that may be outside of the block, while the new function returns the proper one: if (A && B && C) {} Return C instead of A && B && C. Differential Revision: https://reviews.llvm.org/D63538 llvm-svn: 365177
Diffstat (limited to 'clang/unittests/Analysis/CFGTest.cpp')
-rw-r--r--clang/unittests/Analysis/CFGTest.cpp52
1 files changed, 52 insertions, 0 deletions
diff --git a/clang/unittests/Analysis/CFGTest.cpp b/clang/unittests/Analysis/CFGTest.cpp
index 2c2522d2620..69cf78b9737 100644
--- a/clang/unittests/Analysis/CFGTest.cpp
+++ b/clang/unittests/Analysis/CFGTest.cpp
@@ -117,6 +117,58 @@ TEST(CFG, IsLinear) {
expectLinear(true, "void foo() { foo(); }"); // Recursion is not our problem.
}
+TEST(CFG, ConditionExpr) {
+ const char *Code = R"(void f(bool A, bool B, bool C) {
+ if (A && B && C)
+ int x;
+ })";
+ BuildResult Result = BuildCFG(Code);
+ EXPECT_EQ(BuildResult::BuiltCFG, Result.getStatus());
+
+ // [B5 (ENTRY)] -> [B4] -> [B3] -> [B2] -> [B1] -> [B0 (EXIT)]
+ // \ \ \ /
+ // ------------------------------->
+
+ CFG *cfg = Result.getCFG();
+
+ auto GetBlock = [cfg] (unsigned Index) -> CFGBlock * {
+ assert(Index < cfg->size());
+ return *(cfg->begin() + Index);
+ };
+
+ auto GetExprText = [] (const Expr *E) -> std::string {
+ // It's very awkward trying to recover the actual expression text without
+ // a real source file, so use this as a workaround. We know that the
+ // condition expression looks like this:
+ //
+ // ImplicitCastExpr 0xd07bf8 '_Bool' <LValueToRValue>
+ // `-DeclRefExpr 0xd07bd8 '_Bool' lvalue ParmVar 0xd07960 'C' '_Bool'
+
+ assert(isa<ImplicitCastExpr>(E));
+ assert(++E->child_begin() == E->child_end());
+ const auto *D = dyn_cast<DeclRefExpr>(*E->child_begin());
+ return D->getFoundDecl()->getNameAsString();
+ };
+
+ EXPECT_EQ(GetBlock(1)->getLastCondition(), nullptr);
+ EXPECT_EQ(GetExprText(GetBlock(4)->getLastCondition()), "A");
+ EXPECT_EQ(GetExprText(GetBlock(3)->getLastCondition()), "B");
+ EXPECT_EQ(GetExprText(GetBlock(2)->getLastCondition()), "C");
+
+ //===--------------------------------------------------------------------===//
+
+ Code = R"(void foo(int x, int y) {
+ (void)(x + y);
+ })";
+ Result = BuildCFG(Code);
+ EXPECT_EQ(BuildResult::BuiltCFG, Result.getStatus());
+
+ // [B2 (ENTRY)] -> [B1] -> [B0 (EXIT)]
+
+ cfg = Result.getCFG();
+ EXPECT_EQ(GetBlock(1)->getLastCondition(), nullptr);
+}
+
} // namespace
} // namespace analysis
} // namespace clang
OpenPOWER on IntegriCloud