[clang][dataflow] Change diagnoseFunction to use llvm::SmallVector instead of std::vector. (#66014)

The template is agnostic as to the type used by the list, as long as it
is
compatible with `llvm::move` and `std::back_inserter`. In practice,
we've
encountered analyses which use different types (`llvm::SmallVector` vs
`std::vector`), so it seems preferable to leave this open to the caller.
This commit is contained in:
Yitzhak Mandelbaum
2023-09-13 13:10:58 -04:00
committed by GitHub
parent bf85f27370
commit 004a7cea70
5 changed files with 14 additions and 15 deletions

View File

@@ -13,10 +13,8 @@
#include "clang/Analysis/FlowSensitive/DataflowAnalysis.h"
#include "clang/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Error.h"
#include <memory>
#include <optional>
#include <vector>
namespace clang::tidy::bugprone {
using ast_matchers::MatchFinder;
@@ -54,7 +52,7 @@ void UncheckedOptionalAccessCheck::check(
UncheckedOptionalAccessDiagnoser Diagnoser(ModelOptions);
// FIXME: Allow user to set the (defaulted) SAT iterations max for
// `diagnoseFunction` with config options.
if (llvm::Expected<std::vector<SourceLocation>> Locs =
if (llvm::Expected<llvm::SmallVector<SourceLocation>> Locs =
dataflow::diagnoseFunction<UncheckedOptionalAccessModel,
SourceLocation>(*FuncDecl, *Result.Context,
Diagnoser))

View File

@@ -31,6 +31,7 @@
#include "llvm/ADT/Any.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Error.h"
@@ -246,9 +247,9 @@ runDataflowAnalysis(
/// - This limit is still low enough to keep runtimes acceptable (on typical
/// machines) in cases where we hit the limit.
template <typename AnalysisT, typename Diagnostic>
llvm::Expected<std::vector<Diagnostic>> diagnoseFunction(
llvm::Expected<llvm::SmallVector<Diagnostic>> diagnoseFunction(
const FunctionDecl &FuncDecl, ASTContext &ASTCtx,
llvm::function_ref<std::vector<Diagnostic>(
llvm::function_ref<llvm::SmallVector<Diagnostic>(
const CFGElement &, ASTContext &,
const TransferStateForDiagnostics<typename AnalysisT::Lattice> &)>
Diagnoser,
@@ -263,7 +264,7 @@ llvm::Expected<std::vector<Diagnostic>> diagnoseFunction(
DataflowAnalysisContext AnalysisContext(std::move(OwnedSolver));
Environment Env(AnalysisContext, FuncDecl);
AnalysisT Analysis(ASTCtx);
std::vector<Diagnostic> Diagnostics;
llvm::SmallVector<Diagnostic> Diagnostics;
if (llvm::Error Err =
runTypeErasedDataflowAnalysis(
*Context, Analysis, Env,

View File

@@ -21,7 +21,7 @@
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
#include "clang/Analysis/FlowSensitive/NoopLattice.h"
#include "clang/Basic/SourceLocation.h"
#include <vector>
#include "llvm/ADT/SmallVector.h"
namespace clang {
namespace dataflow {
@@ -74,14 +74,14 @@ public:
UncheckedOptionalAccessDiagnoser(
UncheckedOptionalAccessModelOptions Options = {});
std::vector<SourceLocation>
llvm::SmallVector<SourceLocation>
operator()(const CFGElement &Elt, ASTContext &Ctx,
const TransferStateForDiagnostics<NoopLattice> &State) {
return DiagnoseMatchSwitch(Elt, Ctx, State.Env);
}
private:
CFGMatchSwitch<const Environment, std::vector<SourceLocation>>
CFGMatchSwitch<const Environment, llvm::SmallVector<SourceLocation>>
DiagnoseMatchSwitch;
};

View File

@@ -34,7 +34,6 @@
#include <memory>
#include <optional>
#include <utility>
#include <vector>
namespace clang {
namespace dataflow {
@@ -913,8 +912,8 @@ auto buildTransferMatchSwitch() {
.Build();
}
std::vector<SourceLocation> diagnoseUnwrapCall(const Expr *ObjectExpr,
const Environment &Env) {
llvm::SmallVector<SourceLocation> diagnoseUnwrapCall(const Expr *ObjectExpr,
const Environment &Env) {
if (auto *OptionalVal = getValueBehindPossiblePointer(*ObjectExpr, Env)) {
auto *Prop = OptionalVal->getProperty("has_value");
if (auto *HasValueVal = cast_or_null<BoolValue>(Prop)) {
@@ -935,7 +934,8 @@ auto buildDiagnoseMatchSwitch(
// lot of duplicated work (e.g. string comparisons), consider providing APIs
// that avoid it through memoization.
auto IgnorableOptional = ignorableOptional(Options);
return CFGMatchSwitchBuilder<const Environment, std::vector<SourceLocation>>()
return CFGMatchSwitchBuilder<const Environment,
llvm::SmallVector<SourceLocation>>()
// optional::value
.CaseOfCFGStmt<CXXMemberCallExpr>(
valueCall(IgnorableOptional),

View File

@@ -98,7 +98,7 @@ TEST(DataflowAnalysisTest, DiagnoseFunctionDiagnoserCalledOnEachElement) {
cast<FunctionDecl>(findValueDecl(AST->getASTContext(), "target"));
auto Diagnoser = [](const CFGElement &Elt, ASTContext &,
const TransferStateForDiagnostics<NoopLattice> &) {
std::vector<std::string> Diagnostics(1);
llvm::SmallVector<std::string> Diagnostics(1);
llvm::raw_string_ostream OS(Diagnostics.front());
Elt.dumpToStream(OS);
return Diagnostics;