clang 23.0.0git
DerivedAnalysis.h
Go to the documentation of this file.
1//===- DerivedAnalysis.h ----------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Defines DerivedAnalysisBase (type-erased base known to AnalysisDriver) and
10// the typed intermediate DerivedAnalysis<ResultT, DepResultTs...> that
11// concrete analyses inherit from.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_DERIVEDANALYSIS_H
16#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_DERIVEDANALYSIS_H
17
23#include "llvm/Support/Error.h"
24#include <map>
25#include <memory>
26#include <vector>
27
28namespace clang::ssaf {
29
30class AnalysisDriver;
32
33/// Type-erased base for derived analyses. Known to AnalysisDriver.
34///
35/// Not subclassed directly -- use DerivedAnalysis<ResultT, DepResultTs...>.
36/// A derived analysis consumes previously produced AnalysisResult objects
37/// and computes a new one via an initialize/step/finalize lifecycle.
39 friend class AnalysisDriver;
40
41protected:
43
44private:
45 /// Called once with the dependency results before the step() loop.
46 ///
47 /// \param DepResults Immutable results of all declared dependencies, keyed
48 /// by AnalysisName. Guaranteed to contain every name
49 /// returned by dependencyNames().
50 virtual llvm::Error initialize(
51 const std::map<AnalysisName, const AnalysisResult *> &DepResults) = 0;
52
53 /// Performs one pass.
54 /// Returns true if another pass is needed; false when converged.
55 virtual llvm::Expected<bool> step() = 0;
56
57 /// Called after the step() loop converges. Default is a no-op.
58 virtual llvm::Error finalize() { return llvm::Error::success(); }
59};
60
61/// Typed intermediate that concrete derived analyses inherit from.
62///
63/// Concrete analyses must implement:
64/// llvm::Error initialize(const DepResultTs &...) override;
65/// llvm::Expected<bool> step() override;
66/// and may override finalize().
67///
68/// Dependencies are fixed for the lifetime of the analysis: initialize()
69/// binds them once, step() is called until it returns false, and
70/// finalize() post-processes after convergence.
71template <typename ResultT, typename... DepResultTs>
73 static_assert(std::is_base_of_v<AnalysisResult, ResultT>,
74 "ResultT must derive from AnalysisResult");
75 static_assert(HasAnalysisName_v<ResultT>,
76 "ResultT must have a static analysisName() method");
77 static_assert((std::is_base_of_v<AnalysisResult, DepResultTs> && ...),
78 "Every DepResultT must derive from AnalysisResult");
79 static_assert((HasAnalysisName_v<DepResultTs> && ...),
80 "Every DepResultT must have a static analysisName() method");
81
82 friend class AnalysisRegistry;
83 using ResultType = ResultT;
84
85 std::unique_ptr<ResultT> Result = std::make_unique<ResultT>();
86
87public:
88 /// Used by AnalysisRegistry::Add to derive the registry entry name.
89 AnalysisName analysisName() const final { return ResultT::analysisName(); }
90
91 const std::vector<AnalysisName> &dependencyNames() const final {
92 static const std::vector<AnalysisName> Names = {
93 DepResultTs::analysisName()...};
94 return Names;
95 }
96
97 /// Called once with the fixed dependency results before the step() loop.
98 virtual llvm::Error initialize(const DepResultTs &...) = 0;
99
100 /// Performs one step. Returns true if another step is needed; false when
101 /// converged. Single-step analyses always return false.
103
104 /// Called after the step() loop converges. Override for post-processing.
105 virtual llvm::Error finalize() { return llvm::Error::success(); }
106
107protected:
108 /// Read-only access to the result being built.
109 const ResultT &result() const & { return *Result; }
110
111 /// Mutable access to the result being built.
112 ResultT &result() & { return *Result; }
113
114private:
115 /// Seals the type-erased base overload, downcasts, and dispatches to the
116 /// typed initialize(). All dependencies are guaranteed present by the driver.
117 llvm::Error
118 initialize(const std::map<AnalysisName, const AnalysisResult *> &Map) final {
119 auto lookup = [&Map](const AnalysisName &Name) -> const AnalysisResult * {
120 auto It = Map.find(Name);
121 if (It == Map.end()) {
122 ErrorBuilder::fatal("dependency '{0}' missing from DepResults map; "
123 "dependency graph is not topologically sorted",
124 Name);
125 }
126 return It->second;
127 };
128 return initialize(*static_cast<const DepResultTs *>(
129 lookup(DepResultTs::analysisName()))...);
130 }
131
132 /// Type-erased result extraction for the driver.
133 std::unique_ptr<AnalysisResult> result() && final {
134 return std::move(Result);
135 }
136};
137
138} // namespace clang::ssaf
139
140#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_DERIVEDANALYSIS_H
Orchestrates whole-program analysis over an LUSummary.
Uniquely identifies a whole-program analysis and the AnalysisResult it produces.
Unified registry for SummaryAnalysis and DerivedAnalysis implementations.
Base class for whole-program analysis results.
Typed intermediate that concrete derived analyses inherit from.
virtual llvm::Error initialize(const DepResultTs &...)=0
Called once with the fixed dependency results before the step() loop.
const std::vector< AnalysisName > & dependencyNames() const final
AnalysisNames of all AnalysisResult dependencies.
const ResultT & result() const &
Read-only access to the result being built.
virtual llvm::Expected< bool > step()=0
Performs one step.
AnalysisName analysisName() const final
Used by AnalysisRegistry::Add to derive the registry entry name.
ResultT & result() &
Mutable access to the result being built.
virtual llvm::Error finalize()
Called after the step() loop converges. Override for post-processing.
static void fatal(const char *Fmt, Args &&...ArgVals)
Report a fatal error with formatted message and terminate execution.
constexpr bool HasAnalysisName_v
void initialize(TemplateInstantiationCallbackPtrs &Callbacks, const Sema &TheSema)
void finalize(TemplateInstantiationCallbackPtrs &Callbacks, const Sema &TheSema)
float __ovld __cnfn step(float, float)
Returns 0.0 if x < edge, otherwise it returns 1.0.