(
Block==
nullptr) {
50 if(
Block->getBlockID() == CurBlockID)
51 return&CurState.
Env;
52 const auto&State = BlockToState[
Block->getBlockID()];
63 if(LHSValue == RHSValue)
66 if(
auto*LHSBool = dyn_cast_or_null<BoolValue>(LHSValue))
67 if(
auto*RHSBool = dyn_cast_or_null<BoolValue>(RHSValue))
70 if(
auto*LHSPtr = dyn_cast_or_null<PointerValue>(LHSValue))
71 if(
auto*RHSPtr = dyn_cast_or_null<PointerValue>(RHSValue))
75 if(&LHSPtr->getPointeeLoc() == &RHSPtr->getPointeeLoc())
82 if(
auto*Top = llvm::dyn_cast<TopBoolValue>(&
V)) {
98 auto*B = dyn_cast_or_null<BoolValue>(Val);
103 if(&UnpackedVal == Val)
138TransferVisitor(
constStmtToEnvMap &StmtToEnv, Environment &Env,
139Environment::ValueModel &Model)
140: StmtToEnv(StmtToEnv),
Env(
Env), Model(Model) {}
142 voidVisitBinaryOperator(
constBinaryOperator *S) {
143 constExpr *LHS = S->getLHS();
144assert(LHS !=
nullptr);
146 constExpr *RHS = S->getRHS();
147assert(RHS !=
nullptr);
153 if(S->isCompoundAssignmentOp())
156 switch(S->getOpcode()) {
158 auto*LHSLoc =
Env.getStorageLocation(*LHS);
159 if(LHSLoc ==
nullptr)
162 auto*RHSVal =
Env.getValue(*RHS);
163 if(RHSVal ==
nullptr)
167 Env.setValue(*LHSLoc, *RHSVal);
170 Env.setStorageLocation(*S, *LHSLoc);
175BoolValue &LHSVal = getLogicOperatorSubExprValue(*LHS);
176BoolValue &RHSVal = getLogicOperatorSubExprValue(*RHS);
178 if(S->getOpcode() == BO_LAnd)
179 Env.setValue(*S,
Env.makeAnd(LHSVal, RHSVal));
181 Env.setValue(*S,
Env.makeOr(LHSVal, RHSVal));
187 Env.setValue(*S, S->getOpcode() == BO_EQ ? LHSEqRHSValue
188:
Env.makeNot(LHSEqRHSValue));
200 voidVisitDeclRefExpr(
constDeclRefExpr *S) {
201 constValueDecl *VD = S->getDecl();
202assert(VD !=
nullptr);
216 auto*DeclLoc =
Env.getStorageLocation(*VD);
217 if(DeclLoc ==
nullptr)
220 Env.setStorageLocation(*S, *DeclLoc);
223 voidVisitDeclStmt(
constDeclStmt *S) {
226 const auto&
D= *cast<VarDecl>(S->getSingleDecl());
231 voidProcessVarDecl(
constVarDecl &
D) {
233 if(
D.hasGlobalStorage())
239 if(
D.getType()->isReferenceType() &&
Env.getStorageLocation(
D) !=
nullptr)
242assert(
Env.getStorageLocation(
D) ==
nullptr);
244 Env.setStorageLocation(
D,
Env.createObject(
D));
249 if(
const auto*Decomp = dyn_cast<DecompositionDecl>(&
D)) {
255 for(
const auto*B : Decomp->bindings()) {
256 if(
auto*ME = dyn_cast_or_null<MemberExpr>(B->getBinding())) {
257 auto*DE = dyn_cast_or_null<DeclRefExpr>(ME->getBase());
263VisitDeclRefExpr(DE);
266 if(
auto*
Loc=
Env.getStorageLocation(*ME))
267 Env.setStorageLocation(*B, *
Loc);
268}
else if(
auto*VD = B->getHoldingVar()) {
276 auto*VDLoc =
Env.getStorageLocation(*VD);
277assert(VDLoc !=
nullptr);
278 Env.setStorageLocation(*B, *VDLoc);
284 voidVisitImplicitCastExpr(
constImplicitCastExpr *S) {
285 constExpr *SubExpr = S->getSubExpr();
286assert(SubExpr !=
nullptr);
288 switch(S->getCastKind()) {
289 caseCK_IntegralToBoolean: {
293 if(
auto*SubExprVal =
294dyn_cast_or_null<BoolValue>(
Env.getValue(*SubExpr)))
295 Env.setValue(*S, *SubExprVal);
299 Env.setValue(*S,
Env.makeAtomicBoolValue());
303 caseCK_LValueToRValue: {
307 if(SubExprVal ==
nullptr)
310 Env.setValue(*S, *SubExprVal);
314 caseCK_IntegralCast:
320 caseCK_UncheckedDerivedToBase:
321 caseCK_ConstructorConversion:
322 caseCK_UserDefinedConversion:
332 caseCK_NullToPointer: {
333 auto&NullPointerVal =
334 Env.getOrCreateNullPointerValue(S->getType()->getPointeeType());
335 Env.setValue(*S, NullPointerVal);
338 caseCK_NullToMemberPointer:
342 caseCK_FunctionToPointerDecay: {
343StorageLocation *PointeeLoc =
Env.getStorageLocation(*SubExpr);
344 if(PointeeLoc ==
nullptr)
347 Env.setValue(*S,
Env.create<PointerValue>(*PointeeLoc));
350 caseCK_BuiltinFnToFnPtr:
361 voidVisitUnaryOperator(
constUnaryOperator *S) {
362 constExpr *SubExpr = S->getSubExpr();
363assert(SubExpr !=
nullptr);
365 switch(S->getOpcode()) {
367 const auto*SubExprVal =
Env.get<PointerValue>(*SubExpr);
368 if(SubExprVal ==
nullptr)
371 Env.setStorageLocation(*S, SubExprVal->getPointeeLoc());
376 if(S->getType()->isMemberPointerType())
379 if(StorageLocation *PointeeLoc =
Env.getStorageLocation(*SubExpr))
380 Env.setValue(*S,
Env.create<PointerValue>(*PointeeLoc));
384 auto*SubExprVal = dyn_cast_or_null<BoolValue>(
Env.getValue(*SubExpr));
385 if(SubExprVal ==
nullptr)
388 Env.setValue(*S,
Env.makeNot(*SubExprVal));
398 if(StorageLocation *
Loc=
Env.getStorageLocation(*S->getSubExpr()))
407 if(StorageLocation *
Loc=
Env.getStorageLocation(*S->getSubExpr()))
415 voidVisitCXXThisExpr(
constCXXThisExpr *S) {
416 auto*ThisPointeeLoc =
Env.getThisPointeeStorageLocation();
417 if(ThisPointeeLoc ==
nullptr)
422 Env.setValue(*S,
Env.create<PointerValue>(*ThisPointeeLoc));
425 voidVisitCXXNewExpr(
constCXXNewExpr *S) {
426 if(
Value*Val =
Env.createValue(S->getType()))
427 Env.setValue(*S, *Val);
430 voidVisitCXXDeleteExpr(
constCXXDeleteExpr *S) {
437 voidVisitReturnStmt(
constReturnStmt *S) {
438 if(!
Env.getDataflowAnalysisContext().getOptions().ContextSensitiveOpts)
441 auto*
Ret= S->getRetValue();
445 if(
Ret->isPRValue()) {
446 if(
Ret->getType()->isRecordType())
449 auto*Val =
Env.getValue(*Ret);
454 Env.setReturnValue(Val);
456 auto*
Loc=
Env.getStorageLocation(*Ret);
457 if(
Loc==
nullptr)
461 Env.setReturnStorageLocation(
Loc);
465 voidVisitMemberExpr(
constMemberExpr *S) {
466ValueDecl *
Member= S->getMemberDecl();
467assert(
Member!=
nullptr);
470 if(
Member->isFunctionOrFunctionTemplate())
474 if(isa<EnumConstantDecl>(
Member))
477 if(
auto*
D= dyn_cast<VarDecl>(
Member)) {
478 if(
D->hasGlobalStorage()) {
479 auto*VarDeclLoc =
Env.getStorageLocation(*
D);
480 if(VarDeclLoc ==
nullptr)
483 Env.setStorageLocation(*S, *VarDeclLoc);
489 if(BaseLoc ==
nullptr)
492 auto*MemberLoc = BaseLoc->getChild(*
Member);
493 if(MemberLoc ==
nullptr)
495 Env.setStorageLocation(*S, *MemberLoc);
498 voidVisitCXXDefaultArgExpr(
constCXXDefaultArgExpr *S) {
499 constExpr *ArgExpr = S->getExpr();
500assert(ArgExpr !=
nullptr);
503 if(S->isPRValue() && S->getType()->isRecordType()) {
504 auto&
Loc=
Env.getResultObjectLocation(*S);
505 Env.initializeFieldsWithValues(
Loc);
509 voidVisitCXXDefaultInitExpr(
constCXXDefaultInitExpr *S) {
510 constExpr *InitExpr = S->getExpr();
511assert(InitExpr !=
nullptr);
516 if(S->getType()->isRecordType() && S->isPRValue())
522 voidVisitCXXConstructExpr(
constCXXConstructExpr *S) {
523 constCXXConstructorDecl *ConstructorDecl = S->getConstructor();
524assert(ConstructorDecl !=
nullptr);
529 if(!S->getType()->isRecordType()) {
530transferInlineCall(S, ConstructorDecl);
534RecordStorageLocation &
Loc=
Env.getResultObjectLocation(*S);
536 if(ConstructorDecl->isCopyOrMoveConstructor()) {
539assert(S->getNumArgs() != 0);
541 constExpr *Arg = S->getArg(0);
542assert(Arg !=
nullptr);
544 auto*ArgLoc =
Env.get<RecordStorageLocation>(*Arg);
545 if(ArgLoc ==
nullptr)
555 Env.initializeFieldsWithValues(
Loc, S->getType());
557transferInlineCall(S, ConstructorDecl);
560 voidVisitCXXOperatorCallExpr(
constCXXOperatorCallExpr *S) {
561 if(S->getOperator() == OO_Equal) {
562assert(S->getNumArgs() == 2);
564 constExpr *Arg0 = S->getArg(0);
565assert(Arg0 !=
nullptr);
567 constExpr *Arg1 = S->getArg(1);
568assert(Arg1 !=
nullptr);
572dyn_cast_or_null<CXXMethodDecl>(S->getDirectCallee());
575 if(!Method->isCopyAssignmentOperator() &&
576!Method->isMoveAssignmentOperator())
579RecordStorageLocation *LocSrc =
nullptr;
580 if(Arg1->isPRValue()) {
581LocSrc = &
Env.getResultObjectLocation(*Arg1);
583LocSrc =
Env.get<RecordStorageLocation>(*Arg1);
585 auto*LocDst =
Env.get<RecordStorageLocation>(*Arg0);
587 if(LocSrc ==
nullptr|| LocDst ==
nullptr)
595 if(S->getType().getCanonicalType().getUnqualifiedType() !=
596LocDst->getType().getCanonicalType().getUnqualifiedType()) {
597 autoReturnDecl = S->getType()->getAsCXXRecordDecl();
598 autoDstDecl = LocDst->getType()->getAsCXXRecordDecl();
599 if(ReturnDecl ==
nullptr|| DstDecl ==
nullptr)
601 if(!DstDecl->isDerivedFrom(ReturnDecl))
606 Env.setStorageLocation(*S, *LocDst);
618 voidVisitCXXRewrittenBinaryOperator(
constCXXRewrittenBinaryOperator *RBO) {
622 voidVisitCallExpr(
constCallExpr *S) {
626 if(S->isCallToStdMove()) {
627assert(S->getNumArgs() == 1);
629 constExpr *Arg = S->getArg(0);
630assert(Arg !=
nullptr);
632 auto*ArgLoc =
Env.getStorageLocation(*Arg);
633 if(ArgLoc ==
nullptr)
636 Env.setStorageLocation(*S, *ArgLoc);
637}
else if(S->getDirectCallee() !=
nullptr&&
638S->getDirectCallee()->getBuiltinID() ==
639Builtin::BI__builtin_expect) {
640assert(S->getNumArgs() > 0);
641assert(S->getArg(0) !=
nullptr);
642 auto*ArgVal =
Env.getValue(*S->getArg(0));
643 if(ArgVal ==
nullptr)
645 Env.setValue(*S, *ArgVal);
646}
else if(
constFunctionDecl *F = S->getDirectCallee()) {
647transferInlineCall(S, F);
651 if(S->getType()->isRecordType() && S->isPRValue()) {
652RecordStorageLocation &
Loc=
Env.getResultObjectLocation(*S);
653 Env.initializeFieldsWithValues(
Loc);
658 voidVisitMaterializeTemporaryExpr(
constMaterializeTemporaryExpr *S) {
659 constExpr *SubExpr = S->getSubExpr();
660assert(SubExpr !=
nullptr);
662StorageLocation &
Loc=
Env.createStorageLocation(*S);
663 Env.setStorageLocation(*S,
Loc);
665 if(SubExpr->getType()->isRecordType())
670 if(
Value*SubExprVal =
Env.getValue(*SubExpr))
671 Env.setValue(
Loc, *SubExprVal);
674 voidVisitCXXBindTemporaryExpr(
constCXXBindTemporaryExpr *S) {
675 constExpr *SubExpr = S->getSubExpr();
676assert(SubExpr !=
nullptr);
681 voidVisitCXXStaticCastExpr(
constCXXStaticCastExpr *S) {
682 if(S->getCastKind() == CK_NoOp) {
683 constExpr *SubExpr = S->getSubExpr();
684assert(SubExpr !=
nullptr);
690 voidVisitConditionalOperator(
constConditionalOperator *S) {
691 constEnvironment *TrueEnv = StmtToEnv.getEnvironment(*S->getTrueExpr());
692 constEnvironment *FalseEnv = StmtToEnv.getEnvironment(*S->getFalseExpr());
694 if(TrueEnv ==
nullptr|| FalseEnv ==
nullptr) {
702 if(S->isGLValue()) {
703StorageLocation *TrueLoc = TrueEnv->getStorageLocation(*S->getTrueExpr());
704StorageLocation *FalseLoc =
705FalseEnv->getStorageLocation(*S->getFalseExpr());
706 if(TrueLoc == FalseLoc && TrueLoc !=
nullptr)
707 Env.setStorageLocation(*S, *TrueLoc);
708}
else if(!S->getType()->isRecordType()) {
725S->getType(), TrueEnv->getValue(*S->getTrueExpr()), *TrueEnv,
726FalseEnv->getValue(*S->getFalseExpr()), *FalseEnv, Env, Model))
727 Env.setValue(*S, *Val);
731 voidVisitInitListExpr(
constInitListExpr *S) {
732QualType
Type= S->getType();
734 if(!
Type->isRecordType()) {
737 if(!
Type->isArrayType() && S->getNumInits() == 1)
743 if(S->isSemanticForm() && S->isTransparent())
746RecordStorageLocation &
Loc=
Env.getResultObjectLocation(*S);
753RecordInitListHelper InitListHelper(S);
755 for(
auto[Field,
Init] : InitListHelper.field_inits()) {
756 if(
Field->getType()->isRecordType())
758 if(
Field->getType()->isReferenceType()) {
759assert(
Field->getType().getCanonicalType()->getPointeeType() ==
760 Init->getType().getCanonicalType());
764assert(
Field->getType().getCanonicalType().getUnqualifiedType() ==
765 Init->getType().getCanonicalType().getUnqualifiedType());
766StorageLocation *FieldLoc =
Loc.getChild(*Field);
768assert(FieldLoc !=
nullptr);
770 if(Val ==
nullptr&& isa<ImplicitValueInitExpr>(
Init) &&
771 Init->getType()->isPointerType())
773&
Env.getOrCreateNullPointerValue(
Init->getType()->getPointeeType());
775Val =
Env.createValue(
Field->getType());
777 Env.setValue(*FieldLoc, *Val);
780 for(
const auto&[FieldName, FieldLoc] :
Loc.synthetic_fields()) {
781QualType FieldType = FieldLoc->getType();
782 if(FieldType->isRecordType()) {
783 Env.initializeFieldsWithValues(*cast<RecordStorageLocation>(FieldLoc));
785 if(
Value*Val =
Env.createValue(FieldType))
786 Env.setValue(*FieldLoc, *Val);
793 voidVisitCXXBoolLiteralExpr(
constCXXBoolLiteralExpr *S) {
794 Env.setValue(*S,
Env.getBoolLiteralValue(S->getValue()));
797 voidVisitIntegerLiteral(
constIntegerLiteral *S) {
798 Env.setValue(*S,
Env.getIntLiteralValue(S->getValue()));
801 voidVisitParenExpr(
constParenExpr *S) {
805 auto*SubExpr = S->getSubExpr();
806assert(SubExpr !=
nullptr);
810 voidVisitExprWithCleanups(
constExprWithCleanups *S) {
814 auto*SubExpr = S->getSubExpr();
815assert(SubExpr !=
nullptr);
821BoolValue &getLogicOperatorSubExprValue(
constExpr &SubExpr) {
825 if(
constEnvironment *SubExprEnv = StmtToEnv.getEnvironment(SubExpr))
827dyn_cast_or_null<BoolValue>(SubExprEnv->getValue(SubExpr)))
835 if(
Env.getValue(SubExpr) ==
nullptr)
837 if(
auto*Val = dyn_cast_or_null<BoolValue>(
Env.getValue(SubExpr)))
842 return Env.makeAtomicBoolValue();
847 template<
typenameE>
848 voidtransferInlineCall(
const E*S,
constFunctionDecl *F) {
849 const auto&Options =
Env.getDataflowAnalysisContext().getOptions();
850 if(!(Options.ContextSensitiveOpts &&
851 Env.canDescend(Options.ContextSensitiveOpts->Depth, F)))
854 constAdornedCFG *ACFG =
Env.getDataflowAnalysisContext().getAdornedCFG(F);
862 autoExitBlock = ACFG->getCFG().getExit().getBlockID();
864 autoCalleeEnv =
Env.pushCall(S);
869 auto Analysis= NoopAnalysis(ACFG->getDecl().getASTContext(),
870DataflowAnalysisOptions{Options});
872 autoBlockToOutputState =
874assert(BlockToOutputState);
875assert(ExitBlock < BlockToOutputState->size());
877 auto&ExitState = (*BlockToOutputState)[ExitBlock];
880 Env.popCall(S, ExitState->Env);
883 constStmtToEnvMap &StmtToEnv;
885Environment::ValueModel &Model;
892TransferVisitor(StmtToEnv,
Env, Model).Visit(&S);
Defines enum values for all the target-independent builtin functions.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::Expr interface and subclasses for C++ expressions.
Defines an enumeration for C++ overloaded operators.
TypeErasedDataflowAnalysis & Analysis
The analysis to be run.
Represents a single basic block in a source-level CFG.
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
This represents one expression.
Stmt - This represents one statement.
bool isRecordType() const
const CFGBlock * blockForStmt(const Stmt &S) const
Returns the basic block that contains S, or null if no basic block containing S is found.
bool isBlockReachable(const CFGBlock &B) const
Returns whether B is reachable from the entry block.
BoolValue & makeBoolValue(const Formula &)
Creates a BoolValue wrapping a particular formula.
Supplements Environment with non-standard comparison and join operations.
Holds the state of the program (store and heap) at a given program point.
BoolValue & makeIff(BoolValue &LHS, BoolValue &RHS) const
Returns a boolean value represents LHS <=> RHS.
StorageLocation * getStorageLocation(const ValueDecl &D) const
Returns the storage location assigned to D in the environment, or null if D isn't assigned a storage ...
BoolValue & makeAtomicBoolValue() const
Returns an atomic boolean value.
Value * getValue(const StorageLocation &Loc) const
Returns the value assigned to Loc in the environment or null if Loc isn't assigned a value in the env...
BoolValue & getBoolLiteralValue(bool Value) const
Returns a symbolic boolean value that models a boolean literal equal to Value
DataflowAnalysisContext & getDataflowAnalysisContext() const
Returns the DataflowAnalysisContext used by the environment.
static Value * joinValues(QualType Ty, Value *Val1, const Environment &Env1, Value *Val2, const Environment &Env2, Environment &JoinedEnv, Environment::ValueModel &Model)
Returns a value that approximates both Val1 and Val2, or null if no such value can be produced.
void setStorageLocation(const ValueDecl &D, StorageLocation &Loc)
Assigns Loc as the storage location of D in the environment.
void setValue(const StorageLocation &Loc, Value &Val)
Assigns Val as the value of Loc in the environment.
Maps statements to the environments of basic blocks that contain them.
const Environment * getEnvironment(const Stmt &S) const
Returns the environment of the basic block that contains S.
Base class for all values computed by abstract interpretation.
void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env, Environment::ValueModel &Model)
Evaluates S and updates Env accordingly.
static void propagateValueOrStorageLocation(const Expr &From, const Expr &To, Environment &Env)
static void propagateStorageLocation(const Expr &From, const Expr &To, Environment &Env)
static void propagateValue(const Expr &From, const Expr &To, Environment &Env)
static Value * maybeUnpackLValueExpr(const Expr &E, Environment &Env)
void copyRecord(RecordStorageLocation &Src, RecordStorageLocation &Dst, Environment &Env)
Copies a record (struct, class, or union) from Src to Dst.
static BoolValue & unpackValue(BoolValue &V, Environment &Env)
static BoolValue & evaluateBooleanEquality(const Expr &LHS, const Expr &RHS, Environment &Env)
RecordStorageLocation * getBaseObjectLocation(const MemberExpr &ME, const Environment &Env)
Returns the storage location for the base object of a MemberExpr, or null if none is defined in the e...
llvm::Expected< std::vector< std::optional< DataflowAnalysisState< typename AnalysisT::Lattice > > > > runDataflowAnalysis(const AdornedCFG &ACFG, AnalysisT &Analysis, const Environment &InitEnv, CFGEltCallbacks< AnalysisT > PostAnalysisCallbacks={}, std::int32_t MaxBlockVisits=kDefaultMaxBlockVisits)
Performs dataflow analysis and returns a mapping from basic block IDs to dataflow analysis states tha...
bool Ret(InterpState &S, CodePtr &PC)
The JSON file list parser is used to communicate input to InstallAPI.
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