Files
TheRock/compiler/amd-llvm/clang/unittests/Analysis/FlowSensitive/CFGMatchSwitchTest.cpp
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

125 lines
4.1 KiB
C++

//===- unittests/Analysis/FlowSensitive/CFGMatchSwitchTest.cpp ------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "clang/Analysis/FlowSensitive/CFGMatchSwitch.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Stmt.h"
#include "clang/Analysis/CFG.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/StringRef.h"
#include "gtest/gtest.h"
using namespace clang;
using namespace dataflow;
using namespace ast_matchers;
namespace {
// State for tracking the number of matches on each kind of CFGElement by the
// CFGMatchSwitch. Currently only tracks CFGStmt and CFGInitializer.
struct CFGElementMatches {
unsigned StmtMatches = 0;
unsigned InitializerMatches = 0;
};
// Returns a match switch that counts the number of local variables
// (singly-declared) and fields initialized to the integer literal 42.
auto buildCFGMatchSwitch() {
return CFGMatchSwitchBuilder<CFGElementMatches>()
.CaseOfCFGStmt<DeclStmt>(
declStmt(hasSingleDecl(
varDecl(hasInitializer(integerLiteral(equals(42)))))),
[](const DeclStmt *, const MatchFinder::MatchResult &,
CFGElementMatches &Counter) { Counter.StmtMatches++; })
.CaseOfCFGInit<CXXCtorInitializer>(
cxxCtorInitializer(withInitializer(integerLiteral(equals(42)))),
[](const CXXCtorInitializer *, const MatchFinder::MatchResult &,
CFGElementMatches &Counter) { Counter.InitializerMatches++; })
.Build();
}
// Runs the match switch `MS` on the control flow graph generated from `Code`,
// tracking information in state `S`. For simplicity, this test utility is
// restricted to CFGs with a single control flow block (excluding entry and
// exit blocks) - generated by `Code` with sequential flow (i.e. no branching).
//
// Requirements:
//
// `Code` must contain a function named `f`, the body of this function will be
// used to generate the CFG.
template <typename State>
void applySwitchToCode(CFGMatchSwitch<State> &MS, State &S,
llvm::StringRef Code) {
auto Unit = tooling::buildASTFromCodeWithArgs(Code, {"-Wno-unused-value"});
auto &Ctx = Unit->getASTContext();
const auto *F = selectFirst<FunctionDecl>(
"f", match(functionDecl(isDefinition(), hasName("f")).bind("f"), Ctx));
CFG::BuildOptions BO;
BO.AddInitializers = true;
auto CFG = CFG::buildCFG(F, F->getBody(), &Ctx, BO);
auto CFGBlock = *CFG->getEntry().succ_begin();
for (auto &Elt : CFGBlock->Elements) {
MS(Elt, Ctx, S);
}
}
TEST(CFGMatchSwitchTest, NoInitializationTo42) {
CFGMatchSwitch<CFGElementMatches> Switch = buildCFGMatchSwitch();
CFGElementMatches Counter;
applySwitchToCode(Switch, Counter, R"(
void f() {
42;
}
)");
EXPECT_EQ(Counter.StmtMatches, 0u);
EXPECT_EQ(Counter.InitializerMatches, 0u);
}
TEST(CFGMatchSwitchTest, SingleLocalVarInitializationTo42) {
CFGMatchSwitch<CFGElementMatches> Switch = buildCFGMatchSwitch();
CFGElementMatches Counter;
applySwitchToCode(Switch, Counter, R"(
void f() {
int i = 42;
}
)");
EXPECT_EQ(Counter.StmtMatches, 1u);
EXPECT_EQ(Counter.InitializerMatches, 0u);
}
TEST(CFGMatchSwitchTest, SingleFieldInitializationTo42) {
CFGMatchSwitch<CFGElementMatches> Switch = buildCFGMatchSwitch();
CFGElementMatches Counter;
applySwitchToCode(Switch, Counter, R"(
struct f {
int i;
f(): i(42) {}
};
)");
EXPECT_EQ(Counter.StmtMatches, 0u);
EXPECT_EQ(Counter.InitializerMatches, 1u);
}
TEST(CFGMatchSwitchTest, LocalVarAndFieldInitializationTo42) {
CFGMatchSwitch<CFGElementMatches> Switch = buildCFGMatchSwitch();
CFGElementMatches Counter;
applySwitchToCode(Switch, Counter, R"(
struct f {
int i;
f(): i(42) {
int j = 42;
}
};
)");
EXPECT_EQ(Counter.StmtMatches, 1u);
EXPECT_EQ(Counter.InitializerMatches, 1u);
}
} // namespace