, llvm::cl::Hidden, llvm::cl::ValueOptional,
38llvm::cl::desc(
"Emit log of dataflow analysis. With no arg, writes textual " 39 "log to stderr. With an arg, writes HTML logs under the " 40 "specified directory (one per analyzed function)."));
59voidDataflowAnalysisContext::addModeledFields(
const FieldSet&Fields) {
60ModeledFields.set_union(Fields);
65llvm::DenseMap<const ValueDecl *, StorageLocation *> FieldLocs;
67 if(Field->getType()->isReferenceType())
68FieldLocs.insert({Field,
nullptr});
71Field->getType().getNonReferenceType())});
75SyntheticFields.insert(
80std::move(SyntheticFields));
88staticllvm::DenseSet<llvm::StringRef>
getKeys(
constllvm::StringMap<T> &Map) {
89 returnllvm::DenseSet<llvm::StringRef>(Map.keys().begin(), Map.keys().end());
99RecordStorageLocationCreated =
true;
101std::move(SyntheticFields));
105DataflowAnalysisContext::getStableStorageLocation(
const ValueDecl&
D) {
106 if(
auto*
Loc= DeclToLoc.lookup(&
D))
108 auto&
Loc= createStorageLocation(
D.getType().getNonReferenceType());
109DeclToLoc[&
D] = &
Loc;
114DataflowAnalysisContext::getStableStorageLocation(
const Expr&
E) {
117 if(
auto*
Loc= ExprToLoc.lookup(&CanonE))
119 auto&
Loc= createStorageLocation(CanonE.
getType());
120ExprToLoc[&CanonE] = &
Loc;
125DataflowAnalysisContext::getOrCreateNullPointerValue(
QualTypePointeeType) {
126 autoCanonicalPointeeType =
128 autoRes = NullPointerVals.try_emplace(CanonicalPointeeType,
nullptr);
130 auto&PointeeLoc = createStorageLocation(CanonicalPointeeType);
131Res.first->second = &arena().create<
PointerValue>(PointeeLoc);
133 return*Res.first->second;
136voidDataflowAnalysisContext::addInvariant(
const Formula&Constraint) {
143voidDataflowAnalysisContext::addFlowConditionConstraint(
145 autoRes = FlowConditionConstraints.try_emplace(
Token, &Constraint);
148&arena().makeAnd(*Res.first->second, Constraint);
153 AtomForkToken = arena().makeFlowConditionToken();
154FlowConditionDeps[ForkToken].insert(
Token);
155addFlowConditionConstraint(ForkToken, arena().makeAtomRef(
Token));
160DataflowAnalysisContext::joinFlowConditions(
AtomFirstToken,
162 Atom Token= arena().makeFlowConditionToken();
163 auto&TokenDeps = FlowConditionDeps[
Token];
164TokenDeps.insert(FirstToken);
165TokenDeps.insert(SecondToken);
166addFlowConditionConstraint(
Token,
167arena().makeOr(arena().makeAtomRef(FirstToken),
168arena().makeAtomRef(SecondToken)));
173llvm::SetVector<const Formula *> Constraints) {
174 returnS.solve(Constraints.getArrayRef());
177boolDataflowAnalysisContext::flowConditionImplies(
Atom Token,
187llvm::SetVector<const Formula *> Constraints;
188Constraints.insert(&arena().makeAtomRef(
Token));
189Constraints.insert(&arena().makeNot(F));
190addTransitiveFlowConditionConstraints(
Token, Constraints);
191 returnisUnsatisfiable(std::move(Constraints));
194boolDataflowAnalysisContext::flowConditionAllows(
Atom Token,
199llvm::SetVector<const Formula *> Constraints;
200Constraints.insert(&arena().makeAtomRef(
Token));
201Constraints.insert(&F);
202addTransitiveFlowConditionConstraints(
Token, Constraints);
203 returnisSatisfiable(std::move(Constraints));
206boolDataflowAnalysisContext::equivalentFormulas(
const Formula&Val1,
208llvm::SetVector<const Formula *> Constraints;
209Constraints.insert(&arena().makeNot(arena().makeEquals(Val1, Val2)));
210 returnisUnsatisfiable(std::move(Constraints));
213voidDataflowAnalysisContext::addTransitiveFlowConditionConstraints(
214 Atom Token, llvm::SetVector<const Formula *> &Constraints) {
215llvm::DenseSet<Atom> AddedTokens;
216std::vector<Atom> Remaining = {
Token};
221 while(!Remaining.empty()) {
222 auto Token= Remaining.back();
223Remaining.pop_back();
224 if(!AddedTokens.insert(
Token).second)
227 autoConstraintsIt = FlowConditionConstraints.find(
Token);
228 if(ConstraintsIt == FlowConditionConstraints.end()) {
229Constraints.insert(&arena().makeAtomRef(
Token));
233Constraints.insert(&arena().makeEquals(arena().makeAtomRef(Token),
234*ConstraintsIt->second));
237 if(
autoDepsIt = FlowConditionDeps.find(Token);
238DepsIt != FlowConditionDeps.end())
239 for(Atom A : DepsIt->second)
240Remaining.push_back(A);
245llvm::raw_ostream &OS) {
247 for(
size_ti = 0; i < Atoms.size(); ++i) {
249 if(i + 1 < Atoms.size())
255voidDataflowAnalysisContext::dumpFlowCondition(
Atom Token,
256llvm::raw_ostream &OS) {
257llvm::SetVector<const Formula *> Constraints;
258Constraints.insert(&arena().makeAtomRef(
Token));
259addTransitiveFlowConditionConstraints(
Token, Constraints);
261OS <<
"Flow condition token: "<<
Token<<
"\n";
263llvm::SetVector<const Formula *> OriginalConstraints = Constraints;
265 if(!Constraints.empty()) {
266OS <<
"Constraints:\n";
267 for(
const auto*Constraint : Constraints) {
268Constraint->print(OS);
273OS <<
"True atoms: ";
277OS <<
"False atoms: ";
281OS <<
"Equivalent atoms:\n";
286OS <<
"\nFlow condition constraints before simplification:\n";
287 for(
const auto*Constraint : OriginalConstraints) {
288Constraint->print(OS);
299 autoIt = FunctionContexts.find(F);
300 if(It != FunctionContexts.end())
304 autoACFG = AdornedCFG::build(*F);
307 auto Result= FunctionContexts.insert({F, std::move(*ACFG)});
308 return&
Result.first->second;
316 returnLogger::textual(llvm::errs());
319 if(
autoEC = llvm::sys::fs::create_directories(Dir))
320llvm::errs() <<
"Failed to create log dir: "<< EC.message() <<
"\n";
324 staticstd::atomic<unsigned> Counter = {0};
326[Dir(Dir.str())]()
mutable-> std::unique_ptr<llvm::raw_ostream> {
328llvm::sys::path::append(
File,
329std::to_string(Counter.fetch_add(1)) +
".html");
331 autoOS = std::make_unique<llvm::raw_fd_ostream>(
File, EC);
333llvm::errs() <<
"Failed to create log "<<
File<<
": "<< EC.message()
335 returnstd::make_unique<llvm::raw_null_ostream>();
339 returnLogger::html(std::move(StreamFactory));
342DataflowAnalysisContext::DataflowAnalysisContext(
343Solver &S, std::unique_ptr<Solver> &&OwnedSolver, Options Opts)
344: S(S), OwnedSolver(
std::move(OwnedSolver)), A(
std::make_unique<Arena>()),
349 if(Opts.Log ==
nullptr) {
352this->Opts.Log = LogOwner.get();
360DataflowAnalysisContext::~DataflowAnalysisContext() =
default;
static llvm::cl::opt< std::string > DataflowLog("dataflow-log", llvm::cl::Hidden, llvm::cl::ValueOptional, llvm::cl::desc("Emit log of dataflow analysis. With no arg, writes textual " "log to stderr. With an arg, writes HTML logs under the " "specified directory (one per analyzed function)."))
Defines the clang::Expr interface and subclasses for C++ expressions.
This represents one expression.
Represents a member of a struct/union/class.
Represents a function declaration or definition.
bool doesThisDeclarationHaveABody() const
Returns whether this specific declaration of the function has a body.
FunctionDecl * getDefinition()
Get the definition for this declaration.
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
QualType getCanonicalType() const
Token - This structure provides full information about a lexed token.
The base class of the type hierarchy.
bool isRecordType() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Holds CFG with additional information derived from it that is needed to perform dataflow analysis.
llvm::StringMap< QualType > getSyntheticFields(QualType Type)
Returns the names and types of the synthetic fields for the given record type.
StorageLocation & createStorageLocation(QualType Type)
Returns a new storage location appropriate for Type.
FieldSet getModeledFields(QualType Type)
Returns the fields of Type, limited to the set of fields modeled by this context.
RecordStorageLocation & createRecordStorageLocation(QualType Type, RecordStorageLocation::FieldToLoc FieldLocs, RecordStorageLocation::SyntheticFieldMap SyntheticFields)
Creates a RecordStorageLocation for the given type and with the given fields.
bool isLiteral(bool b) const
static Logger & null()
Returns a dummy logger that does nothing.
Models a symbolic pointer. Specifically, any value of type T*.
A storage location for a record (struct, class, or union).
llvm::DenseMap< const ValueDecl *, StorageLocation * > FieldToLoc
llvm::StringMap< StorageLocation * > SyntheticFieldMap
A storage location that is not subdivided further for the purposes of abstract interpretation.
Base class for elements of the local variable store and of the heap.
Atom
Identifies an atomic boolean variable such as "V1".
static void printAtomList(const llvm::SmallVector< Atom > &Atoms, llvm::raw_ostream &OS)
void simplifyConstraints(llvm::SetVector< const Formula * > &Constraints, Arena &arena, SimplifyConstraintsInfo *Info=nullptr)
Simplifies a set of constraints (implicitly connected by "and") in a way that does not change satisfi...
const Expr & ignoreCFGOmittedNodes(const Expr &E)
Skip past nodes that the CFG does not emit.
FieldSet getObjectFields(QualType Type)
Returns the set of all fields in the type.
static std::unique_ptr< Logger > makeLoggerFromCommandLine()
static llvm::DenseSet< llvm::StringRef > getKeys(const llvm::StringMap< T > &Map)
bool containsSameFields(const FieldSet &Fields, const RecordStorageLocation::FieldToLoc &FieldLocs)
Returns whether Fields and FieldLocs contain the same fields.
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.
@ Invariant
The parameter is invariant: must match exactly.
@ Class
The "class" keyword introduces the elaborated-type-specifier.
std::optional< ContextSensitiveOptions > ContextSensitiveOpts
Options for analyzing function bodies when present in the translation unit, or empty to disable conte...
Information on the way a set of constraints was simplified.
llvm::SmallVector< Atom > TrueAtoms
Atoms that the original constraints imply must be true.
llvm::SmallVector< llvm::SmallVector< Atom > > EquivalentAtoms
List of equivalence classes of atoms.
llvm::SmallVector< Atom > FalseAtoms
Atoms that the original constraints imply must be false.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4