Files
TheRock/compiler/amd-llvm/clang/unittests/ScalableStaticAnalysisFramework/ASTEntityMappingTest.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

342 lines
9.5 KiB
C++

//===- ASTEntityMappingTest.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/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h"
#include "FindDecl.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Tooling/Tooling.h"
#include "gtest/gtest.h"
using namespace clang::ast_matchers;
namespace clang::ssaf {
namespace {
TEST(ASTEntityMappingTest, FunctionDecl) {
auto AST = tooling::buildASTFromCode(R"cpp(void foo() {})cpp");
auto &Ctx = AST->getASTContext();
const auto *FD = findFnByName("foo", Ctx);
ASSERT_NE(FD, nullptr);
auto EntityName = getEntityName(FD);
EXPECT_TRUE(EntityName.has_value());
}
TEST(ASTEntityMappingTest, VarDecl) {
auto AST = tooling::buildASTFromCode(R"cpp(int x = 42;)cpp");
auto &Ctx = AST->getASTContext();
const auto *VD = findDeclByName<VarDecl>("x", Ctx);
ASSERT_NE(VD, nullptr);
auto EntityName = getEntityName(VD);
EXPECT_TRUE(EntityName.has_value());
}
TEST(ASTEntityMappingTest, ParmVarDecl) {
auto AST = tooling::buildASTFromCode(R"cpp(void foo(int x) {})cpp");
auto &Ctx = AST->getASTContext();
const auto *FD = findFnByName("foo", Ctx);
ASSERT_NE(FD, nullptr);
ASSERT_EQ(FD->param_size(), 1u);
const auto *PVD = FD->getParamDecl(0);
ASSERT_NE(PVD, nullptr);
auto EntityName = getEntityName(PVD);
EXPECT_TRUE(EntityName.has_value());
}
TEST(ASTEntityMappingTest, RecordDecl) {
auto AST = tooling::buildASTFromCode(R"cpp(struct S {};)cpp");
auto &Ctx = AST->getASTContext();
const auto *RD = findDeclByName<RecordDecl>("S", Ctx);
ASSERT_NE(RD, nullptr);
auto EntityName = getEntityName(RD);
EXPECT_TRUE(EntityName.has_value());
}
TEST(ASTEntityMappingTest, FieldDecl) {
auto AST = tooling::buildASTFromCode(R"cpp(struct S { int field; };)cpp");
auto &Ctx = AST->getASTContext();
const auto *FD = findDeclByName<FieldDecl>("field", Ctx);
ASSERT_NE(FD, nullptr);
auto EntityName = getEntityName(FD);
EXPECT_TRUE(EntityName.has_value());
}
TEST(ASTEntityMappingTest, NullDecl) {
auto EntityName = getEntityName(nullptr);
EXPECT_FALSE(EntityName.has_value());
}
TEST(ASTEntityMappingTest, ImplicitDeclLambda) {
auto AST = tooling::buildASTFromCode(
R"cpp(
auto L = [](){};
)cpp",
"test.cpp", std::make_shared<PCHContainerOperations>());
auto &Ctx = AST->getASTContext();
auto Matcher = cxxRecordDecl(isImplicit()).bind("decl");
auto Matches = match(Matcher, Ctx);
ASSERT_GT(Matches.size(), 0u);
const auto *ImplCXXRD = Matches[0].getNodeAs<CXXRecordDecl>("decl");
ASSERT_NE(ImplCXXRD, nullptr);
auto EntityName = getEntityName(ImplCXXRD);
EXPECT_FALSE(EntityName.has_value());
}
TEST(ASTEntityMappingTest, BuiltinFunction) {
auto AST = tooling::buildASTFromCode(R"cpp(
void test() {
__builtin_memcpy(0, 0, 0);
}
)cpp");
auto &Ctx = AST->getASTContext();
// Find the builtin call
auto Matcher = callExpr().bind("call");
auto Matches = match(Matcher, Ctx);
ASSERT_EQ(Matches.size(), 1ul);
const auto *CE = Matches[0].getNodeAs<CallExpr>("call");
ASSERT_NE(CE, nullptr);
const auto *Callee = CE->getDirectCallee();
ASSERT_NE(Callee, nullptr);
ASSERT_NE(Callee->getBuiltinID(), 0u /* not a built-in */);
auto EntityName = getEntityName(Callee);
EXPECT_FALSE(EntityName.has_value());
}
TEST(ASTEntityMappingTest, UnsupportedDecl) {
auto AST = tooling::buildASTFromCode(R"cpp(namespace N {})cpp");
auto &Ctx = AST->getASTContext();
const auto *ND = findDeclByName<NamespaceDecl>("N", Ctx);
ASSERT_NE(ND, nullptr);
auto EntityName = getEntityName(ND);
EXPECT_FALSE(EntityName.has_value());
}
TEST(ASTEntityMappingTest, FunctionReturn) {
auto AST = tooling::buildASTFromCode(R"cpp(int foo() { return 42; })cpp");
auto &Ctx = AST->getASTContext();
const auto *FD = findFnByName("foo", Ctx);
ASSERT_NE(FD, nullptr);
auto EntityName = getEntityNameForReturn(FD);
EXPECT_TRUE(EntityName.has_value());
}
TEST(ASTEntityMappingTest, FunctionReturnNull) {
auto EntityName = getEntityNameForReturn(nullptr);
EXPECT_FALSE(EntityName.has_value());
}
TEST(ASTEntityMappingTest, FunctionReturnBuiltin) {
auto AST = tooling::buildASTFromCode(R"cpp(
void test() {
__builtin_memcpy(0, 0, 0);
}
)cpp");
auto &Ctx = AST->getASTContext();
// Find the builtin call
auto Matcher = callExpr().bind("call");
auto Matches = match(Matcher, Ctx);
ASSERT_FALSE(Matches.empty());
const auto *CE = Matches[0].getNodeAs<CallExpr>("call");
ASSERT_NE(CE, nullptr);
const auto *Callee = CE->getDirectCallee();
if (Callee && Callee->getBuiltinID()) {
auto EntityName = getEntityNameForReturn(Callee);
EXPECT_FALSE(EntityName.has_value());
}
}
TEST(ASTEntityMappingTest, DifferentFunctionsDifferentNames) {
auto AST = tooling::buildASTFromCode(R"cpp(
void foo() {}
void bar() {}
)cpp");
auto &Ctx = AST->getASTContext();
const auto *Foo = findFnByName("foo", Ctx);
const auto *Bar = findFnByName("bar", Ctx);
ASSERT_NE(Foo, nullptr);
ASSERT_NE(Bar, nullptr);
auto FooName = getEntityName(Foo);
auto BarName = getEntityName(Bar);
ASSERT_TRUE(FooName.has_value());
ASSERT_TRUE(BarName.has_value());
EXPECT_NE(*FooName, *BarName);
}
// Redeclaration tests
TEST(ASTEntityMappingTest, FunctionRedeclaration) {
auto AST = tooling::buildASTFromCode(R"cpp(
void foo();
void foo() {}
)cpp");
auto &Ctx = AST->getASTContext();
auto Matcher = functionDecl(hasName("foo")).bind("decl");
auto Matches = match(Matcher, Ctx);
ASSERT_GE(Matches.size(), 2u);
const auto *FirstDecl = Matches[0].getNodeAs<FunctionDecl>("decl");
ASSERT_NE(FirstDecl, nullptr);
auto FirstName = getEntityName(FirstDecl);
ASSERT_TRUE(FirstName.has_value());
for (size_t I = 1; I < Matches.size(); ++I) {
const auto *Decl = Matches[I].getNodeAs<FunctionDecl>("decl");
ASSERT_NE(Decl, nullptr);
auto Name = getEntityName(Decl);
ASSERT_TRUE(Name.has_value());
EXPECT_EQ(*FirstName, *Name);
}
}
TEST(ASTEntityMappingTest, VarRedeclaration) {
auto AST = tooling::buildASTFromCode(R"cpp(
extern int x;
int x = 42;
)cpp");
auto &Ctx = AST->getASTContext();
auto Matcher = varDecl(hasName("x")).bind("decl");
auto Matches = match(Matcher, Ctx);
ASSERT_EQ(Matches.size(), 2u);
const auto *FirstDecl = Matches[0].getNodeAs<VarDecl>("decl");
ASSERT_NE(FirstDecl, nullptr);
auto FirstName = getEntityName(FirstDecl);
ASSERT_TRUE(FirstName.has_value());
for (size_t I = 1; I < Matches.size(); ++I) {
const auto *Decl = Matches[I].getNodeAs<VarDecl>("decl");
ASSERT_NE(Decl, nullptr);
auto Name = getEntityName(Decl);
ASSERT_TRUE(Name.has_value());
EXPECT_EQ(*FirstName, *Name);
}
}
TEST(ASTEntityMappingTest, RecordRedeclaration) {
auto AST = tooling::buildASTFromCode(R"cpp(
struct S;
struct S {};
)cpp");
auto &Ctx = AST->getASTContext();
auto Matcher = recordDecl(hasName("S"), unless(isImplicit())).bind("decl");
auto Matches = match(Matcher, Ctx);
ASSERT_GE(Matches.size(), 2u);
const auto *FirstDecl = Matches[0].getNodeAs<RecordDecl>("decl");
ASSERT_NE(FirstDecl, nullptr);
auto FirstName = getEntityName(FirstDecl);
ASSERT_TRUE(FirstName.has_value());
for (size_t I = 1; I < Matches.size(); ++I) {
const auto *Decl = Matches[I].getNodeAs<RecordDecl>("decl");
ASSERT_NE(Decl, nullptr);
auto Name = getEntityName(Decl);
ASSERT_TRUE(Name.has_value());
EXPECT_EQ(*FirstName, *Name);
}
}
TEST(ASTEntityMappingTest, ParmVarDeclRedeclaration) {
auto AST = tooling::buildASTFromCode(R"cpp(
void foo(int);
void foo(int x);
void foo(int y);
void foo(int x) {}
)cpp");
auto &Ctx = AST->getASTContext();
auto Matcher = functionDecl(hasName("foo")).bind("decl");
auto Matches = match(Matcher, Ctx);
ASSERT_GE(Matches.size(), 2u);
const auto *FirstFuncDecl = Matches[0].getNodeAs<FunctionDecl>("decl");
ASSERT_NE(FirstFuncDecl, nullptr);
ASSERT_GT(FirstFuncDecl->param_size(), 0u);
auto ParamEName = getEntityName(FirstFuncDecl->getParamDecl(0));
ASSERT_TRUE(ParamEName.has_value());
for (size_t I = 1; I < Matches.size(); ++I) {
const auto *FDecl = Matches[I].getNodeAs<FunctionDecl>("decl");
ASSERT_NE(FDecl, nullptr);
ASSERT_GT(FDecl->param_size(), 0u);
auto ParamRedeclEName = getEntityName(FDecl->getParamDecl(0));
EXPECT_EQ(*ParamEName, *ParamRedeclEName);
}
}
TEST(ASTEntityMappingTest, FunctionReturnRedeclaration) {
auto AST = tooling::buildASTFromCode(R"cpp(
int foo();
int foo() { return 42; }
)cpp");
auto &Ctx = AST->getASTContext();
auto Matcher = functionDecl(hasName("foo")).bind("decl");
auto Matches = match(Matcher, Ctx);
ASSERT_EQ(Matches.size(), 2u);
const auto *Decl1 = Matches[0].getNodeAs<FunctionDecl>("decl");
ASSERT_NE(Decl1, nullptr);
auto Name1 = getEntityNameForReturn(Decl1);
ASSERT_TRUE(Name1.has_value());
for (size_t I = 1; I < Matches.size(); ++I) {
const auto *FDecl = Matches[I].getNodeAs<FunctionDecl>("decl");
ASSERT_NE(FDecl, nullptr);
auto Name = getEntityNameForReturn(Decl1);
ASSERT_TRUE(Name.has_value());
EXPECT_EQ(*Name1, *Name);
}
}
} // namespace
} // namespace clang::ssaf