llvm::DenseMap<const ValueDecl *, StorageLocation *> &DeclToLoc1,
52 constllvm::DenseMap<const ValueDecl *, StorageLocation *> &DeclToLoc2) {
53llvm::DenseMap<const ValueDecl *, StorageLocation *>
Result;
54 for(
auto&Entry : DeclToLoc1) {
55 autoIt = DeclToLoc2.find(Entry.first);
56 if(It != DeclToLoc2.end() && Entry.second == It->second)
57 Result.insert({Entry.first, Entry.second});
67template<
typenameMapT>
71 for(
const auto&Entry : Map2) {
72[[maybe_unused]]
auto[It, Inserted] =
Result.insert(Entry);
75assert(It->second == Entry.second);
107 switch(Model.
compare(
Type, Val1, Env1, Val2, Env2)) {
115llvm_unreachable(
"All cases covered in switch");
129 if(isa<BoolValue>(&Val1) && isa<BoolValue>(&Val2)) {
143 auto&Expr1 = cast<BoolValue>(Val1).formula();
144 auto&Expr2 = cast<BoolValue>(Val2).formula();
145 auto&A = JoinedEnv.
arena();
149A.makeEquals(JoinedVal, Expr1)),
151A.makeEquals(JoinedVal, Expr2))));
152 return&A.makeBoolValue(JoinedVal);
157Model.
join(
Type, Val1, Env1, Val2, Env2, *JoinedVal, JoinedEnv);
167 if(isa<BoolValue>(Prev) && isa<BoolValue>(Current)) {
171 auto&PrevBool = cast<BoolValue>(Prev);
172 auto&CurBool = cast<BoolValue>(Current);
174 if(isa<TopBoolValue>(Prev))
182 boolTruePrev = PrevEnv.
proves(PrevBool.formula());
183 boolTrueCur = CurrentEnv.
proves(CurBool.formula());
184 if(TruePrev && TrueCur)
186 if(!TruePrev && !TrueCur &&
197 if(
auto Result= Model.
widen(
Type, Prev, PrevEnv, Current, CurrentEnv))
207template<
typenameKey>
209 constllvm::MapVector<Key, Value *> &Map2,
213 for(
auto&Entry : Map1) {
215assert(K !=
nullptr);
217 Value*Val = Entry.second;
218assert(Val !=
nullptr);
220 autoIt = Map2.find(K);
221 if(It == Map2.end())
223assert(It->second !=
nullptr);
235staticllvm::MapVector<const StorageLocation *, Value *>
236joinLocToVal(
constllvm::MapVector<const StorageLocation *, Value *> &LocToVal,
237 constllvm::MapVector<const StorageLocation *, Value *> &LocToVal2,
240llvm::MapVector<const StorageLocation *, Value *>
Result;
241 for(
auto&Entry : LocToVal) {
243assert(
Loc!=
nullptr);
245 Value*Val = Entry.second;
246assert(Val !=
nullptr);
248 autoIt = LocToVal2.find(
Loc);
249 if(It == LocToVal2.end())
251assert(It->second !=
nullptr);
254 Loc->getType(), Val, Env1, It->second, Env2, JoinedEnv, Model)) {
264template<
typenameKey>
265staticllvm::MapVector<Key, Value *>
267 constllvm::MapVector<Key, Value *> &PrevMap,
270llvm::MapVector<Key, Value *> WidenedMap;
271 for(
auto&Entry : CurMap) {
273assert(K !=
nullptr);
275 Value*Val = Entry.second;
276assert(Val !=
nullptr);
278 autoPrevIt = PrevMap.find(K);
279 if(PrevIt == PrevMap.end())
281assert(PrevIt->second !=
nullptr);
284WidenedMap.insert({K, Val});
289K->getType(), *PrevIt->second, PrevEnv, *Val, CurEnv, Model);
290WidenedMap.insert({K, WidenedVal});
303classResultObjectVisitor :
publicAnalysisASTVisitor {
309 explicitResultObjectVisitor(
310llvm::DenseMap<const Expr *, RecordStorageLocation *> &ResultObjectMap,
311RecordStorageLocation *LocForRecordReturnVal,
312DataflowAnalysisContext &DACtx)
313: ResultObjectMap(ResultObjectMap),
314LocForRecordReturnVal(LocForRecordReturnVal), DACtx(DACtx) {}
320 voidtraverseConstructorInits(
constCXXConstructorDecl *Ctor,
321RecordStorageLocation *ThisPointeeLoc) {
322assert(ThisPointeeLoc !=
nullptr);
323 for(
constCXXCtorInitializer *
Init: Ctor->inits()) {
324Expr *InitExpr =
Init->getInit();
325 if(FieldDecl *Field =
Init->getMember();
326Field !=
nullptr&& Field->getType()->isRecordType()) {
327PropagateResultObject(InitExpr, cast<RecordStorageLocation>(
328ThisPointeeLoc->getChild(*Field)));
329}
else if(
Init->getBaseClass()) {
330PropagateResultObject(InitExpr, ThisPointeeLoc);
335TraverseStmt(InitExpr);
339 if(
auto*DefaultInit = dyn_cast<CXXDefaultInitExpr>(InitExpr))
340TraverseStmt(DefaultInit->getExpr());
344 boolVisitVarDecl(VarDecl *VD)
override{
345 if(VD->getType()->isRecordType() && VD->hasInit())
346PropagateResultObject(
348&cast<RecordStorageLocation>(DACtx.getStableStorageLocation(*VD)));
352 boolVisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE)
override{
353 if(MTE->getType()->isRecordType())
354PropagateResultObject(
356&cast<RecordStorageLocation>(DACtx.getStableStorageLocation(*MTE)));
360 boolVisitReturnStmt(ReturnStmt *Return)
override{
361Expr *
RetValue= Return->getRetValue();
364PropagateResultObject(
RetValue, LocForRecordReturnVal);
368 boolVisitExpr(Expr *
E)
override{
374 if(
E->isPRValue() &&
E->getType()->isRecordType() &&
375!ResultObjectMap.contains(
E))
376PropagateResultObject(
377 E, &cast<RecordStorageLocation>(DACtx.getStableStorageLocation(*
E)));
382PropagateResultObjectToRecordInitList(
constRecordInitListHelper &InitList,
383RecordStorageLocation *
Loc) {
384 for(
auto[
Base,
Init] : InitList.base_inits()) {
385assert(
Base->getType().getCanonicalType() ==
386 Init->getType().getCanonicalType());
391PropagateResultObject(
Init,
Loc);
394 for(
auto[Field,
Init] : InitList.field_inits()) {
397 if(
Field->getType()->isRecordType())
398PropagateResultObject(
399 Init, cast<RecordStorageLocation>(
Loc->getChild(*Field)));
406 voidPropagateResultObject(Expr *
E, RecordStorageLocation *
Loc) {
407 if(!
E->isPRValue() || !
E->getType()->isRecordType()) {
414ResultObjectMap[
E] =
Loc;
419 if(isa<CXXConstructExpr>(
E) || isa<CallExpr>(
E) || isa<LambdaExpr>(
E) ||
420isa<CXXDefaultArgExpr>(
E) || isa<CXXStdInitializerListExpr>(
E) ||
421isa<AtomicExpr>(
E) || isa<CXXInheritedCtorInitExpr>(
E) ||
425isa<BuiltinBitCastExpr>(
E)) {
428 if(
auto*Op = dyn_cast<BinaryOperator>(
E);
429Op && Op->getOpcode() == BO_Cmp) {
434 if(
auto*InitList = dyn_cast<InitListExpr>(
E)) {
435 if(!InitList->isSemanticForm())
437 if(InitList->isTransparent()) {
438PropagateResultObject(InitList->getInit(0),
Loc);
442PropagateResultObjectToRecordInitList(RecordInitListHelper(InitList),
447 if(
auto*ParenInitList = dyn_cast<CXXParenListInitExpr>(
E)) {
448PropagateResultObjectToRecordInitList(RecordInitListHelper(ParenInitList),
453 if(
auto*Op = dyn_cast<BinaryOperator>(
E); Op && Op->isCommaOp()) {
454PropagateResultObject(Op->getRHS(),
Loc);
458 if(
auto*Cond = dyn_cast<AbstractConditionalOperator>(
E)) {
459PropagateResultObject(Cond->getTrueExpr(),
Loc);
460PropagateResultObject(Cond->getFalseExpr(),
Loc);
464 if(
auto*SE = dyn_cast<StmtExpr>(
E)) {
465PropagateResultObject(cast<Expr>(SE->getSubStmt()->body_back()),
Loc);
469 if(
auto*DIE = dyn_cast<CXXDefaultInitExpr>(
E)) {
470PropagateResultObject(DIE->getExpr(),
Loc);
476SmallVector<Stmt *, 1> Children(
E->child_begin(),
E->child_end());
478 if(Children.size() != 1)
481assert(Children.size() == 1);
482 for(Stmt *S : Children)
483PropagateResultObject(cast<Expr>(S),
Loc);
487llvm::DenseMap<const Expr *, RecordStorageLocation *> &ResultObjectMap;
488RecordStorageLocation *LocForRecordReturnVal;
489DataflowAnalysisContext &DACtx;
495 if(InitialTargetStmt ==
nullptr)
498 if(InitialTargetFunc ==
nullptr) {
501std::make_shared<PrValueToResultObject>(buildResultObjectMap(
509 for(
const auto*ParamDecl : InitialTargetFunc->
parameters()) {
510assert(ParamDecl !=
nullptr);
515LocForRecordReturnVal = &cast<RecordStorageLocation>(
518 if(
const auto*MethodDecl = dyn_cast<CXXMethodDecl>(InitialTargetFunc)) {
519 auto*
Parent= MethodDecl->getParent();
520assert(
Parent!=
nullptr);
522 if(
Parent->isLambda()) {
524 if(
Capture.capturesVariable()) {
528}
else if(
Capture.capturesThis()) {
530 const auto*SurroundingMethodDecl = cast<CXXMethodDecl>(Ancestor);
532SurroundingMethodDecl->getFunctionObjectParameterType();
534cast<RecordStorageLocation>(
createObject(ThisPointeeType)));
535}
else if(
auto*FieldBeingInitialized =
536dyn_cast<FieldDecl>(
Parent->getLambdaContextDecl())) {
540FieldBeingInitialized->getParent()->getTypeForDecl(), 0))));
542assert(
false&&
"Unexpected this-capturing lambda context.");
546}
else if(MethodDecl->isImplicitObjectMemberFunction()) {
547 QualTypeThisPointeeType = MethodDecl->getFunctionObjectParameterType();
554 if(!isa<CXXConstructorDecl>(MethodDecl))
562std::make_shared<PrValueToResultObject>(buildResultObjectMap(
564LocForRecordReturnVal));
570voidEnvironment::initFieldsGlobalsAndFuncs(
const ReferencedDecls&Referenced) {
573DACtx->addModeledFields(Referenced.
Fields);
603 returnCallStack.size() < MaxDepth && !llvm::is_contained(CallStack, Callee);
609 if(
const auto*MethodCall = dyn_cast<CXXMemberCallExpr>(
Call)) {
610 if(
const Expr*Arg = MethodCall->getImplicitObjectArgument()) {
611 if(!isa<CXXThisExpr>(Arg))
612 Env.ThisPointeeLoc =
619 if(
Call->getType()->isRecordType() &&
Call->isPRValue())
620 Env.LocForRecordReturnVal = &
Env.getResultObjectLocation(*
Call);
622 Env.pushCallInternal(
Call->getDirectCallee(),
631 Env.ThisPointeeLoc = &
Env.getResultObjectLocation(*
Call);
632 Env.LocForRecordReturnVal = &
Env.getResultObjectLocation(*
Call);
634 Env.pushCallInternal(
Call->getConstructor(),
640voidEnvironment::pushCallInternal(
const FunctionDecl*FuncDecl,
648CallStack.push_back(FuncDecl);
656 for(
unsignedArgIndex = 0; ArgIndex < Args.size(); ++ParamIt, ++ArgIndex) {
657assert(ParamIt != FuncDecl->
param_end());
658 const VarDecl*Param = *ParamIt;
662ResultObjectMap = std::make_shared<PrValueToResultObject>(
664LocForRecordReturnVal));
675this->LocToVal = std::move(CalleeEnv.LocToVal);
676this->FlowConditionToken = std::move(CalleeEnv.FlowConditionToken);
678 if(
Call->isGLValue()) {
679 if(CalleeEnv.ReturnLoc !=
nullptr)
681}
else if(!
Call->getType()->isVoidType()) {
682 if(CalleeEnv.ReturnVal !=
nullptr)
690this->LocToVal = std::move(CalleeEnv.LocToVal);
691this->FlowConditionToken = std::move(CalleeEnv.FlowConditionToken);
696assert(DACtx ==
Other.DACtx);
698 if(ReturnVal !=
Other.ReturnVal)
701 if(ReturnLoc !=
Other.ReturnLoc)
704 if(LocForRecordReturnVal !=
Other.LocForRecordReturnVal)
707 if(ThisPointeeLoc !=
Other.ThisPointeeLoc)
710 if(DeclToLoc !=
Other.DeclToLoc)
713 if(ExprToLoc !=
Other.ExprToLoc)
727assert(DACtx == PrevEnv.DACtx);
728assert(ReturnVal == PrevEnv.ReturnVal);
729assert(ReturnLoc == PrevEnv.ReturnLoc);
730assert(LocForRecordReturnVal == PrevEnv.LocForRecordReturnVal);
731assert(ThisPointeeLoc == PrevEnv.ThisPointeeLoc);
732assert(CallStack == PrevEnv.CallStack);
733assert(ResultObjectMap == PrevEnv.ResultObjectMap);
734assert(InitialTargetFunc == PrevEnv.InitialTargetFunc);
735assert(InitialTargetStmt == PrevEnv.InitialTargetStmt);
745assert(DeclToLoc.size() <= PrevEnv.DeclToLoc.size());
746assert(ExprToVal.size() <= PrevEnv.ExprToVal.size());
747assert(ExprToLoc.size() <= PrevEnv.ExprToLoc.size());
754 if(DeclToLoc.size() != PrevEnv.DeclToLoc.size() ||
755ExprToLoc.size() != PrevEnv.ExprToLoc.size() ||
756ExprToVal.size() != PrevEnv.ExprToVal.size() ||
757LocToVal.size() != PrevEnv.LocToVal.size())
766assert(EnvA.DACtx == EnvB.DACtx);
767assert(EnvA.LocForRecordReturnVal == EnvB.LocForRecordReturnVal);
768assert(EnvA.ThisPointeeLoc == EnvB.ThisPointeeLoc);
769assert(EnvA.CallStack == EnvB.CallStack);
770assert(EnvA.ResultObjectMap == EnvB.ResultObjectMap);
771assert(EnvA.InitialTargetFunc == EnvB.InitialTargetFunc);
772assert(EnvA.InitialTargetStmt == EnvB.InitialTargetStmt);
776JoinedEnv.CallStack = EnvA.CallStack;
777JoinedEnv.ResultObjectMap = EnvA.ResultObjectMap;
778JoinedEnv.LocForRecordReturnVal = EnvA.LocForRecordReturnVal;
779JoinedEnv.ThisPointeeLoc = EnvA.ThisPointeeLoc;
780JoinedEnv.InitialTargetFunc = EnvA.InitialTargetFunc;
781JoinedEnv.InitialTargetStmt = EnvA.InitialTargetStmt;
785JoinedEnv.ReturnVal =
nullptr;
787JoinedEnv.ReturnVal =
788 joinValues(
Func->getReturnType(), EnvA.ReturnVal, EnvA, EnvB.ReturnVal,
789EnvB, JoinedEnv, Model);
792 if(EnvA.ReturnLoc == EnvB.ReturnLoc)
793JoinedEnv.ReturnLoc = EnvA.ReturnLoc;
795JoinedEnv.ReturnLoc =
nullptr;
802EnvA.FlowConditionToken, EnvB.FlowConditionToken);
805 joinLocToVal(EnvA.LocToVal, EnvB.LocToVal, EnvA, EnvB, JoinedEnv, Model);
808JoinedEnv.ExprToVal =
joinExprMaps(EnvA.ExprToVal, EnvB.ExprToVal);
809JoinedEnv.ExprToLoc =
joinExprMaps(EnvA.ExprToLoc, EnvB.ExprToLoc);
819 if(Val1 ==
nullptr|| Val2 ==
nullptr)
852assert(!DeclToLoc.contains(&
D));
857assert(
D.getType()->isReferenceType() || isa<BindingDecl>(
D) ||
859DeclToLoc[&
D] = &
Loc;
863 autoIt = DeclToLoc.find(&
D);
864 if(It == DeclToLoc.end())
878assert(
E.isGLValue() ||
879 E.getType()->isSpecificBuiltinType(BuiltinType::BuiltinFn));
881assert(!ExprToLoc.contains(&CanonE));
882ExprToLoc[&CanonE] = &
Loc;
887assert(
E.isGLValue() ||
888 E.getType()->isSpecificBuiltinType(BuiltinType::BuiltinFn));
890 returnIt == ExprToLoc.end() ? nullptr : &*It->second;
898assert(ResultObjectMap !=
nullptr);
900assert(
Loc!=
nullptr);
903 if(
Loc==
nullptr)
904 returncast<RecordStorageLocation>(
915llvm::DenseSet<QualType>
Visited;
916 intCreatedValuesCount = 0;
919llvm::errs() <<
"Attempting to initialize a huge value of type: "<<
Type 926assert(!isa<RecordStorageLocation>(
Loc));
927LocToVal[&
Loc] = &Val;
936ExprToVal[&CanonE] = &Val;
941assert(!isa<RecordStorageLocation>(
Loc));
942 returnLocToVal.lookup(&
Loc);
947 if(
Loc==
nullptr)
954assert(!
E.getType()->isRecordType());
956 if(
E.isPRValue()) {
958 returnIt == ExprToVal.end() ? nullptr : It->second;
962 if(It == ExprToLoc.end())
968llvm::DenseSet<QualType>
Visited;
969 intCreatedValuesCount = 0;
973llvm::errs() <<
"Attempting to initialize a huge value of type: "<<
Type 979Value*Environment::createValueUnlessSelfReferential(
981 int&CreatedValuesCount) {
982assert(!
Type.isNull());
992CreatedValuesCount++;
1000CreatedValuesCount++;
1004 if(
Type->isPointerType()) {
1005CreatedValuesCount++;
1006QualType PointeeType =
Type->getPointeeType();
1007StorageLocation &PointeeLoc =
1008createLocAndMaybeValue(PointeeType,
Visited, Depth, CreatedValuesCount);
1010 return&
arena().
create<PointerValue>(PointeeLoc);
1017Environment::createLocAndMaybeValue(QualType Ty,
1018llvm::DenseSet<QualType> &
Visited,
1019 intDepth,
int&CreatedValuesCount) {
1020 if(!
Visited.insert(Ty.getCanonicalType()).second)
1022 autoEraseVisited = llvm::make_scope_exit(
1025Ty = Ty.getNonReferenceType();
1027 if(Ty->isRecordType()) {
1035 if(
Value*Val = createValueUnlessSelfReferential(Ty,
Visited, Depth,
1036CreatedValuesCount))
1044llvm::DenseSet<QualType> &
Visited,
1046 int&CreatedValuesCount) {
1047 auto initField= [&](QualType FieldType, StorageLocation &FieldLoc) {
1048 if(FieldType->isRecordType()) {
1049 auto&FieldRecordLoc = cast<RecordStorageLocation>(FieldLoc);
1051 Visited, Depth + 1, CreatedValuesCount);
1053 if(
getValue(FieldLoc) !=
nullptr)
1055 if(!
Visited.insert(FieldType.getCanonicalType()).second)
1057 if(
Value*Val = createValueUnlessSelfReferential(
1058FieldType,
Visited, Depth + 1, CreatedValuesCount))
1060 Visited.erase(FieldType.getCanonicalType());
1065assert(Field !=
nullptr);
1066QualType FieldType =
Field->getType();
1068 if(FieldType->isReferenceType()) {
1069 Loc.setChild(*Field,
1070&createLocAndMaybeValue(FieldType,
Visited, Depth + 1,
1071CreatedValuesCount));
1073StorageLocation *FieldLoc =
Loc.getChild(*Field);
1074assert(FieldLoc !=
nullptr);
1081assert(!FieldType->isReferenceType());
1082 initField(FieldType,
Loc.getSyntheticField(FieldName));
1086StorageLocation &Environment::createObjectInternal(
constValueDecl *
D,
1088 constExpr *InitExpr) {
1089 if(Ty->isReferenceType()) {
1095 return*InitExprLoc;
1102 returncreateObjectInternal(
D, Ty.getNonReferenceType(),
nullptr);
1105StorageLocation &
Loc=
1108 if(Ty->isRecordType()) {
1113 Value*Val =
nullptr;
1151llvm::DenseMap<const StorageLocation *, std::string> LocToName;
1152 if(LocForRecordReturnVal !=
nullptr)
1153LocToName[LocForRecordReturnVal] =
"(returned record)";
1154 if(ThisPointeeLoc !=
nullptr)
1155LocToName[ThisPointeeLoc] =
"this";
1157OS <<
"DeclToLoc:\n";
1158 for(
auto[
D, L] : DeclToLoc) {
1159 auto Iter= LocToName.insert({L,
D->getNameAsString()}).first;
1160OS <<
" ["<<
Iter->second <<
", "<< L <<
"]\n";
1162OS <<
"ExprToLoc:\n";
1163 for(
auto[
E, L] : ExprToLoc)
1164OS <<
" ["<<
E<<
", "<< L <<
"]\n";
1166OS <<
"ExprToVal:\n";
1167 for(
auto[
E,
V] : ExprToVal)
1168OS <<
" ["<<
E<<
", "<<
V<<
": "<< *
V<<
"]\n";
1170OS <<
"LocToVal:\n";
1171 for(
auto[L,
V] : LocToVal) {
1173 if(
auto Iter= LocToName.find(L);
Iter!= LocToName.end())
1174OS <<
" ("<<
Iter->second <<
")";
1175OS <<
", "<<
V<<
": "<< *
V<<
"]\n";
1179 if(
Func->getReturnType()->isReferenceType()) {
1180OS <<
"ReturnLoc: "<< ReturnLoc;
1181 if(
auto Iter= LocToName.find(ReturnLoc);
Iter!= LocToName.end())
1182OS <<
" ("<<
Iter->second <<
")";
1184}
else if(
Func->getReturnType()->isRecordType() ||
1185isa<CXXConstructorDecl>(
Func)) {
1186OS <<
"LocForRecordReturnVal: "<< LocForRecordReturnVal <<
"\n";
1187}
else if(!
Func->getReturnType()->isVoidType()) {
1188 if(ReturnVal ==
nullptr)
1189OS <<
"ReturnVal: nullptr\n";
1191OS <<
"ReturnVal: "<< *ReturnVal <<
"\n";
1194 if(isa<CXXMethodDecl>(
Func)) {
1195OS <<
"ThisPointeeLoc: "<< ThisPointeeLoc <<
"\n";
1205Environment::PrValueToResultObject Environment::buildResultObjectMap(
1211PrValueToResultObject Map = buildResultObjectMap(
1212DACtx, FuncDecl->
getBody(), ThisPointeeLoc, LocForRecordReturnVal);
1214ResultObjectVisitor Visitor(Map, LocForRecordReturnVal, *DACtx);
1215 if(
const auto*Ctor = dyn_cast<CXXConstructorDecl>(FuncDecl))
1216Visitor.traverseConstructorInits(Ctor, ThisPointeeLoc);
1221Environment::PrValueToResultObject Environment::buildResultObjectMap(
1222DataflowAnalysisContext *DACtx,
Stmt*S,
1223RecordStorageLocation *ThisPointeeLoc,
1224RecordStorageLocation *LocForRecordReturnVal) {
1225PrValueToResultObject Map;
1226ResultObjectVisitor Visitor(Map, LocForRecordReturnVal, *DACtx);
1227Visitor.TraverseStmt(S);
1234 if(ImplicitObject ==
nullptr)
1238 return&cast<RecordStorageLocation>(Val->getPointeeLoc());
1241 returncast_or_null<RecordStorageLocation>(
1248 if(
Base==
nullptr)
1252 return&cast<RecordStorageLocation>(Val->getPointeeLoc());
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
static void initField(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, bool IsActive, bool IsUnionField, bool InUnion, const Descriptor *D, unsigned FieldOffset)
Defines the clang::Expr interface and subclasses for C++ expressions.
llvm::DenseSet< const void * > Visited
static bool RetValue(InterpState &S, CodePtr &Pt)
llvm::MachO::RecordLoc RecordLoc
C Language Family Type Representation.
Represents a call to a C++ constructor.
Represents a call to a member function that may be written either with member call syntax (e....
Expr * getImplicitObjectArgument() const
Retrieve the implicit object argument for the member call.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Decl * getNonClosureAncestor()
Find the nearest non-closure ancestor of this context, i.e.
This represents one expression.
Represents a function declaration or definition.
Stmt * getBody(const FunctionDecl *&Definition) const
Retrieve the body (definition) of the function.
param_iterator param_end()
QualType getReturnType() const
ArrayRef< ParmVarDecl * > parameters() const
param_iterator param_begin()
bool doesThisDeclarationHaveABody() const
Returns whether this specific declaration of the function has a body.
FunctionDecl * getDefinition()
Get the definition for this declaration.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
A (possibly-)qualified type.
Stmt - This represents one statement.
The base class of the type hierarchy.
bool isBooleanType() const
bool isPointerType() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
bool isReferenceType() const
bool isRecordType() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
const Formula & makeAtomRef(Atom A)
Returns a formula for the variable A.
const Formula & makeNot(const Formula &Val)
Returns a formula for the negation of Val.
std::enable_if_t< std::is_base_of< StorageLocation, T >::value, T & > create(Args &&...args)
Creates a T (some subclass of StorageLocation), forwarding args to the constructor,...
Owns objects that encompass the state of a program and stores context that is used during dataflow an...
Atom joinFlowConditions(Atom FirstToken, Atom SecondToken)
Creates a new flow condition that represents the disjunction of the flow conditions identified by Fir...
void addFlowConditionConstraint(Atom Token, const Formula &Constraint)
Adds Constraint to the flow condition identified by Token.
Atom forkFlowCondition(Atom Token)
Creates a new flow condition with the same constraints as the flow condition identified by Token and ...
StorageLocation & getStableStorageLocation(const ValueDecl &D)
Returns a stable storage location for D.
bool flowConditionImplies(Atom Token, const Formula &F)
Returns true if the constraints of the flow condition identified by Token imply that F is true.
bool flowConditionAllows(Atom Token, const Formula &F)
Returns true if the constraints of the flow condition identified by Token still allow F to be true.
PointerValue & getOrCreateNullPointerValue(QualType PointeeType)
Returns a pointer value that represents a null pointer.
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.
LLVM_DUMP_METHOD void dumpFlowCondition(Atom Token, llvm::raw_ostream &OS=llvm::dbgs())
Supplements Environment with non-standard comparison and join operations.
virtual std::optional< WidenResult > widen(QualType Type, Value &Prev, const Environment &PrevEnv, Value &Current, Environment &CurrentEnv)
This function may widen the current value â replace it with an approximation that can reach a fixed p...
virtual void join(QualType Type, const Value &Val1, const Environment &Env1, const Value &Val2, const Environment &Env2, Value &JoinedVal, Environment &JoinedEnv)
Modifies JoinedVal to approximate both Val1 and Val2.
virtual ComparisonResult compare(QualType Type, const Value &Val1, const Environment &Env1, const Value &Val2, const Environment &Env2)
Returns: Same: Val1 is equivalent to Val2, according to the model.
Holds the state of the program (store and heap) at a given program point.
bool allows(const Formula &) const
Returns true if the formula may be true when this point is reached.
LatticeEffect widen(const Environment &PrevEnv, Environment::ValueModel &Model)
Widens the environment point-wise, using PrevEnv as needed to inform the approximation.
PointerValue & getOrCreateNullPointerValue(QualType PointeeType)
Returns a pointer value that represents a null pointer.
RecordStorageLocation * getThisPointeeStorageLocation() const
Returns the storage location assigned to the this pointee in the environment or null if the this poin...
Environment pushCall(const CallExpr *Call) const
Creates and returns an environment to use for an inline analysis of the callee.
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 ...
LLVM_DUMP_METHOD void dump() const
BoolValue & makeTopBoolValue() const
Returns a unique instance of boolean Top.
void initializeFieldsWithValues(RecordStorageLocation &Loc, QualType Type)
Initializes the fields (including synthetic fields) of Loc with values, unless values of the field ty...
StorageLocation & createStorageLocation(QualType Type)
Creates a storage location appropriate for Type.
Environment fork() const
Returns a new environment that is a copy of this one.
void popCall(const CallExpr *Call, const Environment &CalleeEnv)
Moves gathered information back into this from a CalleeEnv created via pushCall.
bool equivalentTo(const Environment &Other, Environment::ValueModel &Model) const
Returns true if and only if the environment is equivalent to Other, i.e the two environments:
BoolValue & makeAtomicBoolValue() const
Returns an atomic boolean value.
bool proves(const Formula &) const
Returns true if the formula is always true when this point is reached.
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...
const FunctionDecl * getCurrentFunc() const
Returns the function currently being analyzed, or null if the code being analyzed isn't part of a fun...
BoolValue & getBoolLiteralValue(bool Value) const
Returns a symbolic boolean value that models a boolean literal equal to Value
StorageLocation & createObject(QualType Ty, const Expr *InitExpr=nullptr)
Creates an object (i.e.
void assume(const Formula &)
Record a fact that must be true if this point in the program is reached.
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 removeDecl(const ValueDecl &D)
Removes the location assigned to D in the environment (if any).
RecordStorageLocation & getResultObjectLocation(const Expr &RecordPRValue) const
Returns the location of the result object for a record-type prvalue.
ExprJoinBehavior
How to treat expression state (ExprToLoc and ExprToVal) in a join.
static Environment join(const Environment &EnvA, const Environment &EnvB, Environment::ValueModel &Model, ExprJoinBehavior ExprBehavior)
Joins two environments by taking the intersection of storage locations and values that are stored in ...
Value * createValue(QualType Type)
Creates a value appropriate for Type, if Type is supported, otherwise returns null.
void setValue(const StorageLocation &Loc, Value &Val)
Assigns Val as the value of Loc in the environment.
void setThisPointeeStorageLocation(RecordStorageLocation &Loc)
Sets the storage location assigned to the this pointee in the environment.
Atom getFlowConditionToken() const
Returns a boolean variable that identifies the flow condition (FC).
bool canDescend(unsigned MaxDepth, const FunctionDecl *Callee) const
Returns whether this Environment can be extended to analyze the given Callee (i.e.
std::enable_if_t< std::is_base_of_v< StorageLocation, T >, T * > get(const ValueDecl &D) const
Returns the result of casting getStorageLocation(...) to a subclass of StorageLocation (using cast_or...
void initialize()
Assigns storage locations and values to all parameters, captures, global variables,...
Models a symbolic pointer. Specifically, any value of type T*.
A storage location for a record (struct, class, or union).
Base class for elements of the local variable store and of the heap.
Base class for all values computed by abstract interpretation.
static bool compareKeyToValueMaps(const llvm::MapVector< Key, Value * > &Map1, const llvm::MapVector< Key, Value * > &Map2, const Environment &Env1, const Environment &Env2, Environment::ValueModel &Model)
static llvm::DenseMap< const ValueDecl *, StorageLocation * > intersectDeclToLoc(const llvm::DenseMap< const ValueDecl *, StorageLocation * > &DeclToLoc1, const llvm::DenseMap< const ValueDecl *, StorageLocation * > &DeclToLoc2)
Returns a map consisting of key-value entries that are present in both maps.
static bool equateUnknownValues(Value::Kind K)
bool areEquivalentValues(const Value &Val1, const Value &Val2)
An equivalence relation for values.
static llvm::MapVector< Key, Value * > widenKeyToValueMap(const llvm::MapVector< Key, Value * > &CurMap, const llvm::MapVector< Key, Value * > &PrevMap, Environment &CurEnv, const Environment &PrevEnv, Environment::ValueModel &Model, LatticeEffect &Effect)
static constexpr int MaxCompositeValueDepth
static constexpr int MaxCompositeValueSize
ReferencedDecls getReferencedDecls(const FunctionDecl &FD)
Returns declarations that are declared in or referenced from FD.
RecordStorageLocation * getImplicitObjectLocation(const CXXMemberCallExpr &MCE, const Environment &Env)
Returns the storage location for the implicit object of a CXXMemberCallExpr, or null if none is defin...
static WidenResult widenDistinctValues(QualType Type, Value &Prev, const Environment &PrevEnv, Value &Current, Environment &CurrentEnv, Environment::ValueModel &Model)
const Expr & ignoreCFGOmittedNodes(const Expr &E)
Skip past nodes that the CFG does not emit.
static llvm::MapVector< const StorageLocation *, Value * > joinLocToVal(const llvm::MapVector< const StorageLocation *, Value * > &LocToVal, const llvm::MapVector< const StorageLocation *, Value * > &LocToVal2, const Environment &Env1, const Environment &Env2, Environment &JoinedEnv, Environment::ValueModel &Model)
static MapT joinExprMaps(const MapT &Map1, const MapT &Map2)
static bool compareDistinctValues(QualType Type, Value &Val1, const Environment &Env1, Value &Val2, const Environment &Env2, Environment::ValueModel &Model)
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...
static Value * joinDistinctValues(QualType Type, Value &Val1, const Environment &Env1, Value &Val2, const Environment &Env2, Environment &JoinedEnv, Environment::ValueModel &Model)
Attempts to join distinct values Val1 and Val2 in Env1 and Env2, respectively, of the same type Type.
LatticeEffect
Effect indicating whether a lattice operation resulted in a new value.
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.
@ Other
Other implicit parameter.
A collection of several types of declarations, all referenced from the same function.
llvm::DenseSet< const VarDecl * > Globals
All variables with static storage duration, notably including static member variables and static vari...
llvm::DenseSet< const FunctionDecl * > Functions
Free functions and member functions which are referenced (but not necessarily called).
FieldSet Fields
Non-static member variables.
The result of a widen operation.
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