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
160 lines
6.4 KiB
C++
160 lines
6.4 KiB
C++
//===- UncheckedStatusOrAccessModelTestFixture.h --------------------------===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_CLANG_ANALYSIS_FLOW_SENSITIVE_UNCHECKEDSTATUSORACCESSMODELTESTFIXTURE_H_
|
|
#define LLVM_CLANG_ANALYSIS_FLOW_SENSITIVE_UNCHECKEDSTATUSORACCESSMODELTESTFIXTURE_H_
|
|
|
|
#include <algorithm>
|
|
#include <iterator>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "TestingSupport.h"
|
|
#include "clang/AST/ASTContext.h"
|
|
#include "clang/AST/Decl.h"
|
|
#include "clang/ASTMatchers/ASTMatchers.h"
|
|
#include "clang/Analysis/CFG.h"
|
|
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
|
|
#include "clang/Analysis/FlowSensitive/MatchSwitch.h"
|
|
#include "clang/Analysis/FlowSensitive/Models/UncheckedStatusOrAccessModel.h"
|
|
#include "clang/Basic/SourceLocation.h"
|
|
#include "clang/Tooling/Tooling.h"
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/ADT/DenseSet.h"
|
|
#include "llvm/ADT/STLExtras.h"
|
|
#include "llvm/Support/Error.h"
|
|
#include "gmock/gmock.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
namespace clang::dataflow::statusor_model {
|
|
|
|
enum class UncheckedStatusOrAccessModelTestAliasKind {
|
|
kUnaliased = 0, // no alias
|
|
kPartiallyAliased = 1, // template<typename T> using Alias = absl::StatusOr;
|
|
kFullyAliased = 2, // using Alias = absl::StatusOr<int>;
|
|
};
|
|
|
|
// Base class for the test executors. This is needed to abstract away the
|
|
// template parameter from the UncheckedStatusOrAccessModelTestExecutor. This
|
|
// allows us to use UncheckedStatusOrAccessModelTestExecutorBase* in the
|
|
// UncheckedStatusOrAccessModelTest.
|
|
class UncheckedStatusOrAccessModelTestExecutorBase {
|
|
public:
|
|
virtual void
|
|
ExpectDiagnosticsFor(std::string SourceCode,
|
|
UncheckedStatusOrAccessModelTestAliasKind) const = 0;
|
|
virtual void ExpectDiagnosticsForLambda(
|
|
std::string SourceCode,
|
|
UncheckedStatusOrAccessModelTestAliasKind) const = 0;
|
|
virtual ~UncheckedStatusOrAccessModelTestExecutorBase() = default;
|
|
};
|
|
|
|
// Returns these macros according to the alias kind:
|
|
// - STATUS
|
|
// - STATUSOR_INT
|
|
// - STATUSOR_BOOL
|
|
// - STATUSOR_VOIDPTR
|
|
// Tests should use these macros instead of e.g. absl::StatusOr<int> to ensure
|
|
// the model is insensitive to whether the StatusOr<> is aliased or not.
|
|
std::string GetAliasMacros(UncheckedStatusOrAccessModelTestAliasKind AliasKind);
|
|
|
|
std::vector<std::pair<std::string, std::string>>
|
|
GetHeaders(UncheckedStatusOrAccessModelTestAliasKind AliasKind);
|
|
|
|
// This allows us to run the same test suite for multiple models. This allows
|
|
// vendors to model internal APIs in an extension of the base model, and make
|
|
// sure that these tests still pass.
|
|
template <typename Model>
|
|
class UncheckedStatusOrAccessModelTestExecutor
|
|
: public UncheckedStatusOrAccessModelTestExecutorBase {
|
|
public:
|
|
void ExpectDiagnosticsFor(
|
|
std::string SourceCode,
|
|
UncheckedStatusOrAccessModelTestAliasKind AliasKind) const override {
|
|
using namespace ::clang::ast_matchers; // NOLINT: Too many names
|
|
ExpectDiagnosticsFor(SourceCode, hasName("target"), AliasKind);
|
|
}
|
|
|
|
void ExpectDiagnosticsForLambda(
|
|
std::string SourceCode,
|
|
UncheckedStatusOrAccessModelTestAliasKind AliasKind) const override {
|
|
using namespace ::clang::ast_matchers; // NOLINT: Too many names
|
|
ExpectDiagnosticsFor(SourceCode,
|
|
allOf(hasOverloadedOperatorName("()"),
|
|
hasDeclContext(cxxRecordDecl(isLambda()))),
|
|
AliasKind);
|
|
}
|
|
|
|
template <typename FuncDeclMatcher>
|
|
void ExpectDiagnosticsFor(
|
|
std::string SourceCode, FuncDeclMatcher FuncMatcher,
|
|
UncheckedStatusOrAccessModelTestAliasKind AliasKind) const {
|
|
std::vector<std::pair<std::string, std::string>> Headers =
|
|
GetHeaders(AliasKind);
|
|
|
|
UncheckedStatusOrAccessModelOptions Options{};
|
|
std::vector<SourceLocation> Diagnostics;
|
|
llvm::Error Error = test::checkDataflow<Model>(
|
|
test::AnalysisInputs<Model>(
|
|
SourceCode, std::move(FuncMatcher),
|
|
[](ASTContext &Ctx, Environment &Env) { return Model(Ctx, Env); })
|
|
.withPostVisitCFG(
|
|
[&Diagnostics,
|
|
Diagnoser = UncheckedStatusOrAccessDiagnoser(Options)](
|
|
ASTContext &Ctx, const CFGElement &Elt,
|
|
const TransferStateForDiagnostics<
|
|
UncheckedStatusOrAccessModel::Lattice> &State) mutable {
|
|
auto EltDiagnostics = Diagnoser(Elt, Ctx, State);
|
|
llvm::move(EltDiagnostics, std::back_inserter(Diagnostics));
|
|
})
|
|
.withASTBuildArgs(
|
|
{"-fsyntax-only", "-std=c++20", "-Wno-undefined-inline"})
|
|
.withASTBuildVirtualMappedFiles(
|
|
tooling::FileContentMappings(Headers.begin(), Headers.end())),
|
|
/*VerifyResults=*/[&Diagnostics, SourceCode](
|
|
const llvm::DenseMap<unsigned, std::string>
|
|
&Annotations,
|
|
const test::AnalysisOutputs &AO) {
|
|
llvm::DenseSet<unsigned> AnnotationLines;
|
|
for (const auto &[Line, _] : Annotations)
|
|
AnnotationLines.insert(Line);
|
|
auto &SrcMgr = AO.ASTCtx.getSourceManager();
|
|
llvm::DenseSet<unsigned> DiagnosticLines;
|
|
for (SourceLocation &Loc : Diagnostics)
|
|
DiagnosticLines.insert(SrcMgr.getPresumedLineNumber(Loc));
|
|
|
|
EXPECT_THAT(DiagnosticLines, testing::ContainerEq(AnnotationLines))
|
|
<< "\nFailing code:\n"
|
|
<< SourceCode;
|
|
});
|
|
if (Error)
|
|
FAIL() << llvm::toString(std::move(Error));
|
|
}
|
|
|
|
~UncheckedStatusOrAccessModelTestExecutor() override = default;
|
|
};
|
|
|
|
class UncheckedStatusOrAccessModelTest
|
|
: public ::testing::TestWithParam<
|
|
std::pair<UncheckedStatusOrAccessModelTestExecutorBase *,
|
|
UncheckedStatusOrAccessModelTestAliasKind>> {
|
|
protected:
|
|
void ExpectDiagnosticsFor(std::string SourceCode) {
|
|
GetParam().first->ExpectDiagnosticsFor(SourceCode, GetParam().second);
|
|
}
|
|
|
|
void ExpectDiagnosticsForLambda(std::string SourceCode) {
|
|
GetParam().first->ExpectDiagnosticsForLambda(SourceCode, GetParam().second);
|
|
}
|
|
};
|
|
|
|
} // namespace clang::dataflow::statusor_model
|
|
|
|
#endif // LLVM_CLANG_ANALYSIS_FLOW_SENSITIVE_UNCHECKEDSTATUSORACCESSMODELTESTFIXTURE_H_
|