clang: lib/Analysis/FlowSensitive/Transfer.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
32#include "llvm/Support/Casting.h"
33#include "llvm/Support/Debug.h"
35#include
36
37#define DEBUG_TYPE "dataflow"
38
40namespace dataflow {
41
44 if (Block == nullptr) {
45 assert(false);
46 return nullptr;
47 }
49 return nullptr;
50 if (Block->getBlockID() == CurBlockID)
51 return &CurState.Env;
52 const auto &State = BlockToState[Block->getBlockID()];
53 if (!(State))
54 return nullptr;
55 return &State->Env;
56}
57
62
63 if (LHSValue == RHSValue)
65
66 if (auto *LHSBool = dyn_cast_or_null(LHSValue))
67 if (auto *RHSBool = dyn_cast_or_null(RHSValue))
68 return Env.makeIff(*LHSBool, *RHSBool);
69
70 if (auto *LHSPtr = dyn_cast_or_null(LHSValue))
71 if (auto *RHSPtr = dyn_cast_or_null(RHSValue))
72
73
74
75 if (&LHSPtr->getPointeeLoc() == &RHSPtr->getPointeeLoc())
77
79}
80
82 if (auto *Top = llvm::dyn_cast(&V)) {
84 return A.makeBoolValue(A.makeAtomRef(Top->getAtom()));
85 }
86 return V;
87}
88
89
90
91
94 if (Loc == nullptr)
95 return nullptr;
97
98 auto *B = dyn_cast_or_null(Val);
99 if (B == nullptr)
100 return Val;
101
103 if (&UnpackedVal == Val)
104 return Val;
106 return &UnpackedVal;
107}
108
111 return;
114}
115
120}
121
122
123
124
130 else
132}
133
134namespace {
135
136class TransferVisitor : public ConstStmtVisitor {
137public:
138 TransferVisitor(const StmtToEnvMap &StmtToEnv, Environment &Env,
139 Environment::ValueModel &Model)
140 : StmtToEnv(StmtToEnv), Env(Env), Model(Model) {}
141
142 void VisitBinaryOperator(const BinaryOperator *S) {
143 const Expr *LHS = S->getLHS();
144 assert(LHS != nullptr);
145
146 const Expr *RHS = S->getRHS();
147 assert(RHS != nullptr);
148
149
150
151
152
153 if (S->isCompoundAssignmentOp())
155
156 switch (S->getOpcode()) {
157 case BO_Assign: {
158 auto *LHSLoc = Env.getStorageLocation(*LHS);
159 if (LHSLoc == nullptr)
160 break;
161
162 auto *RHSVal = Env.getValue(*RHS);
163 if (RHSVal == nullptr)
164 break;
165
166
167 Env.setValue(*LHSLoc, *RHSVal);
168
169
170 Env.setStorageLocation(*S, *LHSLoc);
171 break;
172 }
173 case BO_LAnd:
174 case BO_LOr: {
175 BoolValue &LHSVal = getLogicOperatorSubExprValue(*LHS);
176 BoolValue &RHSVal = getLogicOperatorSubExprValue(*RHS);
177
178 if (S->getOpcode() == BO_LAnd)
179 Env.setValue(*S, Env.makeAnd(LHSVal, RHSVal));
180 else
181 Env.setValue(*S, Env.makeOr(LHSVal, RHSVal));
182 break;
183 }
184 case BO_NE:
185 case BO_EQ: {
187 Env.setValue(*S, S->getOpcode() == BO_EQ ? LHSEqRHSValue
188 : Env.makeNot(LHSEqRHSValue));
189 break;
190 }
191 case BO_Comma: {
193 break;
194 }
195 default:
196 break;
197 }
198 }
199
200 void VisitDeclRefExpr(const DeclRefExpr *S) {
201 const ValueDecl *VD = S->getDecl();
202 assert(VD != nullptr);
203
204
205
206
207
208
209
210
211
212
213 if (!S->isGLValue())
214 return;
215
216 auto *DeclLoc = Env.getStorageLocation(*VD);
217 if (DeclLoc == nullptr)
218 return;
219
220 Env.setStorageLocation(*S, *DeclLoc);
221 }
222
223 void VisitDeclStmt(const DeclStmt *S) {
224
225
226 const auto &D = *cast(S->getSingleDecl());
227
228 ProcessVarDecl(D);
229 }
230
231 void ProcessVarDecl(const VarDecl &D) {
232
233 if (D.hasGlobalStorage())
234 return;
235
236
237
238
239 if (D.getType()->isReferenceType() && Env.getStorageLocation(D) != nullptr)
240 return;
241
242 assert(Env.getStorageLocation(D) == nullptr);
243
244 Env.setStorageLocation(D, Env.createObject(D));
245
246
247
248
249 if (const auto *Decomp = dyn_cast(&D)) {
250
251
252
253
254
255 for (const auto *B : Decomp->bindings()) {
256 if (auto *ME = dyn_cast_or_null(B->getBinding())) {
257 auto *DE = dyn_cast_or_null(ME->getBase());
258 if (DE == nullptr)
259 continue;
260
261
262
263 VisitDeclRefExpr(DE);
264 VisitMemberExpr(ME);
265
266 if (auto *Loc = Env.getStorageLocation(*ME))
267 Env.setStorageLocation(*B, *Loc);
268 } else if (auto *VD = B->getHoldingVar()) {
269
270
271
272
273
274
275 ProcessVarDecl(*VD);
276 auto *VDLoc = Env.getStorageLocation(*VD);
277 assert(VDLoc != nullptr);
278 Env.setStorageLocation(*B, *VDLoc);
279 }
280 }
281 }
282 }
283
284 void VisitImplicitCastExpr(const ImplicitCastExpr *S) {
285 const Expr *SubExpr = S->getSubExpr();
286 assert(SubExpr != nullptr);
287
288 switch (S->getCastKind()) {
289 case CK_IntegralToBoolean: {
290
291
292
293 if (auto *SubExprVal =
294 dyn_cast_or_null(Env.getValue(*SubExpr)))
295 Env.setValue(*S, *SubExprVal);
296 else
297
298
299 Env.setValue(*S, Env.makeAtomicBoolValue());
300 break;
301 }
302
303 case CK_LValueToRValue: {
304
305
307 if (SubExprVal == nullptr)
308 break;
309
310 Env.setValue(*S, *SubExprVal);
311 break;
312 }
313
314 case CK_IntegralCast:
315
316
317
318
319
320 case CK_UncheckedDerivedToBase:
321 case CK_ConstructorConversion:
322 case CK_UserDefinedConversion:
323
324
325 case CK_NoOp: {
326
327
328
330 break;
331 }
332 case CK_NullToPointer: {
333 auto &NullPointerVal =
334 Env.getOrCreateNullPointerValue(S->getType()->getPointeeType());
335 Env.setValue(*S, NullPointerVal);
336 break;
337 }
338 case CK_NullToMemberPointer:
339
340
341 break;
342 case CK_FunctionToPointerDecay: {
343 StorageLocation *PointeeLoc = Env.getStorageLocation(*SubExpr);
344 if (PointeeLoc == nullptr)
345 break;
346
347 Env.setValue(*S, Env.create(*PointeeLoc));
348 break;
349 }
350 case CK_BuiltinFnToFnPtr:
351
352
353
354
355 break;
356 default:
357 break;
358 }
359 }
360
361 void VisitUnaryOperator(const UnaryOperator *S) {
362 const Expr *SubExpr = S->getSubExpr();
363 assert(SubExpr != nullptr);
364
365 switch (S->getOpcode()) {
366 case UO_Deref: {
367 const auto *SubExprVal = Env.get(*SubExpr);
368 if (SubExprVal == nullptr)
369 break;
370
371 Env.setStorageLocation(*S, SubExprVal->getPointeeLoc());
372 break;
373 }
374 case UO_AddrOf: {
375
376 if (S->getType()->isMemberPointerType())
377 break;
378
379 if (StorageLocation *PointeeLoc = Env.getStorageLocation(*SubExpr))
380 Env.setValue(*S, Env.create(*PointeeLoc));
381 break;
382 }
383 case UO_LNot: {
384 auto *SubExprVal = dyn_cast_or_null(Env.getValue(*SubExpr));
385 if (SubExprVal == nullptr)
386 break;
387
388 Env.setValue(*S, Env.makeNot(*SubExprVal));
389 break;
390 }
391 case UO_PreInc:
392 case UO_PreDec:
393
394
395
396
398 if (StorageLocation *Loc = Env.getStorageLocation(*S->getSubExpr()))
400 break;
401 case UO_PostInc:
402 case UO_PostDec:
403
404
405
407 if (StorageLocation *Loc = Env.getStorageLocation(*S->getSubExpr()))
409 break;
410 default:
411 break;
412 }
413 }
414
415 void VisitCXXThisExpr(const CXXThisExpr *S) {
416 auto *ThisPointeeLoc = Env.getThisPointeeStorageLocation();
417 if (ThisPointeeLoc == nullptr)
418
419
420 return;
421
422 Env.setValue(*S, Env.create(*ThisPointeeLoc));
423 }
424
425 void VisitCXXNewExpr(const CXXNewExpr *S) {
426 if (Value *Val = Env.createValue(S->getType()))
427 Env.setValue(*S, *Val);
428 }
429
430 void VisitCXXDeleteExpr(const CXXDeleteExpr *S) {
431
432
433
434
435 }
436
437 void VisitReturnStmt(const ReturnStmt *S) {
438 if (.getDataflowAnalysisContext().getOptions().ContextSensitiveOpts)
439 return;
440
441 auto *Ret = S->getRetValue();
442 if (Ret == nullptr)
443 return;
444
445 if (Ret->isPRValue()) {
446 if (Ret->getType()->isRecordType())
447 return;
448
449 auto *Val = Env.getValue(*Ret);
450 if (Val == nullptr)
451 return;
452
453
454 Env.setReturnValue(Val);
455 } else {
456 auto *Loc = Env.getStorageLocation(*Ret);
457 if (Loc == nullptr)
458 return;
459
460
461 Env.setReturnStorageLocation(Loc);
462 }
463 }
464
465 void VisitMemberExpr(const MemberExpr *S) {
466 ValueDecl *Member = S->getMemberDecl();
467 assert(Member != nullptr);
468
469
470 if (Member->isFunctionOrFunctionTemplate())
471 return;
472
473
474 if (isa(Member))
475 return;
476
477 if (auto *D = dyn_cast(Member)) {
478 if (D->hasGlobalStorage()) {
479 auto *VarDeclLoc = Env.getStorageLocation(*D);
480 if (VarDeclLoc == nullptr)
481 return;
482
483 Env.setStorageLocation(*S, *VarDeclLoc);
484 return;
485 }
486 }
487
489 if (BaseLoc == nullptr)
490 return;
491
492 auto *MemberLoc = BaseLoc->getChild(*Member);
493 if (MemberLoc == nullptr)
494 return;
495 Env.setStorageLocation(*S, *MemberLoc);
496 }
497
498 void VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *S) {
499 const Expr *ArgExpr = S->getExpr();
500 assert(ArgExpr != nullptr);
502
503 if (S->isPRValue() && S->getType()->isRecordType()) {
504 auto &Loc = Env.getResultObjectLocation(*S);
505 Env.initializeFieldsWithValues(Loc);
506 }
507 }
508
509 void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *S) {
510 const Expr *InitExpr = S->getExpr();
511 assert(InitExpr != nullptr);
512
513
514
515
516 if (S->getType()->isRecordType() && S->isPRValue())
517 return;
518
520 }
521
522 void VisitCXXConstructExpr(const CXXConstructExpr *S) {
523 const CXXConstructorDecl *ConstructorDecl = S->getConstructor();
524 assert(ConstructorDecl != nullptr);
525
526
527
528
529 if (!S->getType()->isRecordType()) {
530 transferInlineCall(S, ConstructorDecl);
531 return;
532 }
533
534 RecordStorageLocation &Loc = Env.getResultObjectLocation(*S);
535
536 if (ConstructorDecl->isCopyOrMoveConstructor()) {
537
538
539 assert(S->getNumArgs() != 0);
540
541 const Expr *Arg = S->getArg(0);
542 assert(Arg != nullptr);
543
544 auto *ArgLoc = Env.get(*Arg);
545 if (ArgLoc == nullptr)
546 return;
547
548
549
550
552 return;
553 }
554
555 Env.initializeFieldsWithValues(Loc, S->getType());
556
557 transferInlineCall(S, ConstructorDecl);
558 }
559
560 void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) {
561 if (S->getOperator() == OO_Equal) {
562 assert(S->getNumArgs() == 2);
563
564 const Expr *Arg0 = S->getArg(0);
565 assert(Arg0 != nullptr);
566
567 const Expr *Arg1 = S->getArg(1);
568 assert(Arg1 != nullptr);
569
570
571 const auto *Method =
572 dyn_cast_or_null(S->getDirectCallee());
573 if (!Method)
574 return;
575 if (!Method->isCopyAssignmentOperator() &&
576 !Method->isMoveAssignmentOperator())
577 return;
578
579 RecordStorageLocation *LocSrc = nullptr;
580 if (Arg1->isPRValue()) {
581 LocSrc = &Env.getResultObjectLocation(*Arg1);
582 } else {
583 LocSrc = Env.get(*Arg1);
584 }
585 auto *LocDst = Env.get(*Arg0);
586
587 if (LocSrc == nullptr || LocDst == nullptr)
588 return;
589
591
592
593
594
595 if (S->getType().getCanonicalType().getUnqualifiedType() !=
596 LocDst->getType().getCanonicalType().getUnqualifiedType()) {
597 auto ReturnDecl = S->getType()->getAsCXXRecordDecl();
598 auto DstDecl = LocDst->getType()->getAsCXXRecordDecl();
599 if (ReturnDecl == nullptr || DstDecl == nullptr)
600 return;
601 if (!DstDecl->isDerivedFrom(ReturnDecl))
602 return;
603 }
604
605 if (S->isGLValue())
606 Env.setStorageLocation(*S, *LocDst);
607 else
608 copyRecord(*LocDst, Env.getResultObjectLocation(*S), Env);
609
610 return;
611 }
612
613
614
615 VisitCallExpr(S);
616 }
617
618 void VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator *RBO) {
620 }
621
622 void VisitCallExpr(const CallExpr *S) {
623
624
625
626 if (S->isCallToStdMove()) {
627 assert(S->getNumArgs() == 1);
628
629 const Expr *Arg = S->getArg(0);
630 assert(Arg != nullptr);
631
632 auto *ArgLoc = Env.getStorageLocation(*Arg);
633 if (ArgLoc == nullptr)
634 return;
635
636 Env.setStorageLocation(*S, *ArgLoc);
637 } else if (S->getDirectCallee() != nullptr &&
638 S->getDirectCallee()->getBuiltinID() ==
639 Builtin::BI__builtin_expect) {
640 assert(S->getNumArgs() > 0);
641 assert(S->getArg(0) != nullptr);
642 auto *ArgVal = Env.getValue(*S->getArg(0));
643 if (ArgVal == nullptr)
644 return;
645 Env.setValue(*S, *ArgVal);
646 } else if (const FunctionDecl *F = S->getDirectCallee()) {
647 transferInlineCall(S, F);
648
649
650
651 if (S->getType()->isRecordType() && S->isPRValue()) {
652 RecordStorageLocation &Loc = Env.getResultObjectLocation(*S);
653 Env.initializeFieldsWithValues(Loc);
654 }
655 }
656 }
657
658 void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *S) {
659 const Expr *SubExpr = S->getSubExpr();
660 assert(SubExpr != nullptr);
661
662 StorageLocation &Loc = Env.createStorageLocation(*S);
663 Env.setStorageLocation(*S, Loc);
664
665 if (SubExpr->getType()->isRecordType())
666
667
668 return;
669
670 if (Value *SubExprVal = Env.getValue(*SubExpr))
671 Env.setValue(Loc, *SubExprVal);
672 }
673
674 void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *S) {
675 const Expr *SubExpr = S->getSubExpr();
676 assert(SubExpr != nullptr);
677
679 }
680
681 void VisitCXXStaticCastExpr(const CXXStaticCastExpr *S) {
682 if (S->getCastKind() == CK_NoOp) {
683 const Expr *SubExpr = S->getSubExpr();
684 assert(SubExpr != nullptr);
685
687 }
688 }
689
690 void VisitConditionalOperator(const ConditionalOperator *S) {
691 const Environment *TrueEnv = StmtToEnv.getEnvironment(*S->getTrueExpr());
692 const Environment *FalseEnv = StmtToEnv.getEnvironment(*S->getFalseExpr());
693
694 if (TrueEnv == nullptr || FalseEnv == nullptr) {
695
696
697
698
699 return;
700 }
701
702 if (S->isGLValue()) {
703 StorageLocation *TrueLoc = TrueEnv->getStorageLocation(*S->getTrueExpr());
704 StorageLocation *FalseLoc =
705 FalseEnv->getStorageLocation(*S->getFalseExpr());
706 if (TrueLoc == FalseLoc && TrueLoc != nullptr)
707 Env.setStorageLocation(*S, *TrueLoc);
708 } else if (!S->getType()->isRecordType()) {
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
725 S->getType(), TrueEnv->getValue(*S->getTrueExpr()), *TrueEnv,
726 FalseEnv->getValue(*S->getFalseExpr()), *FalseEnv, Env, Model))
727 Env.setValue(*S, *Val);
728 }
729 }
730
731 void VisitInitListExpr(const InitListExpr *S) {
732 QualType Type = S->getType();
733
734 if (->isRecordType()) {
735
736
737 if (->isArrayType() && S->getNumInits() == 1)
739 return;
740 }
741
742
743 if (S->isSemanticForm() && S->isTransparent())
744 return;
745
746 RecordStorageLocation &Loc = Env.getResultObjectLocation(*S);
747
748
749
750
751
752
753 RecordInitListHelper InitListHelper(S);
754
755 for (auto [Field, Init] : InitListHelper.field_inits()) {
756 if (Field->getType()->isRecordType())
757 continue;
758 if (Field->getType()->isReferenceType()) {
759 assert(Field->getType().getCanonicalType()->getPointeeType() ==
760 Init->getType().getCanonicalType());
761 Loc.setChild(*Field, &Env.createObject(Field->getType(), Init));
762 continue;
763 }
764 assert(Field->getType().getCanonicalType().getUnqualifiedType() ==
765 Init->getType().getCanonicalType().getUnqualifiedType());
766 StorageLocation *FieldLoc = Loc.getChild(*Field);
767
768 assert(FieldLoc != nullptr);
770 if (Val == nullptr && isa(Init) &&
771 Init->getType()->isPointerType())
772 Val =
773 &Env.getOrCreateNullPointerValue(Init->getType()->getPointeeType());
774 if (Val == nullptr)
775 Val = Env.createValue(Field->getType());
776 if (Val != nullptr)
777 Env.setValue(*FieldLoc, *Val);
778 }
779
780 for (const auto &[FieldName, FieldLoc] : Loc.synthetic_fields()) {
781 QualType FieldType = FieldLoc->getType();
782 if (FieldType->isRecordType()) {
783 Env.initializeFieldsWithValues(*cast(FieldLoc));
784 } else {
785 if (Value *Val = Env.createValue(FieldType))
786 Env.setValue(*FieldLoc, *Val);
787 }
788 }
789
790
791 }
792
793 void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *S) {
794 Env.setValue(*S, Env.getBoolLiteralValue(S->getValue()));
795 }
796
797 void VisitIntegerLiteral(const IntegerLiteral *S) {
798 Env.setValue(*S, Env.getIntLiteralValue(S->getValue()));
799 }
800
801 void VisitParenExpr(const ParenExpr *S) {
802
803
804
805 auto *SubExpr = S->getSubExpr();
806 assert(SubExpr != nullptr);
807 Visit(SubExpr);
808 }
809
810 void VisitExprWithCleanups(const ExprWithCleanups *S) {
811
812
813
814 auto *SubExpr = S->getSubExpr();
815 assert(SubExpr != nullptr);
816 Visit(SubExpr);
817 }
818
819private:
820
821 BoolValue &getLogicOperatorSubExprValue(const Expr &SubExpr) {
822
823
824
825 if (const Environment *SubExprEnv = StmtToEnv.getEnvironment(SubExpr))
826 if (auto *Val =
827 dyn_cast_or_null(SubExprEnv->getValue(SubExpr)))
828 return *Val;
829
830
831
832
833
834
835 if (Env.getValue(SubExpr) == nullptr)
836 Visit(&SubExpr);
837 if (auto *Val = dyn_cast_or_null(Env.getValue(SubExpr)))
838 return *Val;
839
840
841
842 return Env.makeAtomicBoolValue();
843 }
844
845
846
847 template
848 void transferInlineCall(const E *S, const FunctionDecl *F) {
849 const auto &Options = Env.getDataflowAnalysisContext().getOptions();
850 if (!(Options.ContextSensitiveOpts &&
851 Env.canDescend(Options.ContextSensitiveOpts->Depth, F)))
852 return;
853
854 const AdornedCFG *ACFG = Env.getDataflowAnalysisContext().getAdornedCFG(F);
855 if (!ACFG)
856 return;
857
858
859
860
861
862 auto ExitBlock = ACFG->getCFG().getExit().getBlockID();
863
864 auto CalleeEnv = Env.pushCall(S);
865
866
867
868
869 auto Analysis = NoopAnalysis(ACFG->getDecl().getASTContext(),
870 DataflowAnalysisOptions{Options});
871
872 auto BlockToOutputState =
874 assert(BlockToOutputState);
875 assert(ExitBlock < BlockToOutputState->size());
876
877 auto &ExitState = (*BlockToOutputState)[ExitBlock];
878 assert(ExitState);
879
880 Env.popCall(S, ExitState->Env);
881 }
882
883 const StmtToEnvMap &StmtToEnv;
884 Environment &Env;
885 Environment::ValueModel &Model;
886};
887
888}
889
892 TransferVisitor(StmtToEnv, Env, Model).Visit(&S);
893}
894
895}
896}
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).