CLANG_EXPORT_TEMPLATE Any::TypeId<clang::dataflow::NoopLattice>;
61 autoBlockPos = llvm::find_if(
63return Succ && Succ->getBlockID() == Block.getBlockID();
81classTerminatorVisitor
84TerminatorVisitor() =
default;
85 const Expr*VisitIfStmt(
const IfStmt*S) {
returnS->getCond(); }
86 constExpr *VisitWhileStmt(
constWhileStmt *S) {
returnS->getCond(); }
87 constExpr *VisitDoStmt(
constDoStmt *S) {
returnS->getCond(); }
88 constExpr *VisitForStmt(
constForStmt *S) {
returnS->getCond(); }
89 constExpr *VisitCXXForRangeStmt(
constCXXForRangeStmt *) {
94 constExpr *VisitBinaryOperator(
constBinaryOperator *S) {
95assert(S->getOpcode() == BO_LAnd || S->getOpcode() == BO_LOr);
98 constExpr *VisitConditionalOperator(
constConditionalOperator *S) {
104structAnalysisContext {
105AnalysisContext(
constAdornedCFG &
ACFG, TypeErasedDataflowAnalysis &
Analysis,
110 Log(*
InitEnv.getDataflowAnalysisContext().getOptions().
Log),
114~AnalysisContext() {
Log.endAnalysis(); }
128classPrettyStackTraceAnalysis :
publicllvm::PrettyStackTraceEntry {
130PrettyStackTraceAnalysis(
constAdornedCFG &ACFG,
const char*Message)
131: ACFG(ACFG), Message(Message) {}
133 void print(raw_ostream &OS)
const override{
134OS << Message <<
"\n";
136ACFG.getDecl().dump(OS);
138ACFG.getCFG().print(OS, LangOptions(),
false);
142 constAdornedCFG &ACFG;
146classPrettyStackTraceCFGElement :
publicllvm::PrettyStackTraceEntry {
148PrettyStackTraceCFGElement(
constCFGElement &Element,
intBlockIdx,
149 intElementIdx,
const char*Message)
150: Element(Element), BlockIdx(BlockIdx), ElementIdx(ElementIdx),
153 void print(raw_ostream &OS)
const override{
154OS << Message <<
": Element [B"<< BlockIdx <<
"."<< ElementIdx <<
"]\n";
155 if(
autoStmt = Element.getAs<CFGStmt>()) {
157ASTDumper Dumper(OS,
false);
158Dumper.Visit(Stmt->getStmt());
163 constCFGElement ∈
173classJoinedStateBuilder {
175Environment::ExprJoinBehavior JoinBehavior;
176std::vector<const TypeErasedDataflowAnalysisState *>
All;
177std::deque<TypeErasedDataflowAnalysisState> Owned;
179TypeErasedDataflowAnalysisState
180join(
constTypeErasedDataflowAnalysisState &L,
181 constTypeErasedDataflowAnalysisState &R) {
182 return{AC.Analysis.joinTypeErased(L.Lattice, R.Lattice),
183Environment::join(L.Env, R.Env, AC.Analysis, JoinBehavior)};
187JoinedStateBuilder(AnalysisContext &AC,
188Environment::ExprJoinBehavior JoinBehavior)
189: AC(AC), JoinBehavior(JoinBehavior) {}
191 voidaddOwned(TypeErasedDataflowAnalysisState State) {
192Owned.push_back(std::move(State));
193 All.push_back(&Owned.back());
195 voidaddUnowned(
constTypeErasedDataflowAnalysisState &State) {
196 All.push_back(&State);
198TypeErasedDataflowAnalysisState take() && {
203 return{AC.Analysis.typeErasedInitialElement(), AC.InitEnv.fork()};
204 if(
All.size() == 1)
209 return{
All[0]->Lattice, Environment::join(All[0]->
Env, All[0]->
Env,
210AC.Analysis, JoinBehavior)};
212 autoResult = join(*All[0], *All[1]);
213 for(
unsignedI = 2; I <
All.size(); ++I)
214Result = join(Result, *All[I]);
221 returnTerminatorStmt ==
nullptr? nullptr
222: TerminatorVisitor().Visit(TerminatorStmt);
233staticTypeErasedDataflowAnalysisState
235std::vector<const CFGBlock *> Preds(
Block.pred_begin(),
Block.pred_end());
236 if(
Block.getTerminator().isTemporaryDtorsBranch()) {
259 if(
Block.succ_begin()->getReachableBlock() !=
nullptr&&
260 Block.succ_begin()->getReachableBlock()->hasNoReturnElement()) {
261 const CFGBlock*StmtBlock =
nullptr;
262 if(
const Stmt*Terminator =
Block.getTerminatorStmt())
263StmtBlock = AC.ACFG.blockForStmt(*Terminator);
264assert(StmtBlock !=
nullptr);
265llvm::erase(Preds, StmtBlock);
277 for(
const CFGBlock*Pred : Preds) {
278 if(Pred && AC.ACFG.containsExprConsumedInDifferentBlock(*Pred)) {
279JoinBehavior = Environment::KeepExprState;
284JoinedStateBuilder Builder(AC, JoinBehavior);
285 for(
const CFGBlock*Pred : Preds) {
287 if(!Pred || Pred->hasNoReturnElement())
292 conststd::optional<TypeErasedDataflowAnalysisState> &MaybePredState =
293AC.BlockStates[Pred->getBlockID()];
299 if(Cond ==
nullptr) {
300Builder.addUnowned(PredState);
309 if(AC.Analysis.builtinOptions()) {
315assert(CondVal !=
nullptr);
317BranchVal ? CondVal : &
Copy.Env.makeNot(*CondVal);
320AC.Analysis.transferBranchTypeErased(BranchVal, Cond,
Copy.Lattice,
322Builder.addOwned(std::move(
Copy));
324 returnstd::move(Builder).take();
331AnalysisContext &AC) {
333assert(S !=
nullptr);
335InputState.
Env, AC.Analysis);
343assert(Init !=
nullptr);
345 auto&
Env= InputState.
Env;
346 auto&ThisLoc = *
Env.getThisPointeeStorageLocation();
348 if(!Init->isAnyMemberInitializer())
352 auto*InitExpr = Init->getInit();
353assert(InitExpr !=
nullptr);
358 if(Init->isMemberInitializer()) {
359 Member= Init->getMember();
360MemberLoc = ThisLoc.getChild(*
Member);
363assert(IndirectField !=
nullptr);
364MemberLoc = &ThisLoc;
365 for(
const auto*I : IndirectField->
chain()) {
366 Member= cast<FieldDecl>(I);
367ParentLoc = cast<RecordStorageLocation>(MemberLoc);
371assert(
Member!=
nullptr);
380 if(
Member->getType()->isReferenceType()) {
381 auto*InitExprLoc =
Env.getStorageLocation(*InitExpr);
382 if(InitExprLoc ==
nullptr)
388}
else if(!
Member->getType()->isRecordType()) {
389assert(MemberLoc !=
nullptr);
390 if(
auto*InitExprVal =
Env.getValue(*InitExpr))
391 Env.setValue(*MemberLoc, *InitExprVal);
397AnalysisContext &AC) {
399 caseCFGElement::Statement:
402 caseCFGElement::Initializer:
405 caseCFGElement::LifetimeEnds:
412State.Env.removeDecl(*VD);
428staticTypeErasedDataflowAnalysisState
431AC.Log.enterBlock(
Block, PostAnalysisCallbacks.Before !=
nullptr||
432PostAnalysisCallbacks.After !=
nullptr);
433 autoState = computeBlockInputState(
Block, AC);
434AC.Log.recordState(State);
436 for(
const auto&Element :
Block) {
437PrettyStackTraceCFGElement CrashInfo(Element,
Block.getBlockID(),
438ElementIdx++,
"transferCFGBlock");
440AC.Log.enterElement(Element);
442 if(PostAnalysisCallbacks.Before) {
443PostAnalysisCallbacks.Before(Element, State);
447 if(AC.Analysis.builtinOptions()) {
448builtinTransfer(
Block.getBlockID(), Element, State, AC);
452AC.Analysis.transferTypeErased(Element, State.Lattice, State.Env);
454 if(PostAnalysisCallbacks.After) {
455PostAnalysisCallbacks.After(Element, State);
458AC.Log.recordState(State);
466 if(
constExpr *TerminatorCond =
467dyn_cast_or_null<Expr>(
Block.getTerminatorCondition())) {
468 if(State.Env.getValue(*TerminatorCond) ==
nullptr)
474 transfer(StmtToEnvMap(AC.ACFG, AC.BlockStates,
Block.getBlockID(), State),
475*TerminatorCond, State.Env, AC.Analysis);
480 if(State.Env.getValue(*TerminatorCond) ==
nullptr)
481State.Env.setValue(*TerminatorCond, State.Env.makeAtomicBoolValue());
482AC.Log.recordState(State);
493std::int32_t MaxBlockVisits) {
494PrettyStackTraceAnalysis CrashInfo(
ACFG,
"runTypeErasedDataflowAnalysis");
496std::optional<Environment> MaybeStartingEnv;
497 if(
InitEnv.callStackSize() == 0) {
498MaybeStartingEnv =
InitEnv.fork();
499MaybeStartingEnv->initialize();
502MaybeStartingEnv ? *MaybeStartingEnv :
InitEnv;
508std::vector<std::optional<TypeErasedDataflowAnalysisState>>
BlockStates(
514StartingEnv.
fork()};
518std::int32_t BlockVisits = 0;
520LLVM_DEBUG(llvm::dbgs()
521<<
"Processing Block "<<
Block->getBlockID() <<
"\n");
522 if(++BlockVisits > MaxBlockVisits) {
523 returnllvm::createStringError(std::errc::timed_out,
524 "maximum number of blocks processed");
527 conststd::optional<TypeErasedDataflowAnalysisState> &OldBlockState =
532llvm::errs() <<
"New Env:\n";
538llvm::errs() <<
"Old Env:\n";
539OldBlockState->Env.dump();
543NewBlockState.
Lattice, OldBlockState->Lattice);
546 if(Effect1 == LatticeJoinEffect::Unchanged &&
547Effect2 == LatticeJoinEffect::Unchanged) {
550AC.Log.blockConverged();
553}
else if(
Analysis.isEqualTypeErased(OldBlockState->Lattice,
555OldBlockState->Env.equivalentTo(NewBlockState.
Env,
Analysis)) {
558AC.Log.blockConverged();
566 if(
Block->hasNoReturnElement())
574 if(PostAnalysisCallbacks.
Before|| PostAnalysisCallbacks.
After) {
static const Stmt * getTerminatorCondition(const CFGBlock *B)
A customized wrapper for CFGBlock::getTerminatorCondition() which returns the element for ObjCForColl...
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
static void print(llvm::raw_ostream &OS, const T &V, ASTContext &ASTCtx, QualType Ty)
llvm::ArrayRef< std::optional< TypeErasedDataflowAnalysisState > > BlockStates
Stores the state of a CFG block if it has been evaluated by the analysis.
const Environment & InitEnv
Initial state to start the analysis.
TypeErasedDataflowAnalysis & Analysis
The analysis to be run.
const AdornedCFG & ACFG
Contains the CFG being analyzed.
This class represents a potential adjacent block in the CFG.
Represents a single basic block in a source-level CFG.
succ_iterator succ_begin()
const Stmt * getLoopTarget() const
unsigned getBlockID() const
Represents a top-level expression in a basic block.
T castAs() const
Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type.
Represents C++ base or member initializer from constructor's initialization list.
CXXCtorInitializer * getInitializer() const
Represents the point where the lifetime of an automatic object ends.
const VarDecl * getVarDecl() const
const Stmt * getStmt() const
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
unsigned size() const
Return the total number of CFGBlocks within the CFG This is simply a renaming of the getNumBlockIDs()...
Represents a C++ base or member initializer.
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
const CFGBlock * dequeue()
This represents one expression.
Represents a member of a struct/union/class.
IfStmt - This represents an if/then/else.
Represents a field injected from an anonymous union/struct into the parent scope.
ArrayRef< NamedDecl * > chain() const
Stmt - This represents one statement.
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.
const Formula & formula() const
Holds the state of the program (store and heap) at a given program point.
LatticeEffect widen(const Environment &PrevEnv, Environment::ValueModel &Model)
Widens the environment point-wise, using PrevEnv as needed to inform the approximation.
LLVM_DUMP_METHOD void dump() const
Environment fork() const
Returns a new environment that is a copy of this one.
ExprJoinBehavior
How to treat expression state (ExprToLoc and ExprToVal) in a join.
A storage location for a record (struct, class, or union).
StorageLocation * getChild(const ValueDecl &D) const
Returns the child storage location for D.
void setChild(const ValueDecl &D, StorageLocation *Loc)
Changes the child storage location for a field D of reference type.
Maps statements to the environments of basic blocks that contain them.
Base class for elements of the local variable store and of the heap.
Type-erased base class for dataflow analyses built on a single lattice type.
constexpr XRayInstrMask All
void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env, Environment::ValueModel &Model)
Evaluates S and updates Env accordingly.
static TypeErasedDataflowAnalysisState computeBlockInputState(const CFGBlock &Block, AnalysisContext &AC)
Computes the input state for a given basic block by joining the output states of its predecessors.
static void builtinTransfer(unsigned CurBlockID, const CFGElement &Elt, TypeErasedDataflowAnalysisState &State, AnalysisContext &AC)
static void builtinTransferInitializer(const CFGInitializer &Elt, TypeErasedDataflowAnalysisState &InputState)
Built-in transfer function for CFGInitializer.
static TypeErasedDataflowAnalysisState transferCFGBlock(const CFGBlock &Block, AnalysisContext &AC, const CFGEltCallbacksTypeErased &PostAnalysisCallbacks={})
Transfers State by evaluating each element in the Block based on the AC.Analysis specified.
static int blockIndexInPredecessor(const CFGBlock &Pred, const CFGBlock &Block)
Returns the index of Block in the successors of Pred.
static bool isBackedgeNode(const CFGBlock &B)
llvm::Expected< std::vector< std::optional< TypeErasedDataflowAnalysisState > > > runTypeErasedDataflowAnalysis(const AdornedCFG &ACFG, TypeErasedDataflowAnalysis &Analysis, const Environment &InitEnv, const CFGEltCallbacksTypeErased &PostAnalysisCallbacks, std::int32_t MaxBlockVisits)
Performs dataflow analysis and returns a mapping from basic block IDs to dataflow analysis states tha...
static void builtinTransferStatement(unsigned CurBlockID, const CFGStmt &Elt, TypeErasedDataflowAnalysisState &InputState, AnalysisContext &AC)
Built-in transfer function for CFGStmt.
LatticeEffect
Effect indicating whether a lattice operation resulted in a new value.
The JSON file list parser is used to communicate input to InstallAPI.
Diagnostic wrappers for TextAPI types for error reporting.
A worklist implementation for forward dataflow analysis.
void enqueueSuccessors(const CFGBlock *Block)
A pair of callbacks to be called with the state before and after visiting a CFG element.
CFGEltCallbackTypeErased Before
CFGEltCallbackTypeErased After
Type-erased model of the program at a given program point.
TypeErasedLattice Lattice
Type-erased model of a program property.
Environment Env
Model of the state of the program (store and heap).
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