10b57cec5SDimitry Andric //===- ExprEngine.cpp - Path-Sensitive Expression-Level Dataflow ----------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric //  This file defines a meta-engine for path-sensitive dataflow analysis that
1081ad6265SDimitry Andric //  is built on CoreEngine, but provides the boilerplate to execute transfer
110b57cec5SDimitry Andric //  functions and build the ExplodedGraph at the expression level.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
160b57cec5SDimitry Andric #include "PrettyStackTraceLocationContext.h"
170b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
180b57cec5SDimitry Andric #include "clang/AST/Decl.h"
190b57cec5SDimitry Andric #include "clang/AST/DeclBase.h"
200b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h"
210b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h"
220b57cec5SDimitry Andric #include "clang/AST/Expr.h"
230b57cec5SDimitry Andric #include "clang/AST/ExprCXX.h"
240b57cec5SDimitry Andric #include "clang/AST/ExprObjC.h"
250b57cec5SDimitry Andric #include "clang/AST/ParentMap.h"
260b57cec5SDimitry Andric #include "clang/AST/PrettyPrinter.h"
270b57cec5SDimitry Andric #include "clang/AST/Stmt.h"
280b57cec5SDimitry Andric #include "clang/AST/StmtCXX.h"
290b57cec5SDimitry Andric #include "clang/AST/StmtObjC.h"
300b57cec5SDimitry Andric #include "clang/AST/Type.h"
310b57cec5SDimitry Andric #include "clang/Analysis/AnalysisDeclContext.h"
320b57cec5SDimitry Andric #include "clang/Analysis/CFG.h"
330b57cec5SDimitry Andric #include "clang/Analysis/ConstructionContext.h"
340b57cec5SDimitry Andric #include "clang/Analysis/ProgramPoint.h"
350b57cec5SDimitry Andric #include "clang/Basic/IdentifierTable.h"
360b57cec5SDimitry Andric #include "clang/Basic/JsonSupport.h"
370b57cec5SDimitry Andric #include "clang/Basic/LLVM.h"
380b57cec5SDimitry Andric #include "clang/Basic/LangOptions.h"
390b57cec5SDimitry Andric #include "clang/Basic/PrettyStackTrace.h"
400b57cec5SDimitry Andric #include "clang/Basic/SourceLocation.h"
410b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h"
420b57cec5SDimitry Andric #include "clang/Basic/Specifiers.h"
430b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
440b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
450b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
460b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/CheckerManager.h"
470b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
480b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
490b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h"
500b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
51bdd1243dSDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
520b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
530b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/LoopUnrolling.h"
540b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h"
550b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
560b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
570b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
580b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
590b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
600b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
610b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
620b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
630b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
640b57cec5SDimitry Andric #include "llvm/ADT/APSInt.h"
650b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
660b57cec5SDimitry Andric #include "llvm/ADT/ImmutableMap.h"
670b57cec5SDimitry Andric #include "llvm/ADT/ImmutableSet.h"
6806c3fb27SDimitry Andric #include "llvm/ADT/STLExtras.h"
690b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
700b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
710b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
720b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
730b57cec5SDimitry Andric #include "llvm/Support/DOTGraphTraits.h"
740b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
750b57cec5SDimitry Andric #include "llvm/Support/GraphWriter.h"
760b57cec5SDimitry Andric #include "llvm/Support/SaveAndRestore.h"
770b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
780b57cec5SDimitry Andric #include <cassert>
790b57cec5SDimitry Andric #include <cstdint>
800b57cec5SDimitry Andric #include <memory>
81bdd1243dSDimitry Andric #include <optional>
820b57cec5SDimitry Andric #include <string>
830b57cec5SDimitry Andric #include <tuple>
840b57cec5SDimitry Andric #include <utility>
850b57cec5SDimitry Andric #include <vector>
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric using namespace clang;
880b57cec5SDimitry Andric using namespace ento;
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric #define DEBUG_TYPE "ExprEngine"
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric STATISTIC(NumRemoveDeadBindings,
930b57cec5SDimitry Andric             "The # of times RemoveDeadBindings is called");
940b57cec5SDimitry Andric STATISTIC(NumMaxBlockCountReached,
950b57cec5SDimitry Andric             "The # of aborted paths due to reaching the maximum block count in "
960b57cec5SDimitry Andric             "a top level function");
970b57cec5SDimitry Andric STATISTIC(NumMaxBlockCountReachedInInlined,
980b57cec5SDimitry Andric             "The # of aborted paths due to reaching the maximum block count in "
990b57cec5SDimitry Andric             "an inlined function");
1000b57cec5SDimitry Andric STATISTIC(NumTimesRetriedWithoutInlining,
1010b57cec5SDimitry Andric             "The # of times we re-evaluated a call without inlining");
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1040b57cec5SDimitry Andric // Internal program state traits.
1050b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric namespace {
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric // When modeling a C++ constructor, for a variety of reasons we need to track
1100b57cec5SDimitry Andric // the location of the object for the duration of its ConstructionContext.
1110b57cec5SDimitry Andric // ObjectsUnderConstruction maps statements within the construction context
1120b57cec5SDimitry Andric // to the object's location, so that on every such statement the location
1130b57cec5SDimitry Andric // could have been retrieved.
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric /// ConstructedObjectKey is used for being able to find the path-sensitive
1160b57cec5SDimitry Andric /// memory region of a freshly constructed object while modeling the AST node
1170b57cec5SDimitry Andric /// that syntactically represents the object that is being constructed.
1180b57cec5SDimitry Andric /// Semantics of such nodes may sometimes require access to the region that's
1190b57cec5SDimitry Andric /// not otherwise present in the program state, or to the very fact that
1200b57cec5SDimitry Andric /// the construction context was present and contained references to these
1210b57cec5SDimitry Andric /// AST nodes.
1220b57cec5SDimitry Andric class ConstructedObjectKey {
12381ad6265SDimitry Andric   using ConstructedObjectKeyImpl =
12481ad6265SDimitry Andric       std::pair<ConstructionContextItem, const LocationContext *>;
1250b57cec5SDimitry Andric   const ConstructedObjectKeyImpl Impl;
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric public:
ConstructedObjectKey(const ConstructionContextItem & Item,const LocationContext * LC)1280b57cec5SDimitry Andric   explicit ConstructedObjectKey(const ConstructionContextItem &Item,
1290b57cec5SDimitry Andric                        const LocationContext *LC)
1300b57cec5SDimitry Andric       : Impl(Item, LC) {}
1310b57cec5SDimitry Andric 
getItem() const1320b57cec5SDimitry Andric   const ConstructionContextItem &getItem() const { return Impl.first; }
getLocationContext() const1330b57cec5SDimitry Andric   const LocationContext *getLocationContext() const { return Impl.second; }
1340b57cec5SDimitry Andric 
getASTContext() const1350b57cec5SDimitry Andric   ASTContext &getASTContext() const {
1360b57cec5SDimitry Andric     return getLocationContext()->getDecl()->getASTContext();
1370b57cec5SDimitry Andric   }
1380b57cec5SDimitry Andric 
printJson(llvm::raw_ostream & Out,PrinterHelper * Helper,PrintingPolicy & PP) const1390b57cec5SDimitry Andric   void printJson(llvm::raw_ostream &Out, PrinterHelper *Helper,
1400b57cec5SDimitry Andric                  PrintingPolicy &PP) const {
1410b57cec5SDimitry Andric     const Stmt *S = getItem().getStmtOrNull();
1420b57cec5SDimitry Andric     const CXXCtorInitializer *I = nullptr;
1430b57cec5SDimitry Andric     if (!S)
1440b57cec5SDimitry Andric       I = getItem().getCXXCtorInitializer();
1450b57cec5SDimitry Andric 
1460b57cec5SDimitry Andric     if (S)
1470b57cec5SDimitry Andric       Out << "\"stmt_id\": " << S->getID(getASTContext());
1480b57cec5SDimitry Andric     else
1490b57cec5SDimitry Andric       Out << "\"init_id\": " << I->getID(getASTContext());
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric     // Kind
1520b57cec5SDimitry Andric     Out << ", \"kind\": \"" << getItem().getKindAsString()
1530b57cec5SDimitry Andric         << "\", \"argument_index\": ";
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric     if (getItem().getKind() == ConstructionContextItem::ArgumentKind)
1560b57cec5SDimitry Andric       Out << getItem().getIndex();
1570b57cec5SDimitry Andric     else
1580b57cec5SDimitry Andric       Out << "null";
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric     // Pretty-print
1610b57cec5SDimitry Andric     Out << ", \"pretty\": ";
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric     if (S) {
1640b57cec5SDimitry Andric       S->printJson(Out, Helper, PP, /*AddQuotes=*/true);
1650b57cec5SDimitry Andric     } else {
166e8d8bef9SDimitry Andric       Out << '\"' << I->getAnyMember()->getDeclName() << '\"';
1670b57cec5SDimitry Andric     }
1680b57cec5SDimitry Andric   }
1690b57cec5SDimitry Andric 
Profile(llvm::FoldingSetNodeID & ID) const1700b57cec5SDimitry Andric   void Profile(llvm::FoldingSetNodeID &ID) const {
1710b57cec5SDimitry Andric     ID.Add(Impl.first);
1720b57cec5SDimitry Andric     ID.AddPointer(Impl.second);
1730b57cec5SDimitry Andric   }
1740b57cec5SDimitry Andric 
operator ==(const ConstructedObjectKey & RHS) const1750b57cec5SDimitry Andric   bool operator==(const ConstructedObjectKey &RHS) const {
1760b57cec5SDimitry Andric     return Impl == RHS.Impl;
1770b57cec5SDimitry Andric   }
1780b57cec5SDimitry Andric 
operator <(const ConstructedObjectKey & RHS) const1790b57cec5SDimitry Andric   bool operator<(const ConstructedObjectKey &RHS) const {
1800b57cec5SDimitry Andric     return Impl < RHS.Impl;
1810b57cec5SDimitry Andric   }
1820b57cec5SDimitry Andric };
1830b57cec5SDimitry Andric } // namespace
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric typedef llvm::ImmutableMap<ConstructedObjectKey, SVal>
1860b57cec5SDimitry Andric     ObjectsUnderConstructionMap;
1870b57cec5SDimitry Andric REGISTER_TRAIT_WITH_PROGRAMSTATE(ObjectsUnderConstruction,
1880b57cec5SDimitry Andric                                  ObjectsUnderConstructionMap)
1890b57cec5SDimitry Andric 
190fcaf7f86SDimitry Andric // This trait is responsible for storing the index of the element that is to be
191fcaf7f86SDimitry Andric // constructed in the next iteration. As a result a CXXConstructExpr is only
192bdd1243dSDimitry Andric // stored if it is array type. Also the index is the index of the continuous
193fcaf7f86SDimitry Andric // memory region, which is important for multi-dimensional arrays. E.g:: int
194fcaf7f86SDimitry Andric // arr[2][2]; assume arr[1][1] will be the next element under construction, so
195fcaf7f86SDimitry Andric // the index is 3.
196fcaf7f86SDimitry Andric typedef llvm::ImmutableMap<
197fcaf7f86SDimitry Andric     std::pair<const CXXConstructExpr *, const LocationContext *>, unsigned>
198fcaf7f86SDimitry Andric     IndexOfElementToConstructMap;
199fcaf7f86SDimitry Andric REGISTER_TRAIT_WITH_PROGRAMSTATE(IndexOfElementToConstruct,
200fcaf7f86SDimitry Andric                                  IndexOfElementToConstructMap)
201972a253aSDimitry Andric 
202972a253aSDimitry Andric // This trait is responsible for holding our pending ArrayInitLoopExprs.
203972a253aSDimitry Andric // It pairs the LocationContext and the initializer CXXConstructExpr with
204972a253aSDimitry Andric // the size of the array that's being copy initialized.
205972a253aSDimitry Andric typedef llvm::ImmutableMap<
206972a253aSDimitry Andric     std::pair<const CXXConstructExpr *, const LocationContext *>, unsigned>
207972a253aSDimitry Andric     PendingInitLoopMap;
208972a253aSDimitry Andric REGISTER_TRAIT_WITH_PROGRAMSTATE(PendingInitLoop, PendingInitLoopMap)
209bdd1243dSDimitry Andric 
210bdd1243dSDimitry Andric typedef llvm::ImmutableMap<const LocationContext *, unsigned>
211bdd1243dSDimitry Andric     PendingArrayDestructionMap;
212bdd1243dSDimitry Andric REGISTER_TRAIT_WITH_PROGRAMSTATE(PendingArrayDestruction,
213bdd1243dSDimitry Andric                                  PendingArrayDestructionMap)
214bdd1243dSDimitry Andric 
2150b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
2160b57cec5SDimitry Andric // Engine construction and deletion.
2170b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric static const char* TagProviderName = "ExprEngine";
2200b57cec5SDimitry Andric 
ExprEngine(cross_tu::CrossTranslationUnitContext & CTU,AnalysisManager & mgr,SetOfConstDecls * VisitedCalleesIn,FunctionSummariesTy * FS,InliningModes HowToInlineIn)2210b57cec5SDimitry Andric ExprEngine::ExprEngine(cross_tu::CrossTranslationUnitContext &CTU,
22281ad6265SDimitry Andric                        AnalysisManager &mgr, SetOfConstDecls *VisitedCalleesIn,
22381ad6265SDimitry Andric                        FunctionSummariesTy *FS, InliningModes HowToInlineIn)
22481ad6265SDimitry Andric     : CTU(CTU), IsCTUEnabled(mgr.getAnalyzerOptions().IsNaiveCTUEnabled),
22581ad6265SDimitry Andric       AMgr(mgr), AnalysisDeclContexts(mgr.getAnalysisDeclContextManager()),
2260b57cec5SDimitry Andric       Engine(*this, FS, mgr.getAnalyzerOptions()), G(Engine.getGraph()),
2270b57cec5SDimitry Andric       StateMgr(getContext(), mgr.getStoreManagerCreator(),
22881ad6265SDimitry Andric                mgr.getConstraintManagerCreator(), G.getAllocator(), this),
22981ad6265SDimitry Andric       SymMgr(StateMgr.getSymbolManager()), MRMgr(StateMgr.getRegionManager()),
23081ad6265SDimitry Andric       svalBuilder(StateMgr.getSValBuilder()), ObjCNoRet(mgr.getASTContext()),
23181ad6265SDimitry Andric       BR(mgr, *this), VisitedCallees(VisitedCalleesIn),
23281ad6265SDimitry Andric       HowToInline(HowToInlineIn) {
2330b57cec5SDimitry Andric   unsigned TrimInterval = mgr.options.GraphTrimInterval;
2340b57cec5SDimitry Andric   if (TrimInterval != 0) {
2350b57cec5SDimitry Andric     // Enable eager node reclamation when constructing the ExplodedGraph.
2360b57cec5SDimitry Andric     G.enableNodeReclamation(TrimInterval);
2370b57cec5SDimitry Andric   }
2380b57cec5SDimitry Andric }
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
2410b57cec5SDimitry Andric // Utility methods.
2420b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
2430b57cec5SDimitry Andric 
getInitialState(const LocationContext * InitLoc)2440b57cec5SDimitry Andric ProgramStateRef ExprEngine::getInitialState(const LocationContext *InitLoc) {
2450b57cec5SDimitry Andric   ProgramStateRef state = StateMgr.getInitialState(InitLoc);
2460b57cec5SDimitry Andric   const Decl *D = InitLoc->getDecl();
2470b57cec5SDimitry Andric 
2480b57cec5SDimitry Andric   // Preconditions.
2490b57cec5SDimitry Andric   // FIXME: It would be nice if we had a more general mechanism to add
2500b57cec5SDimitry Andric   // such preconditions.  Some day.
2510b57cec5SDimitry Andric   do {
2520b57cec5SDimitry Andric     if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
2530b57cec5SDimitry Andric       // Precondition: the first argument of 'main' is an integer guaranteed
2540b57cec5SDimitry Andric       //  to be > 0.
2550b57cec5SDimitry Andric       const IdentifierInfo *II = FD->getIdentifier();
2560b57cec5SDimitry Andric       if (!II || !(II->getName() == "main" && FD->getNumParams() > 0))
2570b57cec5SDimitry Andric         break;
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric       const ParmVarDecl *PD = FD->getParamDecl(0);
2600b57cec5SDimitry Andric       QualType T = PD->getType();
2610b57cec5SDimitry Andric       const auto *BT = dyn_cast<BuiltinType>(T);
2620b57cec5SDimitry Andric       if (!BT || !BT->isInteger())
2630b57cec5SDimitry Andric         break;
2640b57cec5SDimitry Andric 
2650b57cec5SDimitry Andric       const MemRegion *R = state->getRegion(PD, InitLoc);
2660b57cec5SDimitry Andric       if (!R)
2670b57cec5SDimitry Andric         break;
2680b57cec5SDimitry Andric 
2690b57cec5SDimitry Andric       SVal V = state->getSVal(loc::MemRegionVal(R));
2700b57cec5SDimitry Andric       SVal Constraint_untested = evalBinOp(state, BO_GT, V,
2710b57cec5SDimitry Andric                                            svalBuilder.makeZeroVal(T),
2720b57cec5SDimitry Andric                                            svalBuilder.getConditionType());
2730b57cec5SDimitry Andric 
274bdd1243dSDimitry Andric       std::optional<DefinedOrUnknownSVal> Constraint =
2750b57cec5SDimitry Andric           Constraint_untested.getAs<DefinedOrUnknownSVal>();
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric       if (!Constraint)
2780b57cec5SDimitry Andric         break;
2790b57cec5SDimitry Andric 
2800b57cec5SDimitry Andric       if (ProgramStateRef newState = state->assume(*Constraint, true))
2810b57cec5SDimitry Andric         state = newState;
2820b57cec5SDimitry Andric     }
2830b57cec5SDimitry Andric     break;
2840b57cec5SDimitry Andric   }
2850b57cec5SDimitry Andric   while (false);
2860b57cec5SDimitry Andric 
2870b57cec5SDimitry Andric   if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
2880b57cec5SDimitry Andric     // Precondition: 'self' is always non-null upon entry to an Objective-C
2890b57cec5SDimitry Andric     // method.
2900b57cec5SDimitry Andric     const ImplicitParamDecl *SelfD = MD->getSelfDecl();
2910b57cec5SDimitry Andric     const MemRegion *R = state->getRegion(SelfD, InitLoc);
2920b57cec5SDimitry Andric     SVal V = state->getSVal(loc::MemRegionVal(R));
2930b57cec5SDimitry Andric 
294bdd1243dSDimitry Andric     if (std::optional<Loc> LV = V.getAs<Loc>()) {
2950b57cec5SDimitry Andric       // Assume that the pointer value in 'self' is non-null.
2960b57cec5SDimitry Andric       state = state->assume(*LV, true);
2970b57cec5SDimitry Andric       assert(state && "'self' cannot be null");
2980b57cec5SDimitry Andric     }
2990b57cec5SDimitry Andric   }
3000b57cec5SDimitry Andric 
3010b57cec5SDimitry Andric   if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
3025f757f3fSDimitry Andric     if (MD->isImplicitObjectMemberFunction()) {
3030b57cec5SDimitry Andric       // Precondition: 'this' is always non-null upon entry to the
3040b57cec5SDimitry Andric       // top-level function.  This is our starting assumption for
3050b57cec5SDimitry Andric       // analyzing an "open" program.
3060b57cec5SDimitry Andric       const StackFrameContext *SFC = InitLoc->getStackFrame();
3070b57cec5SDimitry Andric       if (SFC->getParent() == nullptr) {
3080b57cec5SDimitry Andric         loc::MemRegionVal L = svalBuilder.getCXXThis(MD, SFC);
3090b57cec5SDimitry Andric         SVal V = state->getSVal(L);
310bdd1243dSDimitry Andric         if (std::optional<Loc> LV = V.getAs<Loc>()) {
3110b57cec5SDimitry Andric           state = state->assume(*LV, true);
3120b57cec5SDimitry Andric           assert(state && "'this' cannot be null");
3130b57cec5SDimitry Andric         }
3140b57cec5SDimitry Andric       }
3150b57cec5SDimitry Andric     }
3160b57cec5SDimitry Andric   }
3170b57cec5SDimitry Andric 
3180b57cec5SDimitry Andric   return state;
3190b57cec5SDimitry Andric }
3200b57cec5SDimitry Andric 
createTemporaryRegionIfNeeded(ProgramStateRef State,const LocationContext * LC,const Expr * InitWithAdjustments,const Expr * Result,const SubRegion ** OutRegionWithAdjustments)3210b57cec5SDimitry Andric ProgramStateRef ExprEngine::createTemporaryRegionIfNeeded(
3220b57cec5SDimitry Andric     ProgramStateRef State, const LocationContext *LC,
3230b57cec5SDimitry Andric     const Expr *InitWithAdjustments, const Expr *Result,
3240b57cec5SDimitry Andric     const SubRegion **OutRegionWithAdjustments) {
3250b57cec5SDimitry Andric   // FIXME: This function is a hack that works around the quirky AST
3260b57cec5SDimitry Andric   // we're often having with respect to C++ temporaries. If only we modelled
3270b57cec5SDimitry Andric   // the actual execution order of statements properly in the CFG,
3280b57cec5SDimitry Andric   // all the hassle with adjustments would not be necessary,
3290b57cec5SDimitry Andric   // and perhaps the whole function would be removed.
3300b57cec5SDimitry Andric   SVal InitValWithAdjustments = State->getSVal(InitWithAdjustments, LC);
3310b57cec5SDimitry Andric   if (!Result) {
3320b57cec5SDimitry Andric     // If we don't have an explicit result expression, we're in "if needed"
3330b57cec5SDimitry Andric     // mode. Only create a region if the current value is a NonLoc.
33481ad6265SDimitry Andric     if (!isa<NonLoc>(InitValWithAdjustments)) {
3350b57cec5SDimitry Andric       if (OutRegionWithAdjustments)
3360b57cec5SDimitry Andric         *OutRegionWithAdjustments = nullptr;
3370b57cec5SDimitry Andric       return State;
3380b57cec5SDimitry Andric     }
3390b57cec5SDimitry Andric     Result = InitWithAdjustments;
3400b57cec5SDimitry Andric   } else {
3415e801ac6SDimitry Andric     // We need to create a region no matter what. Make sure we don't try to
3425e801ac6SDimitry Andric     // stuff a Loc into a non-pointer temporary region.
34381ad6265SDimitry Andric     assert(!isa<Loc>(InitValWithAdjustments) ||
3440b57cec5SDimitry Andric            Loc::isLocType(Result->getType()) ||
3450b57cec5SDimitry Andric            Result->getType()->isMemberPointerType());
3460b57cec5SDimitry Andric   }
3470b57cec5SDimitry Andric 
3480b57cec5SDimitry Andric   ProgramStateManager &StateMgr = State->getStateManager();
3490b57cec5SDimitry Andric   MemRegionManager &MRMgr = StateMgr.getRegionManager();
3500b57cec5SDimitry Andric   StoreManager &StoreMgr = StateMgr.getStoreManager();
3510b57cec5SDimitry Andric 
3520b57cec5SDimitry Andric   // MaterializeTemporaryExpr may appear out of place, after a few field and
3530b57cec5SDimitry Andric   // base-class accesses have been made to the object, even though semantically
3540b57cec5SDimitry Andric   // it is the whole object that gets materialized and lifetime-extended.
3550b57cec5SDimitry Andric   //
3560b57cec5SDimitry Andric   // For example:
3570b57cec5SDimitry Andric   //
3580b57cec5SDimitry Andric   //   `-MaterializeTemporaryExpr
3590b57cec5SDimitry Andric   //     `-MemberExpr
3600b57cec5SDimitry Andric   //       `-CXXTemporaryObjectExpr
3610b57cec5SDimitry Andric   //
3620b57cec5SDimitry Andric   // instead of the more natural
3630b57cec5SDimitry Andric   //
3640b57cec5SDimitry Andric   //   `-MemberExpr
3650b57cec5SDimitry Andric   //     `-MaterializeTemporaryExpr
3660b57cec5SDimitry Andric   //       `-CXXTemporaryObjectExpr
3670b57cec5SDimitry Andric   //
3680b57cec5SDimitry Andric   // Use the usual methods for obtaining the expression of the base object,
3690b57cec5SDimitry Andric   // and record the adjustments that we need to make to obtain the sub-object
3700b57cec5SDimitry Andric   // that the whole expression 'Ex' refers to. This trick is usual,
3710b57cec5SDimitry Andric   // in the sense that CodeGen takes a similar route.
3720b57cec5SDimitry Andric 
3730b57cec5SDimitry Andric   SmallVector<const Expr *, 2> CommaLHSs;
3740b57cec5SDimitry Andric   SmallVector<SubobjectAdjustment, 2> Adjustments;
3750b57cec5SDimitry Andric 
3760b57cec5SDimitry Andric   const Expr *Init = InitWithAdjustments->skipRValueSubobjectAdjustments(
3770b57cec5SDimitry Andric       CommaLHSs, Adjustments);
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric   // Take the region for Init, i.e. for the whole object. If we do not remember
3800b57cec5SDimitry Andric   // the region in which the object originally was constructed, come up with
3810b57cec5SDimitry Andric   // a new temporary region out of thin air and copy the contents of the object
3820b57cec5SDimitry Andric   // (which are currently present in the Environment, because Init is an rvalue)
3830b57cec5SDimitry Andric   // into that region. This is not correct, but it is better than nothing.
3840b57cec5SDimitry Andric   const TypedValueRegion *TR = nullptr;
3850b57cec5SDimitry Andric   if (const auto *MT = dyn_cast<MaterializeTemporaryExpr>(Result)) {
386bdd1243dSDimitry Andric     if (std::optional<SVal> V = getObjectUnderConstruction(State, MT, LC)) {
3870b57cec5SDimitry Andric       State = finishObjectConstruction(State, MT, LC);
3880b57cec5SDimitry Andric       State = State->BindExpr(Result, LC, *V);
3890b57cec5SDimitry Andric       return State;
39006c3fb27SDimitry Andric     } else if (const ValueDecl *VD = MT->getExtendingDecl()) {
3910b57cec5SDimitry Andric       StorageDuration SD = MT->getStorageDuration();
39206c3fb27SDimitry Andric       assert(SD != SD_FullExpression);
3930b57cec5SDimitry Andric       // If this object is bound to a reference with static storage duration, we
3940b57cec5SDimitry Andric       // put it in a different region to prevent "address leakage" warnings.
3950b57cec5SDimitry Andric       if (SD == SD_Static || SD == SD_Thread) {
39606c3fb27SDimitry Andric         TR = MRMgr.getCXXStaticLifetimeExtendedObjectRegion(Init, VD);
3970b57cec5SDimitry Andric       } else {
39806c3fb27SDimitry Andric         TR = MRMgr.getCXXLifetimeExtendedObjectRegion(Init, VD, LC);
3990b57cec5SDimitry Andric       }
40006c3fb27SDimitry Andric     } else {
40106c3fb27SDimitry Andric       assert(MT->getStorageDuration() == SD_FullExpression);
40206c3fb27SDimitry Andric       TR = MRMgr.getCXXTempObjectRegion(Init, LC);
4030b57cec5SDimitry Andric     }
4040b57cec5SDimitry Andric   } else {
4050b57cec5SDimitry Andric     TR = MRMgr.getCXXTempObjectRegion(Init, LC);
4060b57cec5SDimitry Andric   }
4070b57cec5SDimitry Andric 
4080b57cec5SDimitry Andric   SVal Reg = loc::MemRegionVal(TR);
4090b57cec5SDimitry Andric   SVal BaseReg = Reg;
4100b57cec5SDimitry Andric 
4110b57cec5SDimitry Andric   // Make the necessary adjustments to obtain the sub-object.
412349cc55cSDimitry Andric   for (const SubobjectAdjustment &Adj : llvm::reverse(Adjustments)) {
4130b57cec5SDimitry Andric     switch (Adj.Kind) {
4140b57cec5SDimitry Andric     case SubobjectAdjustment::DerivedToBaseAdjustment:
4150b57cec5SDimitry Andric       Reg = StoreMgr.evalDerivedToBase(Reg, Adj.DerivedToBase.BasePath);
4160b57cec5SDimitry Andric       break;
4170b57cec5SDimitry Andric     case SubobjectAdjustment::FieldAdjustment:
4180b57cec5SDimitry Andric       Reg = StoreMgr.getLValueField(Adj.Field, Reg);
4190b57cec5SDimitry Andric       break;
4200b57cec5SDimitry Andric     case SubobjectAdjustment::MemberPointerAdjustment:
4210b57cec5SDimitry Andric       // FIXME: Unimplemented.
4220b57cec5SDimitry Andric       State = State->invalidateRegions(Reg, InitWithAdjustments,
4230b57cec5SDimitry Andric                                        currBldrCtx->blockCount(), LC, true,
4240b57cec5SDimitry Andric                                        nullptr, nullptr, nullptr);
4250b57cec5SDimitry Andric       return State;
4260b57cec5SDimitry Andric     }
4270b57cec5SDimitry Andric   }
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric   // What remains is to copy the value of the object to the new region.
4300b57cec5SDimitry Andric   // FIXME: In other words, what we should always do is copy value of the
4310b57cec5SDimitry Andric   // Init expression (which corresponds to the bigger object) to the whole
4320b57cec5SDimitry Andric   // temporary region TR. However, this value is often no longer present
4330b57cec5SDimitry Andric   // in the Environment. If it has disappeared, we instead invalidate TR.
4340b57cec5SDimitry Andric   // Still, what we can do is assign the value of expression Ex (which
4350b57cec5SDimitry Andric   // corresponds to the sub-object) to the TR's sub-region Reg. At least,
4360b57cec5SDimitry Andric   // values inside Reg would be correct.
4370b57cec5SDimitry Andric   SVal InitVal = State->getSVal(Init, LC);
4380b57cec5SDimitry Andric   if (InitVal.isUnknown()) {
4390b57cec5SDimitry Andric     InitVal = getSValBuilder().conjureSymbolVal(Result, LC, Init->getType(),
4400b57cec5SDimitry Andric                                                 currBldrCtx->blockCount());
4410b57cec5SDimitry Andric     State = State->bindLoc(BaseReg.castAs<Loc>(), InitVal, LC, false);
4420b57cec5SDimitry Andric 
4430b57cec5SDimitry Andric     // Then we'd need to take the value that certainly exists and bind it
4440b57cec5SDimitry Andric     // over.
4450b57cec5SDimitry Andric     if (InitValWithAdjustments.isUnknown()) {
4460b57cec5SDimitry Andric       // Try to recover some path sensitivity in case we couldn't
4470b57cec5SDimitry Andric       // compute the value.
4480b57cec5SDimitry Andric       InitValWithAdjustments = getSValBuilder().conjureSymbolVal(
4490b57cec5SDimitry Andric           Result, LC, InitWithAdjustments->getType(),
4500b57cec5SDimitry Andric           currBldrCtx->blockCount());
4510b57cec5SDimitry Andric     }
4520b57cec5SDimitry Andric     State =
4530b57cec5SDimitry Andric         State->bindLoc(Reg.castAs<Loc>(), InitValWithAdjustments, LC, false);
4540b57cec5SDimitry Andric   } else {
4550b57cec5SDimitry Andric     State = State->bindLoc(BaseReg.castAs<Loc>(), InitVal, LC, false);
4560b57cec5SDimitry Andric   }
4570b57cec5SDimitry Andric 
4580b57cec5SDimitry Andric   // The result expression would now point to the correct sub-region of the
4590b57cec5SDimitry Andric   // newly created temporary region. Do this last in order to getSVal of Init
4600b57cec5SDimitry Andric   // correctly in case (Result == Init).
4610b57cec5SDimitry Andric   if (Result->isGLValue()) {
4620b57cec5SDimitry Andric     State = State->BindExpr(Result, LC, Reg);
4630b57cec5SDimitry Andric   } else {
4640b57cec5SDimitry Andric     State = State->BindExpr(Result, LC, InitValWithAdjustments);
4650b57cec5SDimitry Andric   }
4660b57cec5SDimitry Andric 
4670b57cec5SDimitry Andric   // Notify checkers once for two bindLoc()s.
4680b57cec5SDimitry Andric   State = processRegionChange(State, TR, LC);
4690b57cec5SDimitry Andric 
4700b57cec5SDimitry Andric   if (OutRegionWithAdjustments)
4710b57cec5SDimitry Andric     *OutRegionWithAdjustments = cast<SubRegion>(Reg.getAsRegion());
4720b57cec5SDimitry Andric   return State;
4730b57cec5SDimitry Andric }
4740b57cec5SDimitry Andric 
setIndexOfElementToConstruct(ProgramStateRef State,const CXXConstructExpr * E,const LocationContext * LCtx,unsigned Idx)475fcaf7f86SDimitry Andric ProgramStateRef ExprEngine::setIndexOfElementToConstruct(
476fcaf7f86SDimitry Andric     ProgramStateRef State, const CXXConstructExpr *E,
477fcaf7f86SDimitry Andric     const LocationContext *LCtx, unsigned Idx) {
478fcaf7f86SDimitry Andric   auto Key = std::make_pair(E, LCtx->getStackFrame());
479fcaf7f86SDimitry Andric 
480fcaf7f86SDimitry Andric   assert(!State->contains<IndexOfElementToConstruct>(Key) || Idx > 0);
481fcaf7f86SDimitry Andric 
482fcaf7f86SDimitry Andric   return State->set<IndexOfElementToConstruct>(Key, Idx);
483fcaf7f86SDimitry Andric }
484fcaf7f86SDimitry Andric 
485bdd1243dSDimitry Andric std::optional<unsigned>
getPendingInitLoop(ProgramStateRef State,const CXXConstructExpr * E,const LocationContext * LCtx)486bdd1243dSDimitry Andric ExprEngine::getPendingInitLoop(ProgramStateRef State, const CXXConstructExpr *E,
487972a253aSDimitry Andric                                const LocationContext *LCtx) {
488bdd1243dSDimitry Andric   const unsigned *V = State->get<PendingInitLoop>({E, LCtx->getStackFrame()});
489bdd1243dSDimitry Andric   return V ? std::make_optional(*V) : std::nullopt;
490972a253aSDimitry Andric }
491972a253aSDimitry Andric 
removePendingInitLoop(ProgramStateRef State,const CXXConstructExpr * E,const LocationContext * LCtx)492972a253aSDimitry Andric ProgramStateRef ExprEngine::removePendingInitLoop(ProgramStateRef State,
493972a253aSDimitry Andric                                                   const CXXConstructExpr *E,
494972a253aSDimitry Andric                                                   const LocationContext *LCtx) {
495972a253aSDimitry Andric   auto Key = std::make_pair(E, LCtx->getStackFrame());
496972a253aSDimitry Andric 
497972a253aSDimitry Andric   assert(E && State->contains<PendingInitLoop>(Key));
498972a253aSDimitry Andric   return State->remove<PendingInitLoop>(Key);
499972a253aSDimitry Andric }
500972a253aSDimitry Andric 
setPendingInitLoop(ProgramStateRef State,const CXXConstructExpr * E,const LocationContext * LCtx,unsigned Size)501972a253aSDimitry Andric ProgramStateRef ExprEngine::setPendingInitLoop(ProgramStateRef State,
502972a253aSDimitry Andric                                                const CXXConstructExpr *E,
503972a253aSDimitry Andric                                                const LocationContext *LCtx,
504972a253aSDimitry Andric                                                unsigned Size) {
505972a253aSDimitry Andric   auto Key = std::make_pair(E, LCtx->getStackFrame());
506972a253aSDimitry Andric 
507972a253aSDimitry Andric   assert(!State->contains<PendingInitLoop>(Key) && Size > 0);
508972a253aSDimitry Andric 
509972a253aSDimitry Andric   return State->set<PendingInitLoop>(Key, Size);
510972a253aSDimitry Andric }
511972a253aSDimitry Andric 
512bdd1243dSDimitry Andric std::optional<unsigned>
getIndexOfElementToConstruct(ProgramStateRef State,const CXXConstructExpr * E,const LocationContext * LCtx)513fcaf7f86SDimitry Andric ExprEngine::getIndexOfElementToConstruct(ProgramStateRef State,
514fcaf7f86SDimitry Andric                                          const CXXConstructExpr *E,
515fcaf7f86SDimitry Andric                                          const LocationContext *LCtx) {
516bdd1243dSDimitry Andric   const unsigned *V =
517bdd1243dSDimitry Andric       State->get<IndexOfElementToConstruct>({E, LCtx->getStackFrame()});
518bdd1243dSDimitry Andric   return V ? std::make_optional(*V) : std::nullopt;
519fcaf7f86SDimitry Andric }
520fcaf7f86SDimitry Andric 
521fcaf7f86SDimitry Andric ProgramStateRef
removeIndexOfElementToConstruct(ProgramStateRef State,const CXXConstructExpr * E,const LocationContext * LCtx)522fcaf7f86SDimitry Andric ExprEngine::removeIndexOfElementToConstruct(ProgramStateRef State,
523fcaf7f86SDimitry Andric                                             const CXXConstructExpr *E,
524fcaf7f86SDimitry Andric                                             const LocationContext *LCtx) {
525fcaf7f86SDimitry Andric   auto Key = std::make_pair(E, LCtx->getStackFrame());
526fcaf7f86SDimitry Andric 
527fcaf7f86SDimitry Andric   assert(E && State->contains<IndexOfElementToConstruct>(Key));
528fcaf7f86SDimitry Andric   return State->remove<IndexOfElementToConstruct>(Key);
529fcaf7f86SDimitry Andric }
530fcaf7f86SDimitry Andric 
531bdd1243dSDimitry Andric std::optional<unsigned>
getPendingArrayDestruction(ProgramStateRef State,const LocationContext * LCtx)532bdd1243dSDimitry Andric ExprEngine::getPendingArrayDestruction(ProgramStateRef State,
533bdd1243dSDimitry Andric                                        const LocationContext *LCtx) {
534bdd1243dSDimitry Andric   assert(LCtx && "LocationContext shouldn't be null!");
535bdd1243dSDimitry Andric 
536bdd1243dSDimitry Andric   const unsigned *V =
537bdd1243dSDimitry Andric       State->get<PendingArrayDestruction>(LCtx->getStackFrame());
538bdd1243dSDimitry Andric   return V ? std::make_optional(*V) : std::nullopt;
539bdd1243dSDimitry Andric }
540bdd1243dSDimitry Andric 
setPendingArrayDestruction(ProgramStateRef State,const LocationContext * LCtx,unsigned Idx)541bdd1243dSDimitry Andric ProgramStateRef ExprEngine::setPendingArrayDestruction(
542bdd1243dSDimitry Andric     ProgramStateRef State, const LocationContext *LCtx, unsigned Idx) {
543bdd1243dSDimitry Andric   assert(LCtx && "LocationContext shouldn't be null!");
544bdd1243dSDimitry Andric 
545bdd1243dSDimitry Andric   auto Key = LCtx->getStackFrame();
546bdd1243dSDimitry Andric 
547bdd1243dSDimitry Andric   return State->set<PendingArrayDestruction>(Key, Idx);
548bdd1243dSDimitry Andric }
549bdd1243dSDimitry Andric 
550bdd1243dSDimitry Andric ProgramStateRef
removePendingArrayDestruction(ProgramStateRef State,const LocationContext * LCtx)551bdd1243dSDimitry Andric ExprEngine::removePendingArrayDestruction(ProgramStateRef State,
552bdd1243dSDimitry Andric                                           const LocationContext *LCtx) {
553bdd1243dSDimitry Andric   assert(LCtx && "LocationContext shouldn't be null!");
554bdd1243dSDimitry Andric 
555bdd1243dSDimitry Andric   auto Key = LCtx->getStackFrame();
556bdd1243dSDimitry Andric 
557bdd1243dSDimitry Andric   assert(LCtx && State->contains<PendingArrayDestruction>(Key));
558bdd1243dSDimitry Andric   return State->remove<PendingArrayDestruction>(Key);
559bdd1243dSDimitry Andric }
560bdd1243dSDimitry Andric 
5610b57cec5SDimitry Andric ProgramStateRef
addObjectUnderConstruction(ProgramStateRef State,const ConstructionContextItem & Item,const LocationContext * LC,SVal V)5620b57cec5SDimitry Andric ExprEngine::addObjectUnderConstruction(ProgramStateRef State,
5630b57cec5SDimitry Andric                                        const ConstructionContextItem &Item,
5640b57cec5SDimitry Andric                                        const LocationContext *LC, SVal V) {
5650b57cec5SDimitry Andric   ConstructedObjectKey Key(Item, LC->getStackFrame());
566fcaf7f86SDimitry Andric 
567972a253aSDimitry Andric   const Expr *Init = nullptr;
568fcaf7f86SDimitry Andric 
569fcaf7f86SDimitry Andric   if (auto DS = dyn_cast_or_null<DeclStmt>(Item.getStmtOrNull())) {
570fcaf7f86SDimitry Andric     if (auto VD = dyn_cast_or_null<VarDecl>(DS->getSingleDecl()))
571972a253aSDimitry Andric       Init = VD->getInit();
572fcaf7f86SDimitry Andric   }
573fcaf7f86SDimitry Andric 
574972a253aSDimitry Andric   if (auto LE = dyn_cast_or_null<LambdaExpr>(Item.getStmtOrNull()))
575972a253aSDimitry Andric     Init = *(LE->capture_init_begin() + Item.getIndex());
576972a253aSDimitry Andric 
577972a253aSDimitry Andric   if (!Init && !Item.getStmtOrNull())
578972a253aSDimitry Andric     Init = Item.getCXXCtorInitializer()->getInit();
579972a253aSDimitry Andric 
580972a253aSDimitry Andric   // In an ArrayInitLoopExpr the real initializer is returned by
581bdd1243dSDimitry Andric   // getSubExpr(). Note that AILEs can be nested in case of
582bdd1243dSDimitry Andric   // multidimesnional arrays.
583972a253aSDimitry Andric   if (const auto *AILE = dyn_cast_or_null<ArrayInitLoopExpr>(Init))
584bdd1243dSDimitry Andric     Init = extractElementInitializerFromNestedAILE(AILE);
585fcaf7f86SDimitry Andric 
5860b57cec5SDimitry Andric   // FIXME: Currently the state might already contain the marker due to
5870b57cec5SDimitry Andric   // incorrect handling of temporaries bound to default parameters.
588fcaf7f86SDimitry Andric   // The state will already contain the marker if we construct elements
589fcaf7f86SDimitry Andric   // in an array, as we visit the same statement multiple times before
590fcaf7f86SDimitry Andric   // the array declaration. The marker is removed when we exit the
591fcaf7f86SDimitry Andric   // constructor call.
592fcaf7f86SDimitry Andric   assert((!State->get<ObjectsUnderConstruction>(Key) ||
5930b57cec5SDimitry Andric           Key.getItem().getKind() ==
594fcaf7f86SDimitry Andric               ConstructionContextItem::TemporaryDestructorKind ||
595972a253aSDimitry Andric           State->contains<IndexOfElementToConstruct>(
596972a253aSDimitry Andric               {dyn_cast_or_null<CXXConstructExpr>(Init), LC})) &&
597fcaf7f86SDimitry Andric          "The object is already marked as `UnderConstruction`, when it's not "
598fcaf7f86SDimitry Andric          "supposed to!");
5990b57cec5SDimitry Andric   return State->set<ObjectsUnderConstruction>(Key, V);
6000b57cec5SDimitry Andric }
6010b57cec5SDimitry Andric 
602bdd1243dSDimitry Andric std::optional<SVal>
getObjectUnderConstruction(ProgramStateRef State,const ConstructionContextItem & Item,const LocationContext * LC)6030b57cec5SDimitry Andric ExprEngine::getObjectUnderConstruction(ProgramStateRef State,
6040b57cec5SDimitry Andric                                        const ConstructionContextItem &Item,
6050b57cec5SDimitry Andric                                        const LocationContext *LC) {
6060b57cec5SDimitry Andric   ConstructedObjectKey Key(Item, LC->getStackFrame());
607bdd1243dSDimitry Andric   const SVal *V = State->get<ObjectsUnderConstruction>(Key);
608bdd1243dSDimitry Andric   return V ? std::make_optional(*V) : std::nullopt;
6090b57cec5SDimitry Andric }
6100b57cec5SDimitry Andric 
6110b57cec5SDimitry Andric ProgramStateRef
finishObjectConstruction(ProgramStateRef State,const ConstructionContextItem & Item,const LocationContext * LC)6120b57cec5SDimitry Andric ExprEngine::finishObjectConstruction(ProgramStateRef State,
6130b57cec5SDimitry Andric                                      const ConstructionContextItem &Item,
6140b57cec5SDimitry Andric                                      const LocationContext *LC) {
6150b57cec5SDimitry Andric   ConstructedObjectKey Key(Item, LC->getStackFrame());
6160b57cec5SDimitry Andric   assert(State->contains<ObjectsUnderConstruction>(Key));
6170b57cec5SDimitry Andric   return State->remove<ObjectsUnderConstruction>(Key);
6180b57cec5SDimitry Andric }
6190b57cec5SDimitry Andric 
elideDestructor(ProgramStateRef State,const CXXBindTemporaryExpr * BTE,const LocationContext * LC)6200b57cec5SDimitry Andric ProgramStateRef ExprEngine::elideDestructor(ProgramStateRef State,
6210b57cec5SDimitry Andric                                             const CXXBindTemporaryExpr *BTE,
6220b57cec5SDimitry Andric                                             const LocationContext *LC) {
6230b57cec5SDimitry Andric   ConstructedObjectKey Key({BTE, /*IsElided=*/true}, LC);
6240b57cec5SDimitry Andric   // FIXME: Currently the state might already contain the marker due to
6250b57cec5SDimitry Andric   // incorrect handling of temporaries bound to default parameters.
6260b57cec5SDimitry Andric   return State->set<ObjectsUnderConstruction>(Key, UnknownVal());
6270b57cec5SDimitry Andric }
6280b57cec5SDimitry Andric 
6290b57cec5SDimitry Andric ProgramStateRef
cleanupElidedDestructor(ProgramStateRef State,const CXXBindTemporaryExpr * BTE,const LocationContext * LC)6300b57cec5SDimitry Andric ExprEngine::cleanupElidedDestructor(ProgramStateRef State,
6310b57cec5SDimitry Andric                                     const CXXBindTemporaryExpr *BTE,
6320b57cec5SDimitry Andric                                     const LocationContext *LC) {
6330b57cec5SDimitry Andric   ConstructedObjectKey Key({BTE, /*IsElided=*/true}, LC);
6340b57cec5SDimitry Andric   assert(State->contains<ObjectsUnderConstruction>(Key));
6350b57cec5SDimitry Andric   return State->remove<ObjectsUnderConstruction>(Key);
6360b57cec5SDimitry Andric }
6370b57cec5SDimitry Andric 
isDestructorElided(ProgramStateRef State,const CXXBindTemporaryExpr * BTE,const LocationContext * LC)6380b57cec5SDimitry Andric bool ExprEngine::isDestructorElided(ProgramStateRef State,
6390b57cec5SDimitry Andric                                     const CXXBindTemporaryExpr *BTE,
6400b57cec5SDimitry Andric                                     const LocationContext *LC) {
6410b57cec5SDimitry Andric   ConstructedObjectKey Key({BTE, /*IsElided=*/true}, LC);
6420b57cec5SDimitry Andric   return State->contains<ObjectsUnderConstruction>(Key);
6430b57cec5SDimitry Andric }
6440b57cec5SDimitry Andric 
areAllObjectsFullyConstructed(ProgramStateRef State,const LocationContext * FromLC,const LocationContext * ToLC)6450b57cec5SDimitry Andric bool ExprEngine::areAllObjectsFullyConstructed(ProgramStateRef State,
6460b57cec5SDimitry Andric                                                const LocationContext *FromLC,
6470b57cec5SDimitry Andric                                                const LocationContext *ToLC) {
6480b57cec5SDimitry Andric   const LocationContext *LC = FromLC;
6490b57cec5SDimitry Andric   while (LC != ToLC) {
6500b57cec5SDimitry Andric     assert(LC && "ToLC must be a parent of FromLC!");
6510b57cec5SDimitry Andric     for (auto I : State->get<ObjectsUnderConstruction>())
6520b57cec5SDimitry Andric       if (I.first.getLocationContext() == LC)
6530b57cec5SDimitry Andric         return false;
6540b57cec5SDimitry Andric 
6550b57cec5SDimitry Andric     LC = LC->getParent();
6560b57cec5SDimitry Andric   }
6570b57cec5SDimitry Andric   return true;
6580b57cec5SDimitry Andric }
6590b57cec5SDimitry Andric 
6600b57cec5SDimitry Andric 
6610b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
6620b57cec5SDimitry Andric // Top-level transfer function logic (Dispatcher).
6630b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
6640b57cec5SDimitry Andric 
6650b57cec5SDimitry Andric /// evalAssume - Called by ConstraintManager. Used to call checker-specific
6660b57cec5SDimitry Andric ///  logic for handling assumptions on symbolic values.
processAssume(ProgramStateRef state,SVal cond,bool assumption)6670b57cec5SDimitry Andric ProgramStateRef ExprEngine::processAssume(ProgramStateRef state,
6680b57cec5SDimitry Andric                                               SVal cond, bool assumption) {
6690b57cec5SDimitry Andric   return getCheckerManager().runCheckersForEvalAssume(state, cond, assumption);
6700b57cec5SDimitry Andric }
6710b57cec5SDimitry Andric 
6720b57cec5SDimitry Andric ProgramStateRef
processRegionChanges(ProgramStateRef state,const InvalidatedSymbols * invalidated,ArrayRef<const MemRegion * > Explicits,ArrayRef<const MemRegion * > Regions,const LocationContext * LCtx,const CallEvent * Call)6730b57cec5SDimitry Andric ExprEngine::processRegionChanges(ProgramStateRef state,
6740b57cec5SDimitry Andric                                  const InvalidatedSymbols *invalidated,
6750b57cec5SDimitry Andric                                  ArrayRef<const MemRegion *> Explicits,
6760b57cec5SDimitry Andric                                  ArrayRef<const MemRegion *> Regions,
6770b57cec5SDimitry Andric                                  const LocationContext *LCtx,
6780b57cec5SDimitry Andric                                  const CallEvent *Call) {
6790b57cec5SDimitry Andric   return getCheckerManager().runCheckersForRegionChanges(state, invalidated,
6800b57cec5SDimitry Andric                                                          Explicits, Regions,
6810b57cec5SDimitry Andric                                                          LCtx, Call);
6820b57cec5SDimitry Andric }
6830b57cec5SDimitry Andric 
6840b57cec5SDimitry Andric static void
printObjectsUnderConstructionJson(raw_ostream & Out,ProgramStateRef State,const char * NL,const LocationContext * LCtx,unsigned int Space=0,bool IsDot=false)6850b57cec5SDimitry Andric printObjectsUnderConstructionJson(raw_ostream &Out, ProgramStateRef State,
6860b57cec5SDimitry Andric                                   const char *NL, const LocationContext *LCtx,
6870b57cec5SDimitry Andric                                   unsigned int Space = 0, bool IsDot = false) {
6880b57cec5SDimitry Andric   PrintingPolicy PP =
6890b57cec5SDimitry Andric       LCtx->getAnalysisDeclContext()->getASTContext().getPrintingPolicy();
6900b57cec5SDimitry Andric 
6910b57cec5SDimitry Andric   ++Space;
6920b57cec5SDimitry Andric   bool HasItem = false;
6930b57cec5SDimitry Andric 
6940b57cec5SDimitry Andric   // Store the last key.
6950b57cec5SDimitry Andric   const ConstructedObjectKey *LastKey = nullptr;
6960b57cec5SDimitry Andric   for (const auto &I : State->get<ObjectsUnderConstruction>()) {
6970b57cec5SDimitry Andric     const ConstructedObjectKey &Key = I.first;
6980b57cec5SDimitry Andric     if (Key.getLocationContext() != LCtx)
6990b57cec5SDimitry Andric       continue;
7000b57cec5SDimitry Andric 
7010b57cec5SDimitry Andric     if (!HasItem) {
702bdd1243dSDimitry Andric       Out << '[' << NL;
7030b57cec5SDimitry Andric       HasItem = true;
7040b57cec5SDimitry Andric     }
7050b57cec5SDimitry Andric 
7060b57cec5SDimitry Andric     LastKey = &Key;
7070b57cec5SDimitry Andric   }
7080b57cec5SDimitry Andric 
7090b57cec5SDimitry Andric   for (const auto &I : State->get<ObjectsUnderConstruction>()) {
7100b57cec5SDimitry Andric     const ConstructedObjectKey &Key = I.first;
7110b57cec5SDimitry Andric     SVal Value = I.second;
7120b57cec5SDimitry Andric     if (Key.getLocationContext() != LCtx)
7130b57cec5SDimitry Andric       continue;
7140b57cec5SDimitry Andric 
7150b57cec5SDimitry Andric     Indent(Out, Space, IsDot) << "{ ";
7160b57cec5SDimitry Andric     Key.printJson(Out, nullptr, PP);
7170b57cec5SDimitry Andric     Out << ", \"value\": \"" << Value << "\" }";
7180b57cec5SDimitry Andric 
7190b57cec5SDimitry Andric     if (&Key != LastKey)
7200b57cec5SDimitry Andric       Out << ',';
7210b57cec5SDimitry Andric     Out << NL;
7220b57cec5SDimitry Andric   }
7230b57cec5SDimitry Andric 
7240b57cec5SDimitry Andric   if (HasItem)
7250b57cec5SDimitry Andric     Indent(Out, --Space, IsDot) << ']'; // End of "location_context".
7260b57cec5SDimitry Andric   else {
7270b57cec5SDimitry Andric     Out << "null ";
7280b57cec5SDimitry Andric   }
7290b57cec5SDimitry Andric }
7300b57cec5SDimitry Andric 
printIndicesOfElementsToConstructJson(raw_ostream & Out,ProgramStateRef State,const char * NL,const LocationContext * LCtx,unsigned int Space=0,bool IsDot=false)731fcaf7f86SDimitry Andric static void printIndicesOfElementsToConstructJson(
732fcaf7f86SDimitry Andric     raw_ostream &Out, ProgramStateRef State, const char *NL,
733bdd1243dSDimitry Andric     const LocationContext *LCtx, unsigned int Space = 0, bool IsDot = false) {
734fcaf7f86SDimitry Andric   using KeyT = std::pair<const Expr *, const LocationContext *>;
735fcaf7f86SDimitry Andric 
736bdd1243dSDimitry Andric   const auto &Context = LCtx->getAnalysisDeclContext()->getASTContext();
737bdd1243dSDimitry Andric   PrintingPolicy PP = Context.getPrintingPolicy();
738fcaf7f86SDimitry Andric 
739fcaf7f86SDimitry Andric   ++Space;
740fcaf7f86SDimitry Andric   bool HasItem = false;
741fcaf7f86SDimitry Andric 
742fcaf7f86SDimitry Andric   // Store the last key.
743fcaf7f86SDimitry Andric   KeyT LastKey;
744fcaf7f86SDimitry Andric   for (const auto &I : State->get<IndexOfElementToConstruct>()) {
745fcaf7f86SDimitry Andric     const KeyT &Key = I.first;
746fcaf7f86SDimitry Andric     if (Key.second != LCtx)
747fcaf7f86SDimitry Andric       continue;
748fcaf7f86SDimitry Andric 
749fcaf7f86SDimitry Andric     if (!HasItem) {
750bdd1243dSDimitry Andric       Out << '[' << NL;
751fcaf7f86SDimitry Andric       HasItem = true;
752fcaf7f86SDimitry Andric     }
753fcaf7f86SDimitry Andric 
754fcaf7f86SDimitry Andric     LastKey = Key;
755fcaf7f86SDimitry Andric   }
756fcaf7f86SDimitry Andric 
757fcaf7f86SDimitry Andric   for (const auto &I : State->get<IndexOfElementToConstruct>()) {
758fcaf7f86SDimitry Andric     const KeyT &Key = I.first;
759fcaf7f86SDimitry Andric     unsigned Value = I.second;
760fcaf7f86SDimitry Andric     if (Key.second != LCtx)
761fcaf7f86SDimitry Andric       continue;
762fcaf7f86SDimitry Andric 
763fcaf7f86SDimitry Andric     Indent(Out, Space, IsDot) << "{ ";
764fcaf7f86SDimitry Andric 
765fcaf7f86SDimitry Andric     // Expr
766fcaf7f86SDimitry Andric     const Expr *E = Key.first;
767fcaf7f86SDimitry Andric     Out << "\"stmt_id\": " << E->getID(Context);
768fcaf7f86SDimitry Andric 
769bdd1243dSDimitry Andric     // Kind
770bdd1243dSDimitry Andric     Out << ", \"kind\": null";
771fcaf7f86SDimitry Andric 
772fcaf7f86SDimitry Andric     // Pretty-print
773fcaf7f86SDimitry Andric     Out << ", \"pretty\": ";
774bdd1243dSDimitry Andric     Out << "\"" << E->getStmtClassName() << ' '
775fcaf7f86SDimitry Andric         << E->getSourceRange().printToString(Context.getSourceManager()) << " '"
776fcaf7f86SDimitry Andric         << QualType::getAsString(E->getType().split(), PP);
777fcaf7f86SDimitry Andric     Out << "'\"";
778fcaf7f86SDimitry Andric 
779bdd1243dSDimitry Andric     Out << ", \"value\": \"Current index: " << Value - 1 << "\" }";
780fcaf7f86SDimitry Andric 
781fcaf7f86SDimitry Andric     if (Key != LastKey)
782fcaf7f86SDimitry Andric       Out << ',';
783fcaf7f86SDimitry Andric     Out << NL;
784fcaf7f86SDimitry Andric   }
785fcaf7f86SDimitry Andric 
786fcaf7f86SDimitry Andric   if (HasItem)
787fcaf7f86SDimitry Andric     Indent(Out, --Space, IsDot) << ']'; // End of "location_context".
788fcaf7f86SDimitry Andric   else {
789fcaf7f86SDimitry Andric     Out << "null ";
790fcaf7f86SDimitry Andric   }
791fcaf7f86SDimitry Andric }
792fcaf7f86SDimitry Andric 
printPendingInitLoopJson(raw_ostream & Out,ProgramStateRef State,const char * NL,const LocationContext * LCtx,unsigned int Space=0,bool IsDot=false)793bdd1243dSDimitry Andric static void printPendingInitLoopJson(raw_ostream &Out, ProgramStateRef State,
794bdd1243dSDimitry Andric                                      const char *NL,
795bdd1243dSDimitry Andric                                      const LocationContext *LCtx,
796bdd1243dSDimitry Andric                                      unsigned int Space = 0,
797bdd1243dSDimitry Andric                                      bool IsDot = false) {
798bdd1243dSDimitry Andric   using KeyT = std::pair<const CXXConstructExpr *, const LocationContext *>;
799bdd1243dSDimitry Andric 
800bdd1243dSDimitry Andric   const auto &Context = LCtx->getAnalysisDeclContext()->getASTContext();
801bdd1243dSDimitry Andric   PrintingPolicy PP = Context.getPrintingPolicy();
802bdd1243dSDimitry Andric 
803bdd1243dSDimitry Andric   ++Space;
804bdd1243dSDimitry Andric   bool HasItem = false;
805bdd1243dSDimitry Andric 
806bdd1243dSDimitry Andric   // Store the last key.
807bdd1243dSDimitry Andric   KeyT LastKey;
808bdd1243dSDimitry Andric   for (const auto &I : State->get<PendingInitLoop>()) {
809bdd1243dSDimitry Andric     const KeyT &Key = I.first;
810bdd1243dSDimitry Andric     if (Key.second != LCtx)
811bdd1243dSDimitry Andric       continue;
812bdd1243dSDimitry Andric 
813bdd1243dSDimitry Andric     if (!HasItem) {
814bdd1243dSDimitry Andric       Out << '[' << NL;
815bdd1243dSDimitry Andric       HasItem = true;
816bdd1243dSDimitry Andric     }
817bdd1243dSDimitry Andric 
818bdd1243dSDimitry Andric     LastKey = Key;
819bdd1243dSDimitry Andric   }
820bdd1243dSDimitry Andric 
821bdd1243dSDimitry Andric   for (const auto &I : State->get<PendingInitLoop>()) {
822bdd1243dSDimitry Andric     const KeyT &Key = I.first;
823bdd1243dSDimitry Andric     unsigned Value = I.second;
824bdd1243dSDimitry Andric     if (Key.second != LCtx)
825bdd1243dSDimitry Andric       continue;
826bdd1243dSDimitry Andric 
827bdd1243dSDimitry Andric     Indent(Out, Space, IsDot) << "{ ";
828bdd1243dSDimitry Andric 
829bdd1243dSDimitry Andric     const CXXConstructExpr *E = Key.first;
830bdd1243dSDimitry Andric     Out << "\"stmt_id\": " << E->getID(Context);
831bdd1243dSDimitry Andric 
832bdd1243dSDimitry Andric     Out << ", \"kind\": null";
833bdd1243dSDimitry Andric     Out << ", \"pretty\": ";
834bdd1243dSDimitry Andric     Out << '\"' << E->getStmtClassName() << ' '
835bdd1243dSDimitry Andric         << E->getSourceRange().printToString(Context.getSourceManager()) << " '"
836bdd1243dSDimitry Andric         << QualType::getAsString(E->getType().split(), PP);
837bdd1243dSDimitry Andric     Out << "'\"";
838bdd1243dSDimitry Andric 
839bdd1243dSDimitry Andric     Out << ", \"value\": \"Flattened size: " << Value << "\"}";
840bdd1243dSDimitry Andric 
841bdd1243dSDimitry Andric     if (Key != LastKey)
842bdd1243dSDimitry Andric       Out << ',';
843bdd1243dSDimitry Andric     Out << NL;
844bdd1243dSDimitry Andric   }
845bdd1243dSDimitry Andric 
846bdd1243dSDimitry Andric   if (HasItem)
847bdd1243dSDimitry Andric     Indent(Out, --Space, IsDot) << ']'; // End of "location_context".
848bdd1243dSDimitry Andric   else {
849bdd1243dSDimitry Andric     Out << "null ";
850bdd1243dSDimitry Andric   }
851bdd1243dSDimitry Andric }
852bdd1243dSDimitry Andric 
853bdd1243dSDimitry Andric static void
printPendingArrayDestructionsJson(raw_ostream & Out,ProgramStateRef State,const char * NL,const LocationContext * LCtx,unsigned int Space=0,bool IsDot=false)854bdd1243dSDimitry Andric printPendingArrayDestructionsJson(raw_ostream &Out, ProgramStateRef State,
855bdd1243dSDimitry Andric                                   const char *NL, const LocationContext *LCtx,
856bdd1243dSDimitry Andric                                   unsigned int Space = 0, bool IsDot = false) {
857bdd1243dSDimitry Andric   using KeyT = const LocationContext *;
858bdd1243dSDimitry Andric 
859bdd1243dSDimitry Andric   ++Space;
860bdd1243dSDimitry Andric   bool HasItem = false;
861bdd1243dSDimitry Andric 
862bdd1243dSDimitry Andric   // Store the last key.
863bdd1243dSDimitry Andric   KeyT LastKey = nullptr;
864bdd1243dSDimitry Andric   for (const auto &I : State->get<PendingArrayDestruction>()) {
865bdd1243dSDimitry Andric     const KeyT &Key = I.first;
866bdd1243dSDimitry Andric     if (Key != LCtx)
867bdd1243dSDimitry Andric       continue;
868bdd1243dSDimitry Andric 
869bdd1243dSDimitry Andric     if (!HasItem) {
870bdd1243dSDimitry Andric       Out << '[' << NL;
871bdd1243dSDimitry Andric       HasItem = true;
872bdd1243dSDimitry Andric     }
873bdd1243dSDimitry Andric 
874bdd1243dSDimitry Andric     LastKey = Key;
875bdd1243dSDimitry Andric   }
876bdd1243dSDimitry Andric 
877bdd1243dSDimitry Andric   for (const auto &I : State->get<PendingArrayDestruction>()) {
878bdd1243dSDimitry Andric     const KeyT &Key = I.first;
879bdd1243dSDimitry Andric     if (Key != LCtx)
880bdd1243dSDimitry Andric       continue;
881bdd1243dSDimitry Andric 
882bdd1243dSDimitry Andric     Indent(Out, Space, IsDot) << "{ ";
883bdd1243dSDimitry Andric 
884bdd1243dSDimitry Andric     Out << "\"stmt_id\": null";
885bdd1243dSDimitry Andric     Out << ", \"kind\": null";
886bdd1243dSDimitry Andric     Out << ", \"pretty\": \"Current index: \"";
887bdd1243dSDimitry Andric     Out << ", \"value\": \"" << I.second << "\" }";
888bdd1243dSDimitry Andric 
889bdd1243dSDimitry Andric     if (Key != LastKey)
890bdd1243dSDimitry Andric       Out << ',';
891bdd1243dSDimitry Andric     Out << NL;
892bdd1243dSDimitry Andric   }
893bdd1243dSDimitry Andric 
894bdd1243dSDimitry Andric   if (HasItem)
895bdd1243dSDimitry Andric     Indent(Out, --Space, IsDot) << ']'; // End of "location_context".
896bdd1243dSDimitry Andric   else {
897bdd1243dSDimitry Andric     Out << "null ";
898bdd1243dSDimitry Andric   }
899bdd1243dSDimitry Andric }
900bdd1243dSDimitry Andric 
901bdd1243dSDimitry Andric /// A helper function to generalize program state trait printing.
902bdd1243dSDimitry Andric /// The function invokes Printer as 'Printer(Out, State, NL, LC, Space, IsDot,
903bdd1243dSDimitry Andric /// std::forward<Args>(args)...)'. \n One possible type for Printer is
904bdd1243dSDimitry Andric /// 'void()(raw_ostream &, ProgramStateRef, const char *, const LocationContext
905bdd1243dSDimitry Andric /// *, unsigned int, bool, ...)' \n \param Trait The state trait to be printed.
906bdd1243dSDimitry Andric /// \param Printer A void function that prints Trait.
907bdd1243dSDimitry Andric /// \param Args An additional parameter pack that is passed to Print upon
908bdd1243dSDimitry Andric /// invocation.
909bdd1243dSDimitry Andric template <typename Trait, typename Printer, typename... Args>
printStateTraitWithLocationContextJson(raw_ostream & Out,ProgramStateRef State,const LocationContext * LCtx,const char * NL,unsigned int Space,bool IsDot,const char * jsonPropertyName,Printer printer,Args &&...args)910bdd1243dSDimitry Andric static void printStateTraitWithLocationContextJson(
911bdd1243dSDimitry Andric     raw_ostream &Out, ProgramStateRef State, const LocationContext *LCtx,
912bdd1243dSDimitry Andric     const char *NL, unsigned int Space, bool IsDot,
913bdd1243dSDimitry Andric     const char *jsonPropertyName, Printer printer, Args &&...args) {
914bdd1243dSDimitry Andric 
915bdd1243dSDimitry Andric   using RequiredType =
916bdd1243dSDimitry Andric       void (*)(raw_ostream &, ProgramStateRef, const char *,
917bdd1243dSDimitry Andric                const LocationContext *, unsigned int, bool, Args &&...);
918bdd1243dSDimitry Andric 
919bdd1243dSDimitry Andric   // Try to do as much compile time checking as possible.
920bdd1243dSDimitry Andric   // FIXME: check for invocable instead of function?
921bdd1243dSDimitry Andric   static_assert(std::is_function_v<std::remove_pointer_t<Printer>>,
922bdd1243dSDimitry Andric                 "Printer is not a function!");
923bdd1243dSDimitry Andric   static_assert(std::is_convertible_v<Printer, RequiredType>,
924bdd1243dSDimitry Andric                 "Printer doesn't have the required type!");
925bdd1243dSDimitry Andric 
926bdd1243dSDimitry Andric   if (LCtx && !State->get<Trait>().isEmpty()) {
927bdd1243dSDimitry Andric     Indent(Out, Space, IsDot) << '\"' << jsonPropertyName << "\": ";
928bdd1243dSDimitry Andric     ++Space;
929bdd1243dSDimitry Andric     Out << '[' << NL;
930bdd1243dSDimitry Andric     LCtx->printJson(Out, NL, Space, IsDot, [&](const LocationContext *LC) {
931bdd1243dSDimitry Andric       printer(Out, State, NL, LC, Space, IsDot, std::forward<Args>(args)...);
932bdd1243dSDimitry Andric     });
933bdd1243dSDimitry Andric 
934bdd1243dSDimitry Andric     --Space;
935bdd1243dSDimitry Andric     Indent(Out, Space, IsDot) << "]," << NL; // End of "jsonPropertyName".
936bdd1243dSDimitry Andric   }
937bdd1243dSDimitry Andric }
938bdd1243dSDimitry Andric 
printJson(raw_ostream & Out,ProgramStateRef State,const LocationContext * LCtx,const char * NL,unsigned int Space,bool IsDot) const9390b57cec5SDimitry Andric void ExprEngine::printJson(raw_ostream &Out, ProgramStateRef State,
9400b57cec5SDimitry Andric                            const LocationContext *LCtx, const char *NL,
9410b57cec5SDimitry Andric                            unsigned int Space, bool IsDot) const {
9420b57cec5SDimitry Andric 
943bdd1243dSDimitry Andric   printStateTraitWithLocationContextJson<ObjectsUnderConstruction>(
944bdd1243dSDimitry Andric       Out, State, LCtx, NL, Space, IsDot, "constructing_objects",
945bdd1243dSDimitry Andric       printObjectsUnderConstructionJson);
946bdd1243dSDimitry Andric   printStateTraitWithLocationContextJson<IndexOfElementToConstruct>(
947bdd1243dSDimitry Andric       Out, State, LCtx, NL, Space, IsDot, "index_of_element",
948bdd1243dSDimitry Andric       printIndicesOfElementsToConstructJson);
949bdd1243dSDimitry Andric   printStateTraitWithLocationContextJson<PendingInitLoop>(
950bdd1243dSDimitry Andric       Out, State, LCtx, NL, Space, IsDot, "pending_init_loops",
951bdd1243dSDimitry Andric       printPendingInitLoopJson);
952bdd1243dSDimitry Andric   printStateTraitWithLocationContextJson<PendingArrayDestruction>(
953bdd1243dSDimitry Andric       Out, State, LCtx, NL, Space, IsDot, "pending_destructors",
954bdd1243dSDimitry Andric       printPendingArrayDestructionsJson);
955fcaf7f86SDimitry Andric 
9560b57cec5SDimitry Andric   getCheckerManager().runCheckersForPrintStateJson(Out, State, NL, Space,
9570b57cec5SDimitry Andric                                                    IsDot);
9580b57cec5SDimitry Andric }
9590b57cec5SDimitry Andric 
processEndWorklist()9600b57cec5SDimitry Andric void ExprEngine::processEndWorklist() {
96181ad6265SDimitry Andric   // This prints the name of the top-level function if we crash.
96281ad6265SDimitry Andric   PrettyStackTraceLocationContext CrashInfo(getRootLocationContext());
9630b57cec5SDimitry Andric   getCheckerManager().runCheckersForEndAnalysis(G, BR, *this);
9640b57cec5SDimitry Andric }
9650b57cec5SDimitry Andric 
processCFGElement(const CFGElement E,ExplodedNode * Pred,unsigned StmtIdx,NodeBuilderContext * Ctx)9660b57cec5SDimitry Andric void ExprEngine::processCFGElement(const CFGElement E, ExplodedNode *Pred,
9670b57cec5SDimitry Andric                                    unsigned StmtIdx, NodeBuilderContext *Ctx) {
9680b57cec5SDimitry Andric   PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
9690b57cec5SDimitry Andric   currStmtIdx = StmtIdx;
9700b57cec5SDimitry Andric   currBldrCtx = Ctx;
9710b57cec5SDimitry Andric 
9720b57cec5SDimitry Andric   switch (E.getKind()) {
9730b57cec5SDimitry Andric     case CFGElement::Statement:
9740b57cec5SDimitry Andric     case CFGElement::Constructor:
9750b57cec5SDimitry Andric     case CFGElement::CXXRecordTypedCall:
9760b57cec5SDimitry Andric       ProcessStmt(E.castAs<CFGStmt>().getStmt(), Pred);
9770b57cec5SDimitry Andric       return;
9780b57cec5SDimitry Andric     case CFGElement::Initializer:
9790b57cec5SDimitry Andric       ProcessInitializer(E.castAs<CFGInitializer>(), Pred);
9800b57cec5SDimitry Andric       return;
9810b57cec5SDimitry Andric     case CFGElement::NewAllocator:
9820b57cec5SDimitry Andric       ProcessNewAllocator(E.castAs<CFGNewAllocator>().getAllocatorExpr(),
9830b57cec5SDimitry Andric                           Pred);
9840b57cec5SDimitry Andric       return;
9850b57cec5SDimitry Andric     case CFGElement::AutomaticObjectDtor:
9860b57cec5SDimitry Andric     case CFGElement::DeleteDtor:
9870b57cec5SDimitry Andric     case CFGElement::BaseDtor:
9880b57cec5SDimitry Andric     case CFGElement::MemberDtor:
9890b57cec5SDimitry Andric     case CFGElement::TemporaryDtor:
9900b57cec5SDimitry Andric       ProcessImplicitDtor(E.castAs<CFGImplicitDtor>(), Pred);
9910b57cec5SDimitry Andric       return;
9920b57cec5SDimitry Andric     case CFGElement::LoopExit:
9930b57cec5SDimitry Andric       ProcessLoopExit(E.castAs<CFGLoopExit>().getLoopStmt(), Pred);
9940b57cec5SDimitry Andric       return;
9950b57cec5SDimitry Andric     case CFGElement::LifetimeEnds:
9965f757f3fSDimitry Andric     case CFGElement::CleanupFunction:
9970b57cec5SDimitry Andric     case CFGElement::ScopeBegin:
9980b57cec5SDimitry Andric     case CFGElement::ScopeEnd:
9990b57cec5SDimitry Andric       return;
10000b57cec5SDimitry Andric   }
10010b57cec5SDimitry Andric }
10020b57cec5SDimitry Andric 
shouldRemoveDeadBindings(AnalysisManager & AMgr,const Stmt * S,const ExplodedNode * Pred,const LocationContext * LC)10030b57cec5SDimitry Andric static bool shouldRemoveDeadBindings(AnalysisManager &AMgr,
10040b57cec5SDimitry Andric                                      const Stmt *S,
10050b57cec5SDimitry Andric                                      const ExplodedNode *Pred,
10060b57cec5SDimitry Andric                                      const LocationContext *LC) {
10070b57cec5SDimitry Andric   // Are we never purging state values?
10080b57cec5SDimitry Andric   if (AMgr.options.AnalysisPurgeOpt == PurgeNone)
10090b57cec5SDimitry Andric     return false;
10100b57cec5SDimitry Andric 
10110b57cec5SDimitry Andric   // Is this the beginning of a basic block?
10120b57cec5SDimitry Andric   if (Pred->getLocation().getAs<BlockEntrance>())
10130b57cec5SDimitry Andric     return true;
10140b57cec5SDimitry Andric 
10150b57cec5SDimitry Andric   // Is this on a non-expression?
10160b57cec5SDimitry Andric   if (!isa<Expr>(S))
10170b57cec5SDimitry Andric     return true;
10180b57cec5SDimitry Andric 
10190b57cec5SDimitry Andric   // Run before processing a call.
10200b57cec5SDimitry Andric   if (CallEvent::isCallStmt(S))
10210b57cec5SDimitry Andric     return true;
10220b57cec5SDimitry Andric 
10230b57cec5SDimitry Andric   // Is this an expression that is consumed by another expression?  If so,
10240b57cec5SDimitry Andric   // postpone cleaning out the state.
10250b57cec5SDimitry Andric   ParentMap &PM = LC->getAnalysisDeclContext()->getParentMap();
10260b57cec5SDimitry Andric   return !PM.isConsumedExpr(cast<Expr>(S));
10270b57cec5SDimitry Andric }
10280b57cec5SDimitry Andric 
removeDead(ExplodedNode * Pred,ExplodedNodeSet & Out,const Stmt * ReferenceStmt,const LocationContext * LC,const Stmt * DiagnosticStmt,ProgramPoint::Kind K)10290b57cec5SDimitry Andric void ExprEngine::removeDead(ExplodedNode *Pred, ExplodedNodeSet &Out,
10300b57cec5SDimitry Andric                             const Stmt *ReferenceStmt,
10310b57cec5SDimitry Andric                             const LocationContext *LC,
10320b57cec5SDimitry Andric                             const Stmt *DiagnosticStmt,
10330b57cec5SDimitry Andric                             ProgramPoint::Kind K) {
10340b57cec5SDimitry Andric   assert((K == ProgramPoint::PreStmtPurgeDeadSymbolsKind ||
10350b57cec5SDimitry Andric           ReferenceStmt == nullptr || isa<ReturnStmt>(ReferenceStmt))
10360b57cec5SDimitry Andric           && "PostStmt is not generally supported by the SymbolReaper yet");
10370b57cec5SDimitry Andric   assert(LC && "Must pass the current (or expiring) LocationContext");
10380b57cec5SDimitry Andric 
10390b57cec5SDimitry Andric   if (!DiagnosticStmt) {
10400b57cec5SDimitry Andric     DiagnosticStmt = ReferenceStmt;
10410b57cec5SDimitry Andric     assert(DiagnosticStmt && "Required for clearing a LocationContext");
10420b57cec5SDimitry Andric   }
10430b57cec5SDimitry Andric 
10440b57cec5SDimitry Andric   NumRemoveDeadBindings++;
10450b57cec5SDimitry Andric   ProgramStateRef CleanedState = Pred->getState();
10460b57cec5SDimitry Andric 
10470b57cec5SDimitry Andric   // LC is the location context being destroyed, but SymbolReaper wants a
10480b57cec5SDimitry Andric   // location context that is still live. (If this is the top-level stack
10490b57cec5SDimitry Andric   // frame, this will be null.)
10500b57cec5SDimitry Andric   if (!ReferenceStmt) {
10510b57cec5SDimitry Andric     assert(K == ProgramPoint::PostStmtPurgeDeadSymbolsKind &&
10520b57cec5SDimitry Andric            "Use PostStmtPurgeDeadSymbolsKind for clearing a LocationContext");
10530b57cec5SDimitry Andric     LC = LC->getParent();
10540b57cec5SDimitry Andric   }
10550b57cec5SDimitry Andric 
10560b57cec5SDimitry Andric   const StackFrameContext *SFC = LC ? LC->getStackFrame() : nullptr;
10570b57cec5SDimitry Andric   SymbolReaper SymReaper(SFC, ReferenceStmt, SymMgr, getStoreManager());
10580b57cec5SDimitry Andric 
10590b57cec5SDimitry Andric   for (auto I : CleanedState->get<ObjectsUnderConstruction>()) {
10600b57cec5SDimitry Andric     if (SymbolRef Sym = I.second.getAsSymbol())
10610b57cec5SDimitry Andric       SymReaper.markLive(Sym);
10620b57cec5SDimitry Andric     if (const MemRegion *MR = I.second.getAsRegion())
10630b57cec5SDimitry Andric       SymReaper.markLive(MR);
10640b57cec5SDimitry Andric   }
10650b57cec5SDimitry Andric 
10660b57cec5SDimitry Andric   getCheckerManager().runCheckersForLiveSymbols(CleanedState, SymReaper);
10670b57cec5SDimitry Andric 
10680b57cec5SDimitry Andric   // Create a state in which dead bindings are removed from the environment
10690b57cec5SDimitry Andric   // and the store. TODO: The function should just return new env and store,
10700b57cec5SDimitry Andric   // not a new state.
1071480093f4SDimitry Andric   CleanedState = StateMgr.removeDeadBindingsFromEnvironmentAndStore(
1072480093f4SDimitry Andric       CleanedState, SFC, SymReaper);
10730b57cec5SDimitry Andric 
10740b57cec5SDimitry Andric   // Process any special transfer function for dead symbols.
10750b57cec5SDimitry Andric   // A tag to track convenience transitions, which can be removed at cleanup.
10760b57cec5SDimitry Andric   static SimpleProgramPointTag cleanupTag(TagProviderName, "Clean Node");
10770b57cec5SDimitry Andric   // Call checkers with the non-cleaned state so that they could query the
10780b57cec5SDimitry Andric   // values of the soon to be dead symbols.
10790b57cec5SDimitry Andric   ExplodedNodeSet CheckedSet;
10800b57cec5SDimitry Andric   getCheckerManager().runCheckersForDeadSymbols(CheckedSet, Pred, SymReaper,
10810b57cec5SDimitry Andric                                                 DiagnosticStmt, *this, K);
10820b57cec5SDimitry Andric 
10830b57cec5SDimitry Andric   // For each node in CheckedSet, generate CleanedNodes that have the
10840b57cec5SDimitry Andric   // environment, the store, and the constraints cleaned up but have the
10850b57cec5SDimitry Andric   // user-supplied states as the predecessors.
10860b57cec5SDimitry Andric   StmtNodeBuilder Bldr(CheckedSet, Out, *currBldrCtx);
10870b57cec5SDimitry Andric   for (const auto I : CheckedSet) {
10880b57cec5SDimitry Andric     ProgramStateRef CheckerState = I->getState();
10890b57cec5SDimitry Andric 
10900b57cec5SDimitry Andric     // The constraint manager has not been cleaned up yet, so clean up now.
10910b57cec5SDimitry Andric     CheckerState =
10920b57cec5SDimitry Andric         getConstraintManager().removeDeadBindings(CheckerState, SymReaper);
10930b57cec5SDimitry Andric 
10940b57cec5SDimitry Andric     assert(StateMgr.haveEqualEnvironments(CheckerState, Pred->getState()) &&
10950b57cec5SDimitry Andric            "Checkers are not allowed to modify the Environment as a part of "
10960b57cec5SDimitry Andric            "checkDeadSymbols processing.");
10970b57cec5SDimitry Andric     assert(StateMgr.haveEqualStores(CheckerState, Pred->getState()) &&
10980b57cec5SDimitry Andric            "Checkers are not allowed to modify the Store as a part of "
10990b57cec5SDimitry Andric            "checkDeadSymbols processing.");
11000b57cec5SDimitry Andric 
11010b57cec5SDimitry Andric     // Create a state based on CleanedState with CheckerState GDM and
11020b57cec5SDimitry Andric     // generate a transition to that state.
11030b57cec5SDimitry Andric     ProgramStateRef CleanedCheckerSt =
11040b57cec5SDimitry Andric         StateMgr.getPersistentStateWithGDM(CleanedState, CheckerState);
11050b57cec5SDimitry Andric     Bldr.generateNode(DiagnosticStmt, I, CleanedCheckerSt, &cleanupTag, K);
11060b57cec5SDimitry Andric   }
11070b57cec5SDimitry Andric }
11080b57cec5SDimitry Andric 
ProcessStmt(const Stmt * currStmt,ExplodedNode * Pred)11090b57cec5SDimitry Andric void ExprEngine::ProcessStmt(const Stmt *currStmt, ExplodedNode *Pred) {
11100b57cec5SDimitry Andric   // Reclaim any unnecessary nodes in the ExplodedGraph.
11110b57cec5SDimitry Andric   G.reclaimRecentlyAllocatedNodes();
11120b57cec5SDimitry Andric 
11130b57cec5SDimitry Andric   PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
11140b57cec5SDimitry Andric                                 currStmt->getBeginLoc(),
11150b57cec5SDimitry Andric                                 "Error evaluating statement");
11160b57cec5SDimitry Andric 
11170b57cec5SDimitry Andric   // Remove dead bindings and symbols.
11180b57cec5SDimitry Andric   ExplodedNodeSet CleanedStates;
11190b57cec5SDimitry Andric   if (shouldRemoveDeadBindings(AMgr, currStmt, Pred,
11200b57cec5SDimitry Andric                                Pred->getLocationContext())) {
11210b57cec5SDimitry Andric     removeDead(Pred, CleanedStates, currStmt,
11220b57cec5SDimitry Andric                                     Pred->getLocationContext());
11230b57cec5SDimitry Andric   } else
11240b57cec5SDimitry Andric     CleanedStates.Add(Pred);
11250b57cec5SDimitry Andric 
11260b57cec5SDimitry Andric   // Visit the statement.
11270b57cec5SDimitry Andric   ExplodedNodeSet Dst;
11280b57cec5SDimitry Andric   for (const auto I : CleanedStates) {
11290b57cec5SDimitry Andric     ExplodedNodeSet DstI;
11300b57cec5SDimitry Andric     // Visit the statement.
11310b57cec5SDimitry Andric     Visit(currStmt, I, DstI);
11320b57cec5SDimitry Andric     Dst.insert(DstI);
11330b57cec5SDimitry Andric   }
11340b57cec5SDimitry Andric 
11350b57cec5SDimitry Andric   // Enqueue the new nodes onto the work list.
11360b57cec5SDimitry Andric   Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
11370b57cec5SDimitry Andric }
11380b57cec5SDimitry Andric 
ProcessLoopExit(const Stmt * S,ExplodedNode * Pred)11390b57cec5SDimitry Andric void ExprEngine::ProcessLoopExit(const Stmt* S, ExplodedNode *Pred) {
11400b57cec5SDimitry Andric   PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
11410b57cec5SDimitry Andric                                 S->getBeginLoc(),
11420b57cec5SDimitry Andric                                 "Error evaluating end of the loop");
11430b57cec5SDimitry Andric   ExplodedNodeSet Dst;
11440b57cec5SDimitry Andric   Dst.Add(Pred);
11450b57cec5SDimitry Andric   NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
11460b57cec5SDimitry Andric   ProgramStateRef NewState = Pred->getState();
11470b57cec5SDimitry Andric 
11480b57cec5SDimitry Andric   if(AMgr.options.ShouldUnrollLoops)
11490b57cec5SDimitry Andric     NewState = processLoopEnd(S, NewState);
11500b57cec5SDimitry Andric 
11510b57cec5SDimitry Andric   LoopExit PP(S, Pred->getLocationContext());
11520b57cec5SDimitry Andric   Bldr.generateNode(PP, NewState, Pred);
11530b57cec5SDimitry Andric   // Enqueue the new nodes onto the work list.
11540b57cec5SDimitry Andric   Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
11550b57cec5SDimitry Andric }
11560b57cec5SDimitry Andric 
ProcessInitializer(const CFGInitializer CFGInit,ExplodedNode * Pred)11570b57cec5SDimitry Andric void ExprEngine::ProcessInitializer(const CFGInitializer CFGInit,
11580b57cec5SDimitry Andric                                     ExplodedNode *Pred) {
11590b57cec5SDimitry Andric   const CXXCtorInitializer *BMI = CFGInit.getInitializer();
11600b57cec5SDimitry Andric   const Expr *Init = BMI->getInit()->IgnoreImplicit();
11610b57cec5SDimitry Andric   const LocationContext *LC = Pred->getLocationContext();
11620b57cec5SDimitry Andric 
11630b57cec5SDimitry Andric   PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
11640b57cec5SDimitry Andric                                 BMI->getSourceLocation(),
11650b57cec5SDimitry Andric                                 "Error evaluating initializer");
11660b57cec5SDimitry Andric 
11670b57cec5SDimitry Andric   // We don't clean up dead bindings here.
11680b57cec5SDimitry Andric   const auto *stackFrame = cast<StackFrameContext>(Pred->getLocationContext());
11690b57cec5SDimitry Andric   const auto *decl = cast<CXXConstructorDecl>(stackFrame->getDecl());
11700b57cec5SDimitry Andric 
11710b57cec5SDimitry Andric   ProgramStateRef State = Pred->getState();
11720b57cec5SDimitry Andric   SVal thisVal = State->getSVal(svalBuilder.getCXXThis(decl, stackFrame));
11730b57cec5SDimitry Andric 
11740b57cec5SDimitry Andric   ExplodedNodeSet Tmp;
11750b57cec5SDimitry Andric   SVal FieldLoc;
11760b57cec5SDimitry Andric 
11770b57cec5SDimitry Andric   // Evaluate the initializer, if necessary
11780b57cec5SDimitry Andric   if (BMI->isAnyMemberInitializer()) {
11790b57cec5SDimitry Andric     // Constructors build the object directly in the field,
11800b57cec5SDimitry Andric     // but non-objects must be copied in from the initializer.
11810b57cec5SDimitry Andric     if (getObjectUnderConstruction(State, BMI, LC)) {
11820b57cec5SDimitry Andric       // The field was directly constructed, so there is no need to bind.
11830b57cec5SDimitry Andric       // But we still need to stop tracking the object under construction.
11840b57cec5SDimitry Andric       State = finishObjectConstruction(State, BMI, LC);
11850b57cec5SDimitry Andric       NodeBuilder Bldr(Pred, Tmp, *currBldrCtx);
11860b57cec5SDimitry Andric       PostStore PS(Init, LC, /*Loc*/ nullptr, /*tag*/ nullptr);
11870b57cec5SDimitry Andric       Bldr.generateNode(PS, State, Pred);
11880b57cec5SDimitry Andric     } else {
11890b57cec5SDimitry Andric       const ValueDecl *Field;
11900b57cec5SDimitry Andric       if (BMI->isIndirectMemberInitializer()) {
11910b57cec5SDimitry Andric         Field = BMI->getIndirectMember();
11920b57cec5SDimitry Andric         FieldLoc = State->getLValue(BMI->getIndirectMember(), thisVal);
11930b57cec5SDimitry Andric       } else {
11940b57cec5SDimitry Andric         Field = BMI->getMember();
11950b57cec5SDimitry Andric         FieldLoc = State->getLValue(BMI->getMember(), thisVal);
11960b57cec5SDimitry Andric       }
11970b57cec5SDimitry Andric 
11980b57cec5SDimitry Andric       SVal InitVal;
11990b57cec5SDimitry Andric       if (Init->getType()->isArrayType()) {
12000b57cec5SDimitry Andric         // Handle arrays of trivial type. We can represent this with a
12010b57cec5SDimitry Andric         // primitive load/copy from the base array region.
12020b57cec5SDimitry Andric         const ArraySubscriptExpr *ASE;
12030b57cec5SDimitry Andric         while ((ASE = dyn_cast<ArraySubscriptExpr>(Init)))
12040b57cec5SDimitry Andric           Init = ASE->getBase()->IgnoreImplicit();
12050b57cec5SDimitry Andric 
12060b57cec5SDimitry Andric         SVal LValue = State->getSVal(Init, stackFrame);
12070b57cec5SDimitry Andric         if (!Field->getType()->isReferenceType())
1208bdd1243dSDimitry Andric           if (std::optional<Loc> LValueLoc = LValue.getAs<Loc>())
12090b57cec5SDimitry Andric             InitVal = State->getSVal(*LValueLoc);
12100b57cec5SDimitry Andric 
12110b57cec5SDimitry Andric         // If we fail to get the value for some reason, use a symbolic value.
12120b57cec5SDimitry Andric         if (InitVal.isUnknownOrUndef()) {
12130b57cec5SDimitry Andric           SValBuilder &SVB = getSValBuilder();
12140b57cec5SDimitry Andric           InitVal = SVB.conjureSymbolVal(BMI->getInit(), stackFrame,
12150b57cec5SDimitry Andric                                          Field->getType(),
12160b57cec5SDimitry Andric                                          currBldrCtx->blockCount());
12170b57cec5SDimitry Andric         }
12180b57cec5SDimitry Andric       } else {
12190b57cec5SDimitry Andric         InitVal = State->getSVal(BMI->getInit(), stackFrame);
12200b57cec5SDimitry Andric       }
12210b57cec5SDimitry Andric 
12220b57cec5SDimitry Andric       PostInitializer PP(BMI, FieldLoc.getAsRegion(), stackFrame);
12230b57cec5SDimitry Andric       evalBind(Tmp, Init, Pred, FieldLoc, InitVal, /*isInit=*/true, &PP);
12240b57cec5SDimitry Andric     }
12255f757f3fSDimitry Andric   } else if (BMI->isBaseInitializer() && isa<InitListExpr>(Init)) {
12265f757f3fSDimitry Andric     // When the base class is initialized with an initialization list and the
12275f757f3fSDimitry Andric     // base class does not have a ctor, there will not be a CXXConstructExpr to
12285f757f3fSDimitry Andric     // initialize the base region. Hence, we need to make the bind for it.
12295f757f3fSDimitry Andric     SVal BaseLoc = getStoreManager().evalDerivedToBase(
12305f757f3fSDimitry Andric         thisVal, QualType(BMI->getBaseClass(), 0), BMI->isBaseVirtual());
12315f757f3fSDimitry Andric     SVal InitVal = State->getSVal(Init, stackFrame);
12325f757f3fSDimitry Andric     evalBind(Tmp, Init, Pred, BaseLoc, InitVal, /*isInit=*/true);
12330b57cec5SDimitry Andric   } else {
12340b57cec5SDimitry Andric     assert(BMI->isBaseInitializer() || BMI->isDelegatingInitializer());
12350b57cec5SDimitry Andric     Tmp.insert(Pred);
12360b57cec5SDimitry Andric     // We already did all the work when visiting the CXXConstructExpr.
12370b57cec5SDimitry Andric   }
12380b57cec5SDimitry Andric 
12390b57cec5SDimitry Andric   // Construct PostInitializer nodes whether the state changed or not,
12400b57cec5SDimitry Andric   // so that the diagnostics don't get confused.
12410b57cec5SDimitry Andric   PostInitializer PP(BMI, FieldLoc.getAsRegion(), stackFrame);
12420b57cec5SDimitry Andric   ExplodedNodeSet Dst;
12430b57cec5SDimitry Andric   NodeBuilder Bldr(Tmp, Dst, *currBldrCtx);
12440b57cec5SDimitry Andric   for (const auto I : Tmp) {
12450b57cec5SDimitry Andric     ProgramStateRef State = I->getState();
12460b57cec5SDimitry Andric     Bldr.generateNode(PP, State, I);
12470b57cec5SDimitry Andric   }
12480b57cec5SDimitry Andric 
12490b57cec5SDimitry Andric   // Enqueue the new nodes onto the work list.
12500b57cec5SDimitry Andric   Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
12510b57cec5SDimitry Andric }
12520b57cec5SDimitry Andric 
1253bdd1243dSDimitry Andric std::pair<ProgramStateRef, uint64_t>
prepareStateForArrayDestruction(const ProgramStateRef State,const MemRegion * Region,const QualType & ElementTy,const LocationContext * LCtx,SVal * ElementCountVal)1254bdd1243dSDimitry Andric ExprEngine::prepareStateForArrayDestruction(const ProgramStateRef State,
1255bdd1243dSDimitry Andric                                             const MemRegion *Region,
1256bdd1243dSDimitry Andric                                             const QualType &ElementTy,
1257bdd1243dSDimitry Andric                                             const LocationContext *LCtx,
1258bdd1243dSDimitry Andric                                             SVal *ElementCountVal) {
1259bdd1243dSDimitry Andric   assert(Region != nullptr && "Not-null region expected");
1260bdd1243dSDimitry Andric 
1261bdd1243dSDimitry Andric   QualType Ty = ElementTy.getDesugaredType(getContext());
1262bdd1243dSDimitry Andric   while (const auto *NTy = dyn_cast<ArrayType>(Ty))
1263bdd1243dSDimitry Andric     Ty = NTy->getElementType().getDesugaredType(getContext());
1264bdd1243dSDimitry Andric 
1265bdd1243dSDimitry Andric   auto ElementCount = getDynamicElementCount(State, Region, svalBuilder, Ty);
1266bdd1243dSDimitry Andric 
1267bdd1243dSDimitry Andric   if (ElementCountVal)
1268bdd1243dSDimitry Andric     *ElementCountVal = ElementCount;
1269bdd1243dSDimitry Andric 
1270bdd1243dSDimitry Andric   // Note: the destructors are called in reverse order.
1271bdd1243dSDimitry Andric   unsigned Idx = 0;
1272bdd1243dSDimitry Andric   if (auto OptionalIdx = getPendingArrayDestruction(State, LCtx)) {
1273bdd1243dSDimitry Andric     Idx = *OptionalIdx;
1274bdd1243dSDimitry Andric   } else {
1275bdd1243dSDimitry Andric     // The element count is either unknown, or an SVal that's not an integer.
1276bdd1243dSDimitry Andric     if (!ElementCount.isConstant())
1277bdd1243dSDimitry Andric       return {State, 0};
1278bdd1243dSDimitry Andric 
1279bdd1243dSDimitry Andric     Idx = ElementCount.getAsInteger()->getLimitedValue();
1280bdd1243dSDimitry Andric   }
1281bdd1243dSDimitry Andric 
1282bdd1243dSDimitry Andric   if (Idx == 0)
1283bdd1243dSDimitry Andric     return {State, 0};
1284bdd1243dSDimitry Andric 
1285bdd1243dSDimitry Andric   --Idx;
1286bdd1243dSDimitry Andric 
1287bdd1243dSDimitry Andric   return {setPendingArrayDestruction(State, LCtx, Idx), Idx};
1288bdd1243dSDimitry Andric }
1289bdd1243dSDimitry Andric 
ProcessImplicitDtor(const CFGImplicitDtor D,ExplodedNode * Pred)12900b57cec5SDimitry Andric void ExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D,
12910b57cec5SDimitry Andric                                      ExplodedNode *Pred) {
12920b57cec5SDimitry Andric   ExplodedNodeSet Dst;
12930b57cec5SDimitry Andric   switch (D.getKind()) {
12940b57cec5SDimitry Andric   case CFGElement::AutomaticObjectDtor:
12950b57cec5SDimitry Andric     ProcessAutomaticObjDtor(D.castAs<CFGAutomaticObjDtor>(), Pred, Dst);
12960b57cec5SDimitry Andric     break;
12970b57cec5SDimitry Andric   case CFGElement::BaseDtor:
12980b57cec5SDimitry Andric     ProcessBaseDtor(D.castAs<CFGBaseDtor>(), Pred, Dst);
12990b57cec5SDimitry Andric     break;
13000b57cec5SDimitry Andric   case CFGElement::MemberDtor:
13010b57cec5SDimitry Andric     ProcessMemberDtor(D.castAs<CFGMemberDtor>(), Pred, Dst);
13020b57cec5SDimitry Andric     break;
13030b57cec5SDimitry Andric   case CFGElement::TemporaryDtor:
13040b57cec5SDimitry Andric     ProcessTemporaryDtor(D.castAs<CFGTemporaryDtor>(), Pred, Dst);
13050b57cec5SDimitry Andric     break;
13060b57cec5SDimitry Andric   case CFGElement::DeleteDtor:
13070b57cec5SDimitry Andric     ProcessDeleteDtor(D.castAs<CFGDeleteDtor>(), Pred, Dst);
13080b57cec5SDimitry Andric     break;
13090b57cec5SDimitry Andric   default:
13100b57cec5SDimitry Andric     llvm_unreachable("Unexpected dtor kind.");
13110b57cec5SDimitry Andric   }
13120b57cec5SDimitry Andric 
13130b57cec5SDimitry Andric   // Enqueue the new nodes onto the work list.
13140b57cec5SDimitry Andric   Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
13150b57cec5SDimitry Andric }
13160b57cec5SDimitry Andric 
ProcessNewAllocator(const CXXNewExpr * NE,ExplodedNode * Pred)13170b57cec5SDimitry Andric void ExprEngine::ProcessNewAllocator(const CXXNewExpr *NE,
13180b57cec5SDimitry Andric                                      ExplodedNode *Pred) {
13190b57cec5SDimitry Andric   ExplodedNodeSet Dst;
13200b57cec5SDimitry Andric   AnalysisManager &AMgr = getAnalysisManager();
13210b57cec5SDimitry Andric   AnalyzerOptions &Opts = AMgr.options;
13220b57cec5SDimitry Andric   // TODO: We're not evaluating allocators for all cases just yet as
13230b57cec5SDimitry Andric   // we're not handling the return value correctly, which causes false
13240b57cec5SDimitry Andric   // positives when the alpha.cplusplus.NewDeleteLeaks check is on.
13250b57cec5SDimitry Andric   if (Opts.MayInlineCXXAllocator)
13260b57cec5SDimitry Andric     VisitCXXNewAllocatorCall(NE, Pred, Dst);
13270b57cec5SDimitry Andric   else {
13280b57cec5SDimitry Andric     NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
13290b57cec5SDimitry Andric     const LocationContext *LCtx = Pred->getLocationContext();
133006c3fb27SDimitry Andric     PostImplicitCall PP(NE->getOperatorNew(), NE->getBeginLoc(), LCtx,
133106c3fb27SDimitry Andric                         getCFGElementRef());
13320b57cec5SDimitry Andric     Bldr.generateNode(PP, Pred->getState(), Pred);
13330b57cec5SDimitry Andric   }
13340b57cec5SDimitry Andric   Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
13350b57cec5SDimitry Andric }
13360b57cec5SDimitry Andric 
ProcessAutomaticObjDtor(const CFGAutomaticObjDtor Dtor,ExplodedNode * Pred,ExplodedNodeSet & Dst)13370b57cec5SDimitry Andric void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor Dtor,
13380b57cec5SDimitry Andric                                          ExplodedNode *Pred,
13390b57cec5SDimitry Andric                                          ExplodedNodeSet &Dst) {
1340bdd1243dSDimitry Andric   const auto *DtorDecl = Dtor.getDestructorDecl(getContext());
13410b57cec5SDimitry Andric   const VarDecl *varDecl = Dtor.getVarDecl();
13420b57cec5SDimitry Andric   QualType varType = varDecl->getType();
13430b57cec5SDimitry Andric 
13440b57cec5SDimitry Andric   ProgramStateRef state = Pred->getState();
1345bdd1243dSDimitry Andric   const LocationContext *LCtx = Pred->getLocationContext();
1346bdd1243dSDimitry Andric 
1347bdd1243dSDimitry Andric   SVal dest = state->getLValue(varDecl, LCtx);
13480b57cec5SDimitry Andric   const MemRegion *Region = dest.castAs<loc::MemRegionVal>().getRegion();
13490b57cec5SDimitry Andric 
13500b57cec5SDimitry Andric   if (varType->isReferenceType()) {
13510b57cec5SDimitry Andric     const MemRegion *ValueRegion = state->getSVal(Region).getAsRegion();
13520b57cec5SDimitry Andric     if (!ValueRegion) {
13530b57cec5SDimitry Andric       // FIXME: This should not happen. The language guarantees a presence
13540b57cec5SDimitry Andric       // of a valid initializer here, so the reference shall not be undefined.
13550b57cec5SDimitry Andric       // It seems that we're calling destructors over variables that
13560b57cec5SDimitry Andric       // were not initialized yet.
13570b57cec5SDimitry Andric       return;
13580b57cec5SDimitry Andric     }
13590b57cec5SDimitry Andric     Region = ValueRegion->getBaseRegion();
13600b57cec5SDimitry Andric     varType = cast<TypedValueRegion>(Region)->getValueType();
13610b57cec5SDimitry Andric   }
13620b57cec5SDimitry Andric 
1363bdd1243dSDimitry Andric   unsigned Idx = 0;
1364bdd1243dSDimitry Andric   if (isa<ArrayType>(varType)) {
1365bdd1243dSDimitry Andric     SVal ElementCount;
1366bdd1243dSDimitry Andric     std::tie(state, Idx) = prepareStateForArrayDestruction(
1367bdd1243dSDimitry Andric         state, Region, varType, LCtx, &ElementCount);
1368bdd1243dSDimitry Andric 
1369bdd1243dSDimitry Andric     if (ElementCount.isConstant()) {
1370bdd1243dSDimitry Andric       uint64_t ArrayLength = ElementCount.getAsInteger()->getLimitedValue();
1371bdd1243dSDimitry Andric       assert(ArrayLength &&
1372bdd1243dSDimitry Andric              "An automatic dtor for a 0 length array shouldn't be triggered!");
1373bdd1243dSDimitry Andric 
1374bdd1243dSDimitry Andric       // Still handle this case if we don't have assertions enabled.
1375bdd1243dSDimitry Andric       if (!ArrayLength) {
1376bdd1243dSDimitry Andric         static SimpleProgramPointTag PT(
1377bdd1243dSDimitry Andric             "ExprEngine", "Skipping automatic 0 length array destruction, "
1378bdd1243dSDimitry Andric                           "which shouldn't be in the CFG.");
137906c3fb27SDimitry Andric         PostImplicitCall PP(DtorDecl, varDecl->getLocation(), LCtx,
138006c3fb27SDimitry Andric                             getCFGElementRef(), &PT);
1381bdd1243dSDimitry Andric         NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1382bdd1243dSDimitry Andric         Bldr.generateSink(PP, Pred->getState(), Pred);
1383bdd1243dSDimitry Andric         return;
1384bdd1243dSDimitry Andric       }
1385bdd1243dSDimitry Andric     }
1386bdd1243dSDimitry Andric   }
1387bdd1243dSDimitry Andric 
13880b57cec5SDimitry Andric   EvalCallOptions CallOpts;
1389fcaf7f86SDimitry Andric   Region = makeElementRegion(state, loc::MemRegionVal(Region), varType,
1390bdd1243dSDimitry Andric                              CallOpts.IsArrayCtorOrDtor, Idx)
1391fcaf7f86SDimitry Andric                .getAsRegion();
13920b57cec5SDimitry Andric 
1393bdd1243dSDimitry Andric   NodeBuilder Bldr(Pred, Dst, getBuilderContext());
1394bdd1243dSDimitry Andric 
1395bdd1243dSDimitry Andric   static SimpleProgramPointTag PT("ExprEngine",
1396bdd1243dSDimitry Andric                                   "Prepare for object destruction");
139706c3fb27SDimitry Andric   PreImplicitCall PP(DtorDecl, varDecl->getLocation(), LCtx, getCFGElementRef(),
139806c3fb27SDimitry Andric                      &PT);
1399bdd1243dSDimitry Andric   Pred = Bldr.generateNode(PP, state, Pred);
1400bdd1243dSDimitry Andric 
1401bdd1243dSDimitry Andric   if (!Pred)
1402bdd1243dSDimitry Andric     return;
1403bdd1243dSDimitry Andric   Bldr.takeNodes(Pred);
1404bdd1243dSDimitry Andric 
1405a7dea167SDimitry Andric   VisitCXXDestructor(varType, Region, Dtor.getTriggerStmt(),
1406a7dea167SDimitry Andric                      /*IsBase=*/false, Pred, Dst, CallOpts);
14070b57cec5SDimitry Andric }
14080b57cec5SDimitry Andric 
ProcessDeleteDtor(const CFGDeleteDtor Dtor,ExplodedNode * Pred,ExplodedNodeSet & Dst)14090b57cec5SDimitry Andric void ExprEngine::ProcessDeleteDtor(const CFGDeleteDtor Dtor,
14100b57cec5SDimitry Andric                                    ExplodedNode *Pred,
14110b57cec5SDimitry Andric                                    ExplodedNodeSet &Dst) {
14120b57cec5SDimitry Andric   ProgramStateRef State = Pred->getState();
14130b57cec5SDimitry Andric   const LocationContext *LCtx = Pred->getLocationContext();
14140b57cec5SDimitry Andric   const CXXDeleteExpr *DE = Dtor.getDeleteExpr();
14150b57cec5SDimitry Andric   const Stmt *Arg = DE->getArgument();
14160b57cec5SDimitry Andric   QualType DTy = DE->getDestroyedType();
14170b57cec5SDimitry Andric   SVal ArgVal = State->getSVal(Arg, LCtx);
14180b57cec5SDimitry Andric 
14190b57cec5SDimitry Andric   // If the argument to delete is known to be a null value,
14200b57cec5SDimitry Andric   // don't run destructor.
14210b57cec5SDimitry Andric   if (State->isNull(ArgVal).isConstrainedTrue()) {
14220b57cec5SDimitry Andric     QualType BTy = getContext().getBaseElementType(DTy);
14230b57cec5SDimitry Andric     const CXXRecordDecl *RD = BTy->getAsCXXRecordDecl();
14240b57cec5SDimitry Andric     const CXXDestructorDecl *Dtor = RD->getDestructor();
14250b57cec5SDimitry Andric 
142606c3fb27SDimitry Andric     PostImplicitCall PP(Dtor, DE->getBeginLoc(), LCtx, getCFGElementRef());
14270b57cec5SDimitry Andric     NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
14280b57cec5SDimitry Andric     Bldr.generateNode(PP, Pred->getState(), Pred);
14290b57cec5SDimitry Andric     return;
14300b57cec5SDimitry Andric   }
14310b57cec5SDimitry Andric 
1432bdd1243dSDimitry Andric   auto getDtorDecl = [](const QualType &DTy) {
1433bdd1243dSDimitry Andric     const CXXRecordDecl *RD = DTy->getAsCXXRecordDecl();
1434bdd1243dSDimitry Andric     return RD->getDestructor();
1435bdd1243dSDimitry Andric   };
1436bdd1243dSDimitry Andric 
1437bdd1243dSDimitry Andric   unsigned Idx = 0;
14380b57cec5SDimitry Andric   EvalCallOptions CallOpts;
14390b57cec5SDimitry Andric   const MemRegion *ArgR = ArgVal.getAsRegion();
1440bdd1243dSDimitry Andric 
14410b57cec5SDimitry Andric   if (DE->isArrayForm()) {
14420b57cec5SDimitry Andric     CallOpts.IsArrayCtorOrDtor = true;
14430b57cec5SDimitry Andric     // Yes, it may even be a multi-dimensional array.
14440b57cec5SDimitry Andric     while (const auto *AT = getContext().getAsArrayType(DTy))
14450b57cec5SDimitry Andric       DTy = AT->getElementType();
1446bdd1243dSDimitry Andric 
1447bdd1243dSDimitry Andric     if (ArgR) {
1448bdd1243dSDimitry Andric       SVal ElementCount;
1449bdd1243dSDimitry Andric       std::tie(State, Idx) = prepareStateForArrayDestruction(
1450bdd1243dSDimitry Andric           State, ArgR, DTy, LCtx, &ElementCount);
1451bdd1243dSDimitry Andric 
1452bdd1243dSDimitry Andric       // If we're about to destruct a 0 length array, don't run any of the
1453bdd1243dSDimitry Andric       // destructors.
1454bdd1243dSDimitry Andric       if (ElementCount.isConstant() &&
1455bdd1243dSDimitry Andric           ElementCount.getAsInteger()->getLimitedValue() == 0) {
1456bdd1243dSDimitry Andric 
1457bdd1243dSDimitry Andric         static SimpleProgramPointTag PT(
1458bdd1243dSDimitry Andric             "ExprEngine", "Skipping 0 length array delete destruction");
145906c3fb27SDimitry Andric         PostImplicitCall PP(getDtorDecl(DTy), DE->getBeginLoc(), LCtx,
146006c3fb27SDimitry Andric                             getCFGElementRef(), &PT);
1461bdd1243dSDimitry Andric         NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1462bdd1243dSDimitry Andric         Bldr.generateNode(PP, Pred->getState(), Pred);
1463bdd1243dSDimitry Andric         return;
14640b57cec5SDimitry Andric       }
14650b57cec5SDimitry Andric 
1466bdd1243dSDimitry Andric       ArgR = State->getLValue(DTy, svalBuilder.makeArrayIndex(Idx), ArgVal)
1467bdd1243dSDimitry Andric                  .getAsRegion();
1468bdd1243dSDimitry Andric     }
1469bdd1243dSDimitry Andric   }
1470bdd1243dSDimitry Andric 
1471bdd1243dSDimitry Andric   NodeBuilder Bldr(Pred, Dst, getBuilderContext());
1472bdd1243dSDimitry Andric   static SimpleProgramPointTag PT("ExprEngine",
1473bdd1243dSDimitry Andric                                   "Prepare for object destruction");
147406c3fb27SDimitry Andric   PreImplicitCall PP(getDtorDecl(DTy), DE->getBeginLoc(), LCtx,
147506c3fb27SDimitry Andric                      getCFGElementRef(), &PT);
1476bdd1243dSDimitry Andric   Pred = Bldr.generateNode(PP, State, Pred);
1477bdd1243dSDimitry Andric 
1478bdd1243dSDimitry Andric   if (!Pred)
1479bdd1243dSDimitry Andric     return;
1480bdd1243dSDimitry Andric   Bldr.takeNodes(Pred);
1481bdd1243dSDimitry Andric 
14820b57cec5SDimitry Andric   VisitCXXDestructor(DTy, ArgR, DE, /*IsBase=*/false, Pred, Dst, CallOpts);
14830b57cec5SDimitry Andric }
14840b57cec5SDimitry Andric 
ProcessBaseDtor(const CFGBaseDtor D,ExplodedNode * Pred,ExplodedNodeSet & Dst)14850b57cec5SDimitry Andric void ExprEngine::ProcessBaseDtor(const CFGBaseDtor D,
14860b57cec5SDimitry Andric                                  ExplodedNode *Pred, ExplodedNodeSet &Dst) {
14870b57cec5SDimitry Andric   const LocationContext *LCtx = Pred->getLocationContext();
14880b57cec5SDimitry Andric 
14890b57cec5SDimitry Andric   const auto *CurDtor = cast<CXXDestructorDecl>(LCtx->getDecl());
14900b57cec5SDimitry Andric   Loc ThisPtr = getSValBuilder().getCXXThis(CurDtor,
14910b57cec5SDimitry Andric                                             LCtx->getStackFrame());
14920b57cec5SDimitry Andric   SVal ThisVal = Pred->getState()->getSVal(ThisPtr);
14930b57cec5SDimitry Andric 
14940b57cec5SDimitry Andric   // Create the base object region.
14950b57cec5SDimitry Andric   const CXXBaseSpecifier *Base = D.getBaseSpecifier();
14960b57cec5SDimitry Andric   QualType BaseTy = Base->getType();
14970b57cec5SDimitry Andric   SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, BaseTy,
14980b57cec5SDimitry Andric                                                      Base->isVirtual());
14990b57cec5SDimitry Andric 
1500a7dea167SDimitry Andric   EvalCallOptions CallOpts;
1501a7dea167SDimitry Andric   VisitCXXDestructor(BaseTy, BaseVal.getAsRegion(), CurDtor->getBody(),
1502a7dea167SDimitry Andric                      /*IsBase=*/true, Pred, Dst, CallOpts);
15030b57cec5SDimitry Andric }
15040b57cec5SDimitry Andric 
ProcessMemberDtor(const CFGMemberDtor D,ExplodedNode * Pred,ExplodedNodeSet & Dst)15050b57cec5SDimitry Andric void ExprEngine::ProcessMemberDtor(const CFGMemberDtor D,
15060b57cec5SDimitry Andric                                    ExplodedNode *Pred, ExplodedNodeSet &Dst) {
1507bdd1243dSDimitry Andric   const auto *DtorDecl = D.getDestructorDecl(getContext());
15080b57cec5SDimitry Andric   const FieldDecl *Member = D.getFieldDecl();
15090b57cec5SDimitry Andric   QualType T = Member->getType();
15100b57cec5SDimitry Andric   ProgramStateRef State = Pred->getState();
15110b57cec5SDimitry Andric   const LocationContext *LCtx = Pred->getLocationContext();
15120b57cec5SDimitry Andric 
15130b57cec5SDimitry Andric   const auto *CurDtor = cast<CXXDestructorDecl>(LCtx->getDecl());
1514a7dea167SDimitry Andric   Loc ThisStorageLoc =
1515a7dea167SDimitry Andric       getSValBuilder().getCXXThis(CurDtor, LCtx->getStackFrame());
1516a7dea167SDimitry Andric   Loc ThisLoc = State->getSVal(ThisStorageLoc).castAs<Loc>();
1517a7dea167SDimitry Andric   SVal FieldVal = State->getLValue(Member, ThisLoc);
15180b57cec5SDimitry Andric 
1519bdd1243dSDimitry Andric   unsigned Idx = 0;
1520bdd1243dSDimitry Andric   if (isa<ArrayType>(T)) {
1521bdd1243dSDimitry Andric     SVal ElementCount;
1522bdd1243dSDimitry Andric     std::tie(State, Idx) = prepareStateForArrayDestruction(
1523bdd1243dSDimitry Andric         State, FieldVal.getAsRegion(), T, LCtx, &ElementCount);
1524bdd1243dSDimitry Andric 
1525bdd1243dSDimitry Andric     if (ElementCount.isConstant()) {
1526bdd1243dSDimitry Andric       uint64_t ArrayLength = ElementCount.getAsInteger()->getLimitedValue();
1527bdd1243dSDimitry Andric       assert(ArrayLength &&
1528bdd1243dSDimitry Andric              "A member dtor for a 0 length array shouldn't be triggered!");
1529bdd1243dSDimitry Andric 
1530bdd1243dSDimitry Andric       // Still handle this case if we don't have assertions enabled.
1531bdd1243dSDimitry Andric       if (!ArrayLength) {
1532bdd1243dSDimitry Andric         static SimpleProgramPointTag PT(
1533bdd1243dSDimitry Andric             "ExprEngine", "Skipping member 0 length array destruction, which "
1534bdd1243dSDimitry Andric                           "shouldn't be in the CFG.");
153506c3fb27SDimitry Andric         PostImplicitCall PP(DtorDecl, Member->getLocation(), LCtx,
153606c3fb27SDimitry Andric                             getCFGElementRef(), &PT);
1537bdd1243dSDimitry Andric         NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
1538bdd1243dSDimitry Andric         Bldr.generateSink(PP, Pred->getState(), Pred);
1539bdd1243dSDimitry Andric         return;
1540bdd1243dSDimitry Andric       }
1541bdd1243dSDimitry Andric     }
1542bdd1243dSDimitry Andric   }
1543bdd1243dSDimitry Andric 
15440b57cec5SDimitry Andric   EvalCallOptions CallOpts;
1545bdd1243dSDimitry Andric   FieldVal =
1546bdd1243dSDimitry Andric       makeElementRegion(State, FieldVal, T, CallOpts.IsArrayCtorOrDtor, Idx);
1547bdd1243dSDimitry Andric 
1548bdd1243dSDimitry Andric   NodeBuilder Bldr(Pred, Dst, getBuilderContext());
1549bdd1243dSDimitry Andric 
1550bdd1243dSDimitry Andric   static SimpleProgramPointTag PT("ExprEngine",
1551bdd1243dSDimitry Andric                                   "Prepare for object destruction");
155206c3fb27SDimitry Andric   PreImplicitCall PP(DtorDecl, Member->getLocation(), LCtx, getCFGElementRef(),
155306c3fb27SDimitry Andric                      &PT);
1554bdd1243dSDimitry Andric   Pred = Bldr.generateNode(PP, State, Pred);
1555bdd1243dSDimitry Andric 
1556bdd1243dSDimitry Andric   if (!Pred)
1557bdd1243dSDimitry Andric     return;
1558bdd1243dSDimitry Andric   Bldr.takeNodes(Pred);
15590b57cec5SDimitry Andric 
1560a7dea167SDimitry Andric   VisitCXXDestructor(T, FieldVal.getAsRegion(), CurDtor->getBody(),
1561a7dea167SDimitry Andric                      /*IsBase=*/false, Pred, Dst, CallOpts);
15620b57cec5SDimitry Andric }
15630b57cec5SDimitry Andric 
ProcessTemporaryDtor(const CFGTemporaryDtor D,ExplodedNode * Pred,ExplodedNodeSet & Dst)15640b57cec5SDimitry Andric void ExprEngine::ProcessTemporaryDtor(const CFGTemporaryDtor D,
15650b57cec5SDimitry Andric                                       ExplodedNode *Pred,
15660b57cec5SDimitry Andric                                       ExplodedNodeSet &Dst) {
15670b57cec5SDimitry Andric   const CXXBindTemporaryExpr *BTE = D.getBindTemporaryExpr();
15680b57cec5SDimitry Andric   ProgramStateRef State = Pred->getState();
15690b57cec5SDimitry Andric   const LocationContext *LC = Pred->getLocationContext();
15700b57cec5SDimitry Andric   const MemRegion *MR = nullptr;
15710b57cec5SDimitry Andric 
1572bdd1243dSDimitry Andric   if (std::optional<SVal> V = getObjectUnderConstruction(
1573bdd1243dSDimitry Andric           State, D.getBindTemporaryExpr(), Pred->getLocationContext())) {
15740b57cec5SDimitry Andric     // FIXME: Currently we insert temporary destructors for default parameters,
15750b57cec5SDimitry Andric     // but we don't insert the constructors, so the entry in
15760b57cec5SDimitry Andric     // ObjectsUnderConstruction may be missing.
15770b57cec5SDimitry Andric     State = finishObjectConstruction(State, D.getBindTemporaryExpr(),
15780b57cec5SDimitry Andric                                      Pred->getLocationContext());
15790b57cec5SDimitry Andric     MR = V->getAsRegion();
15800b57cec5SDimitry Andric   }
15810b57cec5SDimitry Andric 
15820b57cec5SDimitry Andric   // If copy elision has occurred, and the constructor corresponding to the
15830b57cec5SDimitry Andric   // destructor was elided, we need to skip the destructor as well.
15840b57cec5SDimitry Andric   if (isDestructorElided(State, BTE, LC)) {
15850b57cec5SDimitry Andric     State = cleanupElidedDestructor(State, BTE, LC);
15860b57cec5SDimitry Andric     NodeBuilder Bldr(Pred, Dst, *currBldrCtx);
15870b57cec5SDimitry Andric     PostImplicitCall PP(D.getDestructorDecl(getContext()),
15880b57cec5SDimitry Andric                         D.getBindTemporaryExpr()->getBeginLoc(),
158906c3fb27SDimitry Andric                         Pred->getLocationContext(), getCFGElementRef());
15900b57cec5SDimitry Andric     Bldr.generateNode(PP, State, Pred);
15910b57cec5SDimitry Andric     return;
15920b57cec5SDimitry Andric   }
15930b57cec5SDimitry Andric 
15940b57cec5SDimitry Andric   ExplodedNodeSet CleanDtorState;
15950b57cec5SDimitry Andric   StmtNodeBuilder StmtBldr(Pred, CleanDtorState, *currBldrCtx);
15960b57cec5SDimitry Andric   StmtBldr.generateNode(D.getBindTemporaryExpr(), Pred, State);
15970b57cec5SDimitry Andric 
15980b57cec5SDimitry Andric   QualType T = D.getBindTemporaryExpr()->getSubExpr()->getType();
15990b57cec5SDimitry Andric   // FIXME: Currently CleanDtorState can be empty here due to temporaries being
16000b57cec5SDimitry Andric   // bound to default parameters.
16010b57cec5SDimitry Andric   assert(CleanDtorState.size() <= 1);
16020b57cec5SDimitry Andric   ExplodedNode *CleanPred =
16030b57cec5SDimitry Andric       CleanDtorState.empty() ? Pred : *CleanDtorState.begin();
16040b57cec5SDimitry Andric 
16050b57cec5SDimitry Andric   EvalCallOptions CallOpts;
16060b57cec5SDimitry Andric   CallOpts.IsTemporaryCtorOrDtor = true;
16070b57cec5SDimitry Andric   if (!MR) {
1608bdd1243dSDimitry Andric     // FIXME: If we have no MR, we still need to unwrap the array to avoid
1609bdd1243dSDimitry Andric     // destroying the whole array at once.
1610bdd1243dSDimitry Andric     //
1611bdd1243dSDimitry Andric     // For this case there is no universal solution as there is no way to
1612bdd1243dSDimitry Andric     // directly create an array of temporary objects. There are some expressions
1613bdd1243dSDimitry Andric     // however which can create temporary objects and have an array type.
1614bdd1243dSDimitry Andric     //
1615bdd1243dSDimitry Andric     // E.g.: std::initializer_list<S>{S(), S()};
1616bdd1243dSDimitry Andric     //
1617bdd1243dSDimitry Andric     // The expression above has a type of 'const struct S[2]' but it's a single
1618bdd1243dSDimitry Andric     // 'std::initializer_list<>'. The destructors of the 2 temporary 'S()'
1619bdd1243dSDimitry Andric     // objects will be called anyway, because they are 2 separate objects in 2
1620bdd1243dSDimitry Andric     // separate clusters, i.e.: not an array.
1621bdd1243dSDimitry Andric     //
1622bdd1243dSDimitry Andric     // Now the 'std::initializer_list<>' is not an array either even though it
1623bdd1243dSDimitry Andric     // has the type of an array. The point is, we only want to invoke the
1624bdd1243dSDimitry Andric     // destructor for the initializer list once not twice or so.
16250b57cec5SDimitry Andric     while (const ArrayType *AT = getContext().getAsArrayType(T)) {
16260b57cec5SDimitry Andric       T = AT->getElementType();
1627bdd1243dSDimitry Andric 
1628bdd1243dSDimitry Andric       // FIXME: Enable this flag once we handle this case properly.
1629bdd1243dSDimitry Andric       // CallOpts.IsArrayCtorOrDtor = true;
16300b57cec5SDimitry Andric     }
16310b57cec5SDimitry Andric   } else {
1632bdd1243dSDimitry Andric     // FIXME: We'd eventually need to makeElementRegion() trick here,
16330b57cec5SDimitry Andric     // but for now we don't have the respective construction contexts,
16340b57cec5SDimitry Andric     // so MR would always be null in this case. Do nothing for now.
16350b57cec5SDimitry Andric   }
16360b57cec5SDimitry Andric   VisitCXXDestructor(T, MR, D.getBindTemporaryExpr(),
16370b57cec5SDimitry Andric                      /*IsBase=*/false, CleanPred, Dst, CallOpts);
16380b57cec5SDimitry Andric }
16390b57cec5SDimitry Andric 
processCleanupTemporaryBranch(const CXXBindTemporaryExpr * BTE,NodeBuilderContext & BldCtx,ExplodedNode * Pred,ExplodedNodeSet & Dst,const CFGBlock * DstT,const CFGBlock * DstF)16400b57cec5SDimitry Andric void ExprEngine::processCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE,
16410b57cec5SDimitry Andric                                                NodeBuilderContext &BldCtx,
16420b57cec5SDimitry Andric                                                ExplodedNode *Pred,
16430b57cec5SDimitry Andric                                                ExplodedNodeSet &Dst,
16440b57cec5SDimitry Andric                                                const CFGBlock *DstT,
16450b57cec5SDimitry Andric                                                const CFGBlock *DstF) {
16460b57cec5SDimitry Andric   BranchNodeBuilder TempDtorBuilder(Pred, Dst, BldCtx, DstT, DstF);
16470b57cec5SDimitry Andric   ProgramStateRef State = Pred->getState();
16480b57cec5SDimitry Andric   const LocationContext *LC = Pred->getLocationContext();
16490b57cec5SDimitry Andric   if (getObjectUnderConstruction(State, BTE, LC)) {
16500b57cec5SDimitry Andric     TempDtorBuilder.markInfeasible(false);
16510b57cec5SDimitry Andric     TempDtorBuilder.generateNode(State, true, Pred);
16520b57cec5SDimitry Andric   } else {
16530b57cec5SDimitry Andric     TempDtorBuilder.markInfeasible(true);
16540b57cec5SDimitry Andric     TempDtorBuilder.generateNode(State, false, Pred);
16550b57cec5SDimitry Andric   }
16560b57cec5SDimitry Andric }
16570b57cec5SDimitry Andric 
VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr * BTE,ExplodedNodeSet & PreVisit,ExplodedNodeSet & Dst)16580b57cec5SDimitry Andric void ExprEngine::VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE,
16590b57cec5SDimitry Andric                                            ExplodedNodeSet &PreVisit,
16600b57cec5SDimitry Andric                                            ExplodedNodeSet &Dst) {
16610b57cec5SDimitry Andric   // This is a fallback solution in case we didn't have a construction
16620b57cec5SDimitry Andric   // context when we were constructing the temporary. Otherwise the map should
16630b57cec5SDimitry Andric   // have been populated there.
16640b57cec5SDimitry Andric   if (!getAnalysisManager().options.ShouldIncludeTemporaryDtorsInCFG) {
16650b57cec5SDimitry Andric     // In case we don't have temporary destructors in the CFG, do not mark
16660b57cec5SDimitry Andric     // the initialization - we would otherwise never clean it up.
16670b57cec5SDimitry Andric     Dst = PreVisit;
16680b57cec5SDimitry Andric     return;
16690b57cec5SDimitry Andric   }
16700b57cec5SDimitry Andric   StmtNodeBuilder StmtBldr(PreVisit, Dst, *currBldrCtx);
16710b57cec5SDimitry Andric   for (ExplodedNode *Node : PreVisit) {
16720b57cec5SDimitry Andric     ProgramStateRef State = Node->getState();
16730b57cec5SDimitry Andric     const LocationContext *LC = Node->getLocationContext();
16740b57cec5SDimitry Andric     if (!getObjectUnderConstruction(State, BTE, LC)) {
16750b57cec5SDimitry Andric       // FIXME: Currently the state might also already contain the marker due to
16760b57cec5SDimitry Andric       // incorrect handling of temporaries bound to default parameters; for
16770b57cec5SDimitry Andric       // those, we currently skip the CXXBindTemporaryExpr but rely on adding
16780b57cec5SDimitry Andric       // temporary destructor nodes.
16790b57cec5SDimitry Andric       State = addObjectUnderConstruction(State, BTE, LC, UnknownVal());
16800b57cec5SDimitry Andric     }
16810b57cec5SDimitry Andric     StmtBldr.generateNode(BTE, Node, State);
16820b57cec5SDimitry Andric   }
16830b57cec5SDimitry Andric }
16840b57cec5SDimitry Andric 
escapeValues(ProgramStateRef State,ArrayRef<SVal> Vs,PointerEscapeKind K,const CallEvent * Call) const1685480093f4SDimitry Andric ProgramStateRef ExprEngine::escapeValues(ProgramStateRef State,
1686480093f4SDimitry Andric                                          ArrayRef<SVal> Vs,
1687480093f4SDimitry Andric                                          PointerEscapeKind K,
1688480093f4SDimitry Andric                                          const CallEvent *Call) const {
16890b57cec5SDimitry Andric   class CollectReachableSymbolsCallback final : public SymbolVisitor {
1690480093f4SDimitry Andric     InvalidatedSymbols &Symbols;
16910b57cec5SDimitry Andric 
16920b57cec5SDimitry Andric   public:
1693480093f4SDimitry Andric     explicit CollectReachableSymbolsCallback(InvalidatedSymbols &Symbols)
1694480093f4SDimitry Andric         : Symbols(Symbols) {}
16950b57cec5SDimitry Andric 
16960b57cec5SDimitry Andric     const InvalidatedSymbols &getSymbols() const { return Symbols; }
16970b57cec5SDimitry Andric 
16980b57cec5SDimitry Andric     bool VisitSymbol(SymbolRef Sym) override {
16990b57cec5SDimitry Andric       Symbols.insert(Sym);
17000b57cec5SDimitry Andric       return true;
17010b57cec5SDimitry Andric     }
17020b57cec5SDimitry Andric   };
1703480093f4SDimitry Andric   InvalidatedSymbols Symbols;
1704480093f4SDimitry Andric   CollectReachableSymbolsCallback CallBack(Symbols);
1705480093f4SDimitry Andric   for (SVal V : Vs)
1706480093f4SDimitry Andric     State->scanReachableSymbols(V, CallBack);
17070b57cec5SDimitry Andric 
17080b57cec5SDimitry Andric   return getCheckerManager().runCheckersForPointerEscape(
1709480093f4SDimitry Andric       State, CallBack.getSymbols(), Call, K, nullptr);
17100b57cec5SDimitry Andric }
17110b57cec5SDimitry Andric 
Visit(const Stmt * S,ExplodedNode * Pred,ExplodedNodeSet & DstTop)17120b57cec5SDimitry Andric void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
17130b57cec5SDimitry Andric                        ExplodedNodeSet &DstTop) {
17140b57cec5SDimitry Andric   PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
17150b57cec5SDimitry Andric                                 S->getBeginLoc(), "Error evaluating statement");
17160b57cec5SDimitry Andric   ExplodedNodeSet Dst;
17170b57cec5SDimitry Andric   StmtNodeBuilder Bldr(Pred, DstTop, *currBldrCtx);
17180b57cec5SDimitry Andric 
17190b57cec5SDimitry Andric   assert(!isa<Expr>(S) || S == cast<Expr>(S)->IgnoreParens());
17200b57cec5SDimitry Andric 
17210b57cec5SDimitry Andric   switch (S->getStmtClass()) {
17220b57cec5SDimitry Andric     // C++, OpenMP and ARC stuff we don't support yet.
17230b57cec5SDimitry Andric     case Stmt::CXXDependentScopeMemberExprClass:
17240b57cec5SDimitry Andric     case Stmt::CXXTryStmtClass:
17250b57cec5SDimitry Andric     case Stmt::CXXTypeidExprClass:
17260b57cec5SDimitry Andric     case Stmt::CXXUuidofExprClass:
17270b57cec5SDimitry Andric     case Stmt::CXXFoldExprClass:
17280b57cec5SDimitry Andric     case Stmt::MSPropertyRefExprClass:
17290b57cec5SDimitry Andric     case Stmt::MSPropertySubscriptExprClass:
17300b57cec5SDimitry Andric     case Stmt::CXXUnresolvedConstructExprClass:
17310b57cec5SDimitry Andric     case Stmt::DependentScopeDeclRefExprClass:
17320b57cec5SDimitry Andric     case Stmt::ArrayTypeTraitExprClass:
17330b57cec5SDimitry Andric     case Stmt::ExpressionTraitExprClass:
17340b57cec5SDimitry Andric     case Stmt::UnresolvedLookupExprClass:
17350b57cec5SDimitry Andric     case Stmt::UnresolvedMemberExprClass:
17360b57cec5SDimitry Andric     case Stmt::TypoExprClass:
17375ffd83dbSDimitry Andric     case Stmt::RecoveryExprClass:
17380b57cec5SDimitry Andric     case Stmt::CXXNoexceptExprClass:
17390b57cec5SDimitry Andric     case Stmt::PackExpansionExprClass:
17400b57cec5SDimitry Andric     case Stmt::SubstNonTypeTemplateParmPackExprClass:
17410b57cec5SDimitry Andric     case Stmt::FunctionParmPackExprClass:
17420b57cec5SDimitry Andric     case Stmt::CoroutineBodyStmtClass:
17430b57cec5SDimitry Andric     case Stmt::CoawaitExprClass:
17440b57cec5SDimitry Andric     case Stmt::DependentCoawaitExprClass:
17450b57cec5SDimitry Andric     case Stmt::CoreturnStmtClass:
17460b57cec5SDimitry Andric     case Stmt::CoyieldExprClass:
17470b57cec5SDimitry Andric     case Stmt::SEHTryStmtClass:
17480b57cec5SDimitry Andric     case Stmt::SEHExceptStmtClass:
17490b57cec5SDimitry Andric     case Stmt::SEHLeaveStmtClass:
17500b57cec5SDimitry Andric     case Stmt::SEHFinallyStmtClass:
1751fe6060f1SDimitry Andric     case Stmt::OMPCanonicalLoopClass:
17520b57cec5SDimitry Andric     case Stmt::OMPParallelDirectiveClass:
17530b57cec5SDimitry Andric     case Stmt::OMPSimdDirectiveClass:
17540b57cec5SDimitry Andric     case Stmt::OMPForDirectiveClass:
17550b57cec5SDimitry Andric     case Stmt::OMPForSimdDirectiveClass:
17560b57cec5SDimitry Andric     case Stmt::OMPSectionsDirectiveClass:
17570b57cec5SDimitry Andric     case Stmt::OMPSectionDirectiveClass:
17585f757f3fSDimitry Andric     case Stmt::OMPScopeDirectiveClass:
17590b57cec5SDimitry Andric     case Stmt::OMPSingleDirectiveClass:
17600b57cec5SDimitry Andric     case Stmt::OMPMasterDirectiveClass:
17610b57cec5SDimitry Andric     case Stmt::OMPCriticalDirectiveClass:
17620b57cec5SDimitry Andric     case Stmt::OMPParallelForDirectiveClass:
17630b57cec5SDimitry Andric     case Stmt::OMPParallelForSimdDirectiveClass:
17640b57cec5SDimitry Andric     case Stmt::OMPParallelSectionsDirectiveClass:
1765480093f4SDimitry Andric     case Stmt::OMPParallelMasterDirectiveClass:
176681ad6265SDimitry Andric     case Stmt::OMPParallelMaskedDirectiveClass:
17670b57cec5SDimitry Andric     case Stmt::OMPTaskDirectiveClass:
17680b57cec5SDimitry Andric     case Stmt::OMPTaskyieldDirectiveClass:
17690b57cec5SDimitry Andric     case Stmt::OMPBarrierDirectiveClass:
17700b57cec5SDimitry Andric     case Stmt::OMPTaskwaitDirectiveClass:
1771bdd1243dSDimitry Andric     case Stmt::OMPErrorDirectiveClass:
17720b57cec5SDimitry Andric     case Stmt::OMPTaskgroupDirectiveClass:
17730b57cec5SDimitry Andric     case Stmt::OMPFlushDirectiveClass:
17745ffd83dbSDimitry Andric     case Stmt::OMPDepobjDirectiveClass:
17755ffd83dbSDimitry Andric     case Stmt::OMPScanDirectiveClass:
17760b57cec5SDimitry Andric     case Stmt::OMPOrderedDirectiveClass:
17770b57cec5SDimitry Andric     case Stmt::OMPAtomicDirectiveClass:
17780b57cec5SDimitry Andric     case Stmt::OMPTargetDirectiveClass:
17790b57cec5SDimitry Andric     case Stmt::OMPTargetDataDirectiveClass:
17800b57cec5SDimitry Andric     case Stmt::OMPTargetEnterDataDirectiveClass:
17810b57cec5SDimitry Andric     case Stmt::OMPTargetExitDataDirectiveClass:
17820b57cec5SDimitry Andric     case Stmt::OMPTargetParallelDirectiveClass:
17830b57cec5SDimitry Andric     case Stmt::OMPTargetParallelForDirectiveClass:
17840b57cec5SDimitry Andric     case Stmt::OMPTargetUpdateDirectiveClass:
17850b57cec5SDimitry Andric     case Stmt::OMPTeamsDirectiveClass:
17860b57cec5SDimitry Andric     case Stmt::OMPCancellationPointDirectiveClass:
17870b57cec5SDimitry Andric     case Stmt::OMPCancelDirectiveClass:
17880b57cec5SDimitry Andric     case Stmt::OMPTaskLoopDirectiveClass:
17890b57cec5SDimitry Andric     case Stmt::OMPTaskLoopSimdDirectiveClass:
1790a7dea167SDimitry Andric     case Stmt::OMPMasterTaskLoopDirectiveClass:
179181ad6265SDimitry Andric     case Stmt::OMPMaskedTaskLoopDirectiveClass:
1792a7dea167SDimitry Andric     case Stmt::OMPMasterTaskLoopSimdDirectiveClass:
179381ad6265SDimitry Andric     case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:
1794a7dea167SDimitry Andric     case Stmt::OMPParallelMasterTaskLoopDirectiveClass:
179581ad6265SDimitry Andric     case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:
1796480093f4SDimitry Andric     case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:
179781ad6265SDimitry Andric     case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:
17980b57cec5SDimitry Andric     case Stmt::OMPDistributeDirectiveClass:
17990b57cec5SDimitry Andric     case Stmt::OMPDistributeParallelForDirectiveClass:
18000b57cec5SDimitry Andric     case Stmt::OMPDistributeParallelForSimdDirectiveClass:
18010b57cec5SDimitry Andric     case Stmt::OMPDistributeSimdDirectiveClass:
18020b57cec5SDimitry Andric     case Stmt::OMPTargetParallelForSimdDirectiveClass:
18030b57cec5SDimitry Andric     case Stmt::OMPTargetSimdDirectiveClass:
18040b57cec5SDimitry Andric     case Stmt::OMPTeamsDistributeDirectiveClass:
18050b57cec5SDimitry Andric     case Stmt::OMPTeamsDistributeSimdDirectiveClass:
18060b57cec5SDimitry Andric     case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
18070b57cec5SDimitry Andric     case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
18080b57cec5SDimitry Andric     case Stmt::OMPTargetTeamsDirectiveClass:
18090b57cec5SDimitry Andric     case Stmt::OMPTargetTeamsDistributeDirectiveClass:
18100b57cec5SDimitry Andric     case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
18110b57cec5SDimitry Andric     case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
18120b57cec5SDimitry Andric     case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
1813fe6060f1SDimitry Andric     case Stmt::OMPTileDirectiveClass:
1814fe6060f1SDimitry Andric     case Stmt::OMPInteropDirectiveClass:
1815fe6060f1SDimitry Andric     case Stmt::OMPDispatchDirectiveClass:
1816fe6060f1SDimitry Andric     case Stmt::OMPMaskedDirectiveClass:
1817349cc55cSDimitry Andric     case Stmt::OMPGenericLoopDirectiveClass:
181881ad6265SDimitry Andric     case Stmt::OMPTeamsGenericLoopDirectiveClass:
181981ad6265SDimitry Andric     case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:
182081ad6265SDimitry Andric     case Stmt::OMPParallelGenericLoopDirectiveClass:
182181ad6265SDimitry Andric     case Stmt::OMPTargetParallelGenericLoopDirectiveClass:
1822fe6060f1SDimitry Andric     case Stmt::CapturedStmtClass:
1823349cc55cSDimitry Andric     case Stmt::OMPUnrollDirectiveClass:
1824349cc55cSDimitry Andric     case Stmt::OMPMetaDirectiveClass: {
18250b57cec5SDimitry Andric       const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());
18260b57cec5SDimitry Andric       Engine.addAbortedBlock(node, currBldrCtx->getBlock());
18270b57cec5SDimitry Andric       break;
18280b57cec5SDimitry Andric     }
18290b57cec5SDimitry Andric 
18300b57cec5SDimitry Andric     case Stmt::ParenExprClass:
18310b57cec5SDimitry Andric       llvm_unreachable("ParenExprs already handled.");
18320b57cec5SDimitry Andric     case Stmt::GenericSelectionExprClass:
18330b57cec5SDimitry Andric       llvm_unreachable("GenericSelectionExprs already handled.");
18340b57cec5SDimitry Andric     // Cases that should never be evaluated simply because they shouldn't
18350b57cec5SDimitry Andric     // appear in the CFG.
18360b57cec5SDimitry Andric     case Stmt::BreakStmtClass:
18370b57cec5SDimitry Andric     case Stmt::CaseStmtClass:
18380b57cec5SDimitry Andric     case Stmt::CompoundStmtClass:
18390b57cec5SDimitry Andric     case Stmt::ContinueStmtClass:
18400b57cec5SDimitry Andric     case Stmt::CXXForRangeStmtClass:
18410b57cec5SDimitry Andric     case Stmt::DefaultStmtClass:
18420b57cec5SDimitry Andric     case Stmt::DoStmtClass:
18430b57cec5SDimitry Andric     case Stmt::ForStmtClass:
18440b57cec5SDimitry Andric     case Stmt::GotoStmtClass:
18450b57cec5SDimitry Andric     case Stmt::IfStmtClass:
18460b57cec5SDimitry Andric     case Stmt::IndirectGotoStmtClass:
18470b57cec5SDimitry Andric     case Stmt::LabelStmtClass:
18480b57cec5SDimitry Andric     case Stmt::NoStmtClass:
18490b57cec5SDimitry Andric     case Stmt::NullStmtClass:
18500b57cec5SDimitry Andric     case Stmt::SwitchStmtClass:
18510b57cec5SDimitry Andric     case Stmt::WhileStmtClass:
18520b57cec5SDimitry Andric     case Expr::MSDependentExistsStmtClass:
18530b57cec5SDimitry Andric       llvm_unreachable("Stmt should not be in analyzer evaluation loop");
1854480093f4SDimitry Andric     case Stmt::ImplicitValueInitExprClass:
1855480093f4SDimitry Andric       // These nodes are shared in the CFG and would case caching out.
1856480093f4SDimitry Andric       // Moreover, no additional evaluation required for them, the
1857480093f4SDimitry Andric       // analyzer can reconstruct these values from the AST.
1858480093f4SDimitry Andric       llvm_unreachable("Should be pruned from CFG");
18590b57cec5SDimitry Andric 
18600b57cec5SDimitry Andric     case Stmt::ObjCSubscriptRefExprClass:
18610b57cec5SDimitry Andric     case Stmt::ObjCPropertyRefExprClass:
18620b57cec5SDimitry Andric       llvm_unreachable("These are handled by PseudoObjectExpr");
18630b57cec5SDimitry Andric 
18640b57cec5SDimitry Andric     case Stmt::GNUNullExprClass: {
18650b57cec5SDimitry Andric       // GNU __null is a pointer-width integer, not an actual pointer.
18660b57cec5SDimitry Andric       ProgramStateRef state = Pred->getState();
186781ad6265SDimitry Andric       state = state->BindExpr(
186881ad6265SDimitry Andric           S, Pred->getLocationContext(),
186981ad6265SDimitry Andric           svalBuilder.makeIntValWithWidth(getContext().VoidPtrTy, 0));
18700b57cec5SDimitry Andric       Bldr.generateNode(S, Pred, state);
18710b57cec5SDimitry Andric       break;
18720b57cec5SDimitry Andric     }
18730b57cec5SDimitry Andric 
18740b57cec5SDimitry Andric     case Stmt::ObjCAtSynchronizedStmtClass:
18750b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
18760b57cec5SDimitry Andric       VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S), Pred, Dst);
18770b57cec5SDimitry Andric       Bldr.addNodes(Dst);
18780b57cec5SDimitry Andric       break;
18790b57cec5SDimitry Andric 
18800b57cec5SDimitry Andric     case Expr::ConstantExprClass:
18810b57cec5SDimitry Andric     case Stmt::ExprWithCleanupsClass:
18820b57cec5SDimitry Andric       // Handled due to fully linearised CFG.
18830b57cec5SDimitry Andric       break;
18840b57cec5SDimitry Andric 
18850b57cec5SDimitry Andric     case Stmt::CXXBindTemporaryExprClass: {
18860b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
18870b57cec5SDimitry Andric       ExplodedNodeSet PreVisit;
18880b57cec5SDimitry Andric       getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
18890b57cec5SDimitry Andric       ExplodedNodeSet Next;
18900b57cec5SDimitry Andric       VisitCXXBindTemporaryExpr(cast<CXXBindTemporaryExpr>(S), PreVisit, Next);
18910b57cec5SDimitry Andric       getCheckerManager().runCheckersForPostStmt(Dst, Next, S, *this);
18920b57cec5SDimitry Andric       Bldr.addNodes(Dst);
18930b57cec5SDimitry Andric       break;
18940b57cec5SDimitry Andric     }
18950b57cec5SDimitry Andric 
189681ad6265SDimitry Andric     case Stmt::ArrayInitLoopExprClass:
189781ad6265SDimitry Andric       Bldr.takeNodes(Pred);
189881ad6265SDimitry Andric       VisitArrayInitLoopExpr(cast<ArrayInitLoopExpr>(S), Pred, Dst);
189981ad6265SDimitry Andric       Bldr.addNodes(Dst);
190081ad6265SDimitry Andric       break;
19010b57cec5SDimitry Andric     // Cases not handled yet; but will handle some day.
19020b57cec5SDimitry Andric     case Stmt::DesignatedInitExprClass:
19030b57cec5SDimitry Andric     case Stmt::DesignatedInitUpdateExprClass:
19040b57cec5SDimitry Andric     case Stmt::ArrayInitIndexExprClass:
19050b57cec5SDimitry Andric     case Stmt::ExtVectorElementExprClass:
19060b57cec5SDimitry Andric     case Stmt::ImaginaryLiteralClass:
19070b57cec5SDimitry Andric     case Stmt::ObjCAtCatchStmtClass:
19080b57cec5SDimitry Andric     case Stmt::ObjCAtFinallyStmtClass:
19090b57cec5SDimitry Andric     case Stmt::ObjCAtTryStmtClass:
19100b57cec5SDimitry Andric     case Stmt::ObjCAutoreleasePoolStmtClass:
19110b57cec5SDimitry Andric     case Stmt::ObjCEncodeExprClass:
19120b57cec5SDimitry Andric     case Stmt::ObjCIsaExprClass:
19130b57cec5SDimitry Andric     case Stmt::ObjCProtocolExprClass:
19140b57cec5SDimitry Andric     case Stmt::ObjCSelectorExprClass:
19150b57cec5SDimitry Andric     case Stmt::ParenListExprClass:
19160b57cec5SDimitry Andric     case Stmt::ShuffleVectorExprClass:
19170b57cec5SDimitry Andric     case Stmt::ConvertVectorExprClass:
19180b57cec5SDimitry Andric     case Stmt::VAArgExprClass:
19190b57cec5SDimitry Andric     case Stmt::CUDAKernelCallExprClass:
19200b57cec5SDimitry Andric     case Stmt::OpaqueValueExprClass:
19210b57cec5SDimitry Andric     case Stmt::AsTypeExprClass:
1922a7dea167SDimitry Andric     case Stmt::ConceptSpecializationExprClass:
1923a7dea167SDimitry Andric     case Stmt::CXXRewrittenBinaryOperatorClass:
192455e4f9d5SDimitry Andric     case Stmt::RequiresExprClass:
1925bdd1243dSDimitry Andric     case Expr::CXXParenListInitExprClass:
19260b57cec5SDimitry Andric       // Fall through.
19270b57cec5SDimitry Andric 
19280b57cec5SDimitry Andric     // Cases we intentionally don't evaluate, since they don't need
19290b57cec5SDimitry Andric     // to be explicitly evaluated.
19300b57cec5SDimitry Andric     case Stmt::PredefinedExprClass:
19310b57cec5SDimitry Andric     case Stmt::AddrLabelExprClass:
19320b57cec5SDimitry Andric     case Stmt::AttributedStmtClass:
19330b57cec5SDimitry Andric     case Stmt::IntegerLiteralClass:
19340b57cec5SDimitry Andric     case Stmt::FixedPointLiteralClass:
19350b57cec5SDimitry Andric     case Stmt::CharacterLiteralClass:
19360b57cec5SDimitry Andric     case Stmt::CXXScalarValueInitExprClass:
19370b57cec5SDimitry Andric     case Stmt::CXXBoolLiteralExprClass:
19380b57cec5SDimitry Andric     case Stmt::ObjCBoolLiteralExprClass:
19390b57cec5SDimitry Andric     case Stmt::ObjCAvailabilityCheckExprClass:
19400b57cec5SDimitry Andric     case Stmt::FloatingLiteralClass:
19410b57cec5SDimitry Andric     case Stmt::NoInitExprClass:
19420b57cec5SDimitry Andric     case Stmt::SizeOfPackExprClass:
19430b57cec5SDimitry Andric     case Stmt::StringLiteralClass:
19440b57cec5SDimitry Andric     case Stmt::SourceLocExprClass:
19450b57cec5SDimitry Andric     case Stmt::ObjCStringLiteralClass:
19460b57cec5SDimitry Andric     case Stmt::CXXPseudoDestructorExprClass:
19470b57cec5SDimitry Andric     case Stmt::SubstNonTypeTemplateParmExprClass:
19480b57cec5SDimitry Andric     case Stmt::CXXNullPtrLiteralExprClass:
19490b57cec5SDimitry Andric     case Stmt::OMPArraySectionExprClass:
19505ffd83dbSDimitry Andric     case Stmt::OMPArrayShapingExprClass:
19515ffd83dbSDimitry Andric     case Stmt::OMPIteratorExprClass:
1952fe6060f1SDimitry Andric     case Stmt::SYCLUniqueStableNameExprClass:
19530b57cec5SDimitry Andric     case Stmt::TypeTraitExprClass: {
19540b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
19550b57cec5SDimitry Andric       ExplodedNodeSet preVisit;
19560b57cec5SDimitry Andric       getCheckerManager().runCheckersForPreStmt(preVisit, Pred, S, *this);
19570b57cec5SDimitry Andric       getCheckerManager().runCheckersForPostStmt(Dst, preVisit, S, *this);
19580b57cec5SDimitry Andric       Bldr.addNodes(Dst);
19590b57cec5SDimitry Andric       break;
19600b57cec5SDimitry Andric     }
19610b57cec5SDimitry Andric 
19620b57cec5SDimitry Andric     case Stmt::CXXDefaultArgExprClass:
19630b57cec5SDimitry Andric     case Stmt::CXXDefaultInitExprClass: {
19640b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
19650b57cec5SDimitry Andric       ExplodedNodeSet PreVisit;
19660b57cec5SDimitry Andric       getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
19670b57cec5SDimitry Andric 
19680b57cec5SDimitry Andric       ExplodedNodeSet Tmp;
19690b57cec5SDimitry Andric       StmtNodeBuilder Bldr2(PreVisit, Tmp, *currBldrCtx);
19700b57cec5SDimitry Andric 
19710b57cec5SDimitry Andric       const Expr *ArgE;
19720b57cec5SDimitry Andric       if (const auto *DefE = dyn_cast<CXXDefaultArgExpr>(S))
19730b57cec5SDimitry Andric         ArgE = DefE->getExpr();
19740b57cec5SDimitry Andric       else if (const auto *DefE = dyn_cast<CXXDefaultInitExpr>(S))
19750b57cec5SDimitry Andric         ArgE = DefE->getExpr();
19760b57cec5SDimitry Andric       else
19770b57cec5SDimitry Andric         llvm_unreachable("unknown constant wrapper kind");
19780b57cec5SDimitry Andric 
19790b57cec5SDimitry Andric       bool IsTemporary = false;
19800b57cec5SDimitry Andric       if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(ArgE)) {
1981480093f4SDimitry Andric         ArgE = MTE->getSubExpr();
19820b57cec5SDimitry Andric         IsTemporary = true;
19830b57cec5SDimitry Andric       }
19840b57cec5SDimitry Andric 
1985bdd1243dSDimitry Andric       std::optional<SVal> ConstantVal = svalBuilder.getConstantVal(ArgE);
19860b57cec5SDimitry Andric       if (!ConstantVal)
19870b57cec5SDimitry Andric         ConstantVal = UnknownVal();
19880b57cec5SDimitry Andric 
19890b57cec5SDimitry Andric       const LocationContext *LCtx = Pred->getLocationContext();
19900b57cec5SDimitry Andric       for (const auto I : PreVisit) {
19910b57cec5SDimitry Andric         ProgramStateRef State = I->getState();
19920b57cec5SDimitry Andric         State = State->BindExpr(S, LCtx, *ConstantVal);
19930b57cec5SDimitry Andric         if (IsTemporary)
19940b57cec5SDimitry Andric           State = createTemporaryRegionIfNeeded(State, LCtx,
19950b57cec5SDimitry Andric                                                 cast<Expr>(S),
19960b57cec5SDimitry Andric                                                 cast<Expr>(S));
19970b57cec5SDimitry Andric         Bldr2.generateNode(S, I, State);
19980b57cec5SDimitry Andric       }
19990b57cec5SDimitry Andric 
20000b57cec5SDimitry Andric       getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this);
20010b57cec5SDimitry Andric       Bldr.addNodes(Dst);
20020b57cec5SDimitry Andric       break;
20030b57cec5SDimitry Andric     }
20040b57cec5SDimitry Andric 
20050b57cec5SDimitry Andric     // Cases we evaluate as opaque expressions, conjuring a symbol.
20060b57cec5SDimitry Andric     case Stmt::CXXStdInitializerListExprClass:
20070b57cec5SDimitry Andric     case Expr::ObjCArrayLiteralClass:
20080b57cec5SDimitry Andric     case Expr::ObjCDictionaryLiteralClass:
20090b57cec5SDimitry Andric     case Expr::ObjCBoxedExprClass: {
20100b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
20110b57cec5SDimitry Andric 
20120b57cec5SDimitry Andric       ExplodedNodeSet preVisit;
20130b57cec5SDimitry Andric       getCheckerManager().runCheckersForPreStmt(preVisit, Pred, S, *this);
20140b57cec5SDimitry Andric 
20150b57cec5SDimitry Andric       ExplodedNodeSet Tmp;
20160b57cec5SDimitry Andric       StmtNodeBuilder Bldr2(preVisit, Tmp, *currBldrCtx);
20170b57cec5SDimitry Andric 
20180b57cec5SDimitry Andric       const auto *Ex = cast<Expr>(S);
20190b57cec5SDimitry Andric       QualType resultType = Ex->getType();
20200b57cec5SDimitry Andric 
20210b57cec5SDimitry Andric       for (const auto N : preVisit) {
20220b57cec5SDimitry Andric         const LocationContext *LCtx = N->getLocationContext();
20230b57cec5SDimitry Andric         SVal result = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx,
20240b57cec5SDimitry Andric                                                    resultType,
20250b57cec5SDimitry Andric                                                    currBldrCtx->blockCount());
20260b57cec5SDimitry Andric         ProgramStateRef State = N->getState()->BindExpr(Ex, LCtx, result);
20270b57cec5SDimitry Andric 
20280b57cec5SDimitry Andric         // Escape pointers passed into the list, unless it's an ObjC boxed
20290b57cec5SDimitry Andric         // expression which is not a boxable C structure.
20300b57cec5SDimitry Andric         if (!(isa<ObjCBoxedExpr>(Ex) &&
20310b57cec5SDimitry Andric               !cast<ObjCBoxedExpr>(Ex)->getSubExpr()
20320b57cec5SDimitry Andric                                       ->getType()->isRecordType()))
20330b57cec5SDimitry Andric           for (auto Child : Ex->children()) {
20340b57cec5SDimitry Andric             assert(Child);
20350b57cec5SDimitry Andric             SVal Val = State->getSVal(Child, LCtx);
2036480093f4SDimitry Andric             State = escapeValues(State, Val, PSK_EscapeOther);
20370b57cec5SDimitry Andric           }
20380b57cec5SDimitry Andric 
20390b57cec5SDimitry Andric         Bldr2.generateNode(S, N, State);
20400b57cec5SDimitry Andric       }
20410b57cec5SDimitry Andric 
20420b57cec5SDimitry Andric       getCheckerManager().runCheckersForPostStmt(Dst, Tmp, S, *this);
20430b57cec5SDimitry Andric       Bldr.addNodes(Dst);
20440b57cec5SDimitry Andric       break;
20450b57cec5SDimitry Andric     }
20460b57cec5SDimitry Andric 
20470b57cec5SDimitry Andric     case Stmt::ArraySubscriptExprClass:
20480b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
20490b57cec5SDimitry Andric       VisitArraySubscriptExpr(cast<ArraySubscriptExpr>(S), Pred, Dst);
20500b57cec5SDimitry Andric       Bldr.addNodes(Dst);
20510b57cec5SDimitry Andric       break;
20520b57cec5SDimitry Andric 
20535ffd83dbSDimitry Andric     case Stmt::MatrixSubscriptExprClass:
20545ffd83dbSDimitry Andric       llvm_unreachable("Support for MatrixSubscriptExpr is not implemented.");
20555ffd83dbSDimitry Andric       break;
20565ffd83dbSDimitry Andric 
20570b57cec5SDimitry Andric     case Stmt::GCCAsmStmtClass:
20580b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
20590b57cec5SDimitry Andric       VisitGCCAsmStmt(cast<GCCAsmStmt>(S), Pred, Dst);
20600b57cec5SDimitry Andric       Bldr.addNodes(Dst);
20610b57cec5SDimitry Andric       break;
20620b57cec5SDimitry Andric 
20630b57cec5SDimitry Andric     case Stmt::MSAsmStmtClass:
20640b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
20650b57cec5SDimitry Andric       VisitMSAsmStmt(cast<MSAsmStmt>(S), Pred, Dst);
20660b57cec5SDimitry Andric       Bldr.addNodes(Dst);
20670b57cec5SDimitry Andric       break;
20680b57cec5SDimitry Andric 
20690b57cec5SDimitry Andric     case Stmt::BlockExprClass:
20700b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
20710b57cec5SDimitry Andric       VisitBlockExpr(cast<BlockExpr>(S), Pred, Dst);
20720b57cec5SDimitry Andric       Bldr.addNodes(Dst);
20730b57cec5SDimitry Andric       break;
20740b57cec5SDimitry Andric 
20750b57cec5SDimitry Andric     case Stmt::LambdaExprClass:
20760b57cec5SDimitry Andric       if (AMgr.options.ShouldInlineLambdas) {
20770b57cec5SDimitry Andric         Bldr.takeNodes(Pred);
20780b57cec5SDimitry Andric         VisitLambdaExpr(cast<LambdaExpr>(S), Pred, Dst);
20790b57cec5SDimitry Andric         Bldr.addNodes(Dst);
20800b57cec5SDimitry Andric       } else {
20810b57cec5SDimitry Andric         const ExplodedNode *node = Bldr.generateSink(S, Pred, Pred->getState());
20820b57cec5SDimitry Andric         Engine.addAbortedBlock(node, currBldrCtx->getBlock());
20830b57cec5SDimitry Andric       }
20840b57cec5SDimitry Andric       break;
20850b57cec5SDimitry Andric 
20860b57cec5SDimitry Andric     case Stmt::BinaryOperatorClass: {
20870b57cec5SDimitry Andric       const auto *B = cast<BinaryOperator>(S);
20880b57cec5SDimitry Andric       if (B->isLogicalOp()) {
20890b57cec5SDimitry Andric         Bldr.takeNodes(Pred);
20900b57cec5SDimitry Andric         VisitLogicalExpr(B, Pred, Dst);
20910b57cec5SDimitry Andric         Bldr.addNodes(Dst);
20920b57cec5SDimitry Andric         break;
20930b57cec5SDimitry Andric       }
20940b57cec5SDimitry Andric       else if (B->getOpcode() == BO_Comma) {
20950b57cec5SDimitry Andric         ProgramStateRef state = Pred->getState();
20960b57cec5SDimitry Andric         Bldr.generateNode(B, Pred,
20970b57cec5SDimitry Andric                           state->BindExpr(B, Pred->getLocationContext(),
20980b57cec5SDimitry Andric                                           state->getSVal(B->getRHS(),
20990b57cec5SDimitry Andric                                                   Pred->getLocationContext())));
21000b57cec5SDimitry Andric         break;
21010b57cec5SDimitry Andric       }
21020b57cec5SDimitry Andric 
21030b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
21040b57cec5SDimitry Andric 
21050b57cec5SDimitry Andric       if (AMgr.options.ShouldEagerlyAssume &&
21060b57cec5SDimitry Andric           (B->isRelationalOp() || B->isEqualityOp())) {
21070b57cec5SDimitry Andric         ExplodedNodeSet Tmp;
21080b57cec5SDimitry Andric         VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Tmp);
21090b57cec5SDimitry Andric         evalEagerlyAssumeBinOpBifurcation(Dst, Tmp, cast<Expr>(S));
21100b57cec5SDimitry Andric       }
21110b57cec5SDimitry Andric       else
21120b57cec5SDimitry Andric         VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
21130b57cec5SDimitry Andric 
21140b57cec5SDimitry Andric       Bldr.addNodes(Dst);
21150b57cec5SDimitry Andric       break;
21160b57cec5SDimitry Andric     }
21170b57cec5SDimitry Andric 
21180b57cec5SDimitry Andric     case Stmt::CXXOperatorCallExprClass: {
21190b57cec5SDimitry Andric       const auto *OCE = cast<CXXOperatorCallExpr>(S);
21200b57cec5SDimitry Andric 
21210b57cec5SDimitry Andric       // For instance method operators, make sure the 'this' argument has a
21220b57cec5SDimitry Andric       // valid region.
21230b57cec5SDimitry Andric       const Decl *Callee = OCE->getCalleeDecl();
21240b57cec5SDimitry Andric       if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(Callee)) {
21255f757f3fSDimitry Andric         if (MD->isImplicitObjectMemberFunction()) {
21260b57cec5SDimitry Andric           ProgramStateRef State = Pred->getState();
21270b57cec5SDimitry Andric           const LocationContext *LCtx = Pred->getLocationContext();
21280b57cec5SDimitry Andric           ProgramStateRef NewState =
21290b57cec5SDimitry Andric             createTemporaryRegionIfNeeded(State, LCtx, OCE->getArg(0));
21300b57cec5SDimitry Andric           if (NewState != State) {
21310b57cec5SDimitry Andric             Pred = Bldr.generateNode(OCE, Pred, NewState, /*tag=*/nullptr,
21320b57cec5SDimitry Andric                                      ProgramPoint::PreStmtKind);
21330b57cec5SDimitry Andric             // Did we cache out?
21340b57cec5SDimitry Andric             if (!Pred)
21350b57cec5SDimitry Andric               break;
21360b57cec5SDimitry Andric           }
21370b57cec5SDimitry Andric         }
21380b57cec5SDimitry Andric       }
2139bdd1243dSDimitry Andric       [[fallthrough]];
21400b57cec5SDimitry Andric     }
21410b57cec5SDimitry Andric 
21420b57cec5SDimitry Andric     case Stmt::CallExprClass:
21430b57cec5SDimitry Andric     case Stmt::CXXMemberCallExprClass:
21440b57cec5SDimitry Andric     case Stmt::UserDefinedLiteralClass:
21450b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
21460b57cec5SDimitry Andric       VisitCallExpr(cast<CallExpr>(S), Pred, Dst);
21470b57cec5SDimitry Andric       Bldr.addNodes(Dst);
21480b57cec5SDimitry Andric       break;
21490b57cec5SDimitry Andric 
21500b57cec5SDimitry Andric     case Stmt::CXXCatchStmtClass:
21510b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
21520b57cec5SDimitry Andric       VisitCXXCatchStmt(cast<CXXCatchStmt>(S), Pred, Dst);
21530b57cec5SDimitry Andric       Bldr.addNodes(Dst);
21540b57cec5SDimitry Andric       break;
21550b57cec5SDimitry Andric 
21560b57cec5SDimitry Andric     case Stmt::CXXTemporaryObjectExprClass:
21570b57cec5SDimitry Andric     case Stmt::CXXConstructExprClass:
21580b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
21590b57cec5SDimitry Andric       VisitCXXConstructExpr(cast<CXXConstructExpr>(S), Pred, Dst);
21600b57cec5SDimitry Andric       Bldr.addNodes(Dst);
21610b57cec5SDimitry Andric       break;
21620b57cec5SDimitry Andric 
21635ffd83dbSDimitry Andric     case Stmt::CXXInheritedCtorInitExprClass:
21645ffd83dbSDimitry Andric       Bldr.takeNodes(Pred);
21655ffd83dbSDimitry Andric       VisitCXXInheritedCtorInitExpr(cast<CXXInheritedCtorInitExpr>(S), Pred,
21665ffd83dbSDimitry Andric                                     Dst);
21675ffd83dbSDimitry Andric       Bldr.addNodes(Dst);
21685ffd83dbSDimitry Andric       break;
21695ffd83dbSDimitry Andric 
21700b57cec5SDimitry Andric     case Stmt::CXXNewExprClass: {
21710b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
21720b57cec5SDimitry Andric 
21730b57cec5SDimitry Andric       ExplodedNodeSet PreVisit;
21740b57cec5SDimitry Andric       getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
21750b57cec5SDimitry Andric 
21760b57cec5SDimitry Andric       ExplodedNodeSet PostVisit;
21770b57cec5SDimitry Andric       for (const auto i : PreVisit)
21780b57cec5SDimitry Andric         VisitCXXNewExpr(cast<CXXNewExpr>(S), i, PostVisit);
21790b57cec5SDimitry Andric 
21800b57cec5SDimitry Andric       getCheckerManager().runCheckersForPostStmt(Dst, PostVisit, S, *this);
21810b57cec5SDimitry Andric       Bldr.addNodes(Dst);
21820b57cec5SDimitry Andric       break;
21830b57cec5SDimitry Andric     }
21840b57cec5SDimitry Andric 
21850b57cec5SDimitry Andric     case Stmt::CXXDeleteExprClass: {
21860b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
21870b57cec5SDimitry Andric       ExplodedNodeSet PreVisit;
21880b57cec5SDimitry Andric       const auto *CDE = cast<CXXDeleteExpr>(S);
21890b57cec5SDimitry Andric       getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
21905ffd83dbSDimitry Andric       ExplodedNodeSet PostVisit;
21915ffd83dbSDimitry Andric       getCheckerManager().runCheckersForPostStmt(PostVisit, PreVisit, S, *this);
21920b57cec5SDimitry Andric 
21935ffd83dbSDimitry Andric       for (const auto i : PostVisit)
21940b57cec5SDimitry Andric         VisitCXXDeleteExpr(CDE, i, Dst);
21950b57cec5SDimitry Andric 
21960b57cec5SDimitry Andric       Bldr.addNodes(Dst);
21970b57cec5SDimitry Andric       break;
21980b57cec5SDimitry Andric     }
21990b57cec5SDimitry Andric       // FIXME: ChooseExpr is really a constant.  We need to fix
22000b57cec5SDimitry Andric       //        the CFG do not model them as explicit control-flow.
22010b57cec5SDimitry Andric 
22020b57cec5SDimitry Andric     case Stmt::ChooseExprClass: { // __builtin_choose_expr
22030b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
22040b57cec5SDimitry Andric       const auto *C = cast<ChooseExpr>(S);
22050b57cec5SDimitry Andric       VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
22060b57cec5SDimitry Andric       Bldr.addNodes(Dst);
22070b57cec5SDimitry Andric       break;
22080b57cec5SDimitry Andric     }
22090b57cec5SDimitry Andric 
22100b57cec5SDimitry Andric     case Stmt::CompoundAssignOperatorClass:
22110b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
22120b57cec5SDimitry Andric       VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
22130b57cec5SDimitry Andric       Bldr.addNodes(Dst);
22140b57cec5SDimitry Andric       break;
22150b57cec5SDimitry Andric 
22160b57cec5SDimitry Andric     case Stmt::CompoundLiteralExprClass:
22170b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
22180b57cec5SDimitry Andric       VisitCompoundLiteralExpr(cast<CompoundLiteralExpr>(S), Pred, Dst);
22190b57cec5SDimitry Andric       Bldr.addNodes(Dst);
22200b57cec5SDimitry Andric       break;
22210b57cec5SDimitry Andric 
22220b57cec5SDimitry Andric     case Stmt::BinaryConditionalOperatorClass:
22230b57cec5SDimitry Andric     case Stmt::ConditionalOperatorClass: { // '?' operator
22240b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
22250b57cec5SDimitry Andric       const auto *C = cast<AbstractConditionalOperator>(S);
22260b57cec5SDimitry Andric       VisitGuardedExpr(C, C->getTrueExpr(), C->getFalseExpr(), Pred, Dst);
22270b57cec5SDimitry Andric       Bldr.addNodes(Dst);
22280b57cec5SDimitry Andric       break;
22290b57cec5SDimitry Andric     }
22300b57cec5SDimitry Andric 
22310b57cec5SDimitry Andric     case Stmt::CXXThisExprClass:
22320b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
22330b57cec5SDimitry Andric       VisitCXXThisExpr(cast<CXXThisExpr>(S), Pred, Dst);
22340b57cec5SDimitry Andric       Bldr.addNodes(Dst);
22350b57cec5SDimitry Andric       break;
22360b57cec5SDimitry Andric 
22370b57cec5SDimitry Andric     case Stmt::DeclRefExprClass: {
22380b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
22390b57cec5SDimitry Andric       const auto *DE = cast<DeclRefExpr>(S);
22400b57cec5SDimitry Andric       VisitCommonDeclRefExpr(DE, DE->getDecl(), Pred, Dst);
22410b57cec5SDimitry Andric       Bldr.addNodes(Dst);
22420b57cec5SDimitry Andric       break;
22430b57cec5SDimitry Andric     }
22440b57cec5SDimitry Andric 
22450b57cec5SDimitry Andric     case Stmt::DeclStmtClass:
22460b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
22470b57cec5SDimitry Andric       VisitDeclStmt(cast<DeclStmt>(S), Pred, Dst);
22480b57cec5SDimitry Andric       Bldr.addNodes(Dst);
22490b57cec5SDimitry Andric       break;
22500b57cec5SDimitry Andric 
22510b57cec5SDimitry Andric     case Stmt::ImplicitCastExprClass:
22520b57cec5SDimitry Andric     case Stmt::CStyleCastExprClass:
22530b57cec5SDimitry Andric     case Stmt::CXXStaticCastExprClass:
22540b57cec5SDimitry Andric     case Stmt::CXXDynamicCastExprClass:
22550b57cec5SDimitry Andric     case Stmt::CXXReinterpretCastExprClass:
22560b57cec5SDimitry Andric     case Stmt::CXXConstCastExprClass:
22570b57cec5SDimitry Andric     case Stmt::CXXFunctionalCastExprClass:
22580b57cec5SDimitry Andric     case Stmt::BuiltinBitCastExprClass:
22595ffd83dbSDimitry Andric     case Stmt::ObjCBridgedCastExprClass:
22605ffd83dbSDimitry Andric     case Stmt::CXXAddrspaceCastExprClass: {
22610b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
22620b57cec5SDimitry Andric       const auto *C = cast<CastExpr>(S);
22630b57cec5SDimitry Andric       ExplodedNodeSet dstExpr;
22640b57cec5SDimitry Andric       VisitCast(C, C->getSubExpr(), Pred, dstExpr);
22650b57cec5SDimitry Andric 
22660b57cec5SDimitry Andric       // Handle the postvisit checks.
22670b57cec5SDimitry Andric       getCheckerManager().runCheckersForPostStmt(Dst, dstExpr, C, *this);
22680b57cec5SDimitry Andric       Bldr.addNodes(Dst);
22690b57cec5SDimitry Andric       break;
22700b57cec5SDimitry Andric     }
22710b57cec5SDimitry Andric 
22720b57cec5SDimitry Andric     case Expr::MaterializeTemporaryExprClass: {
22730b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
22740b57cec5SDimitry Andric       const auto *MTE = cast<MaterializeTemporaryExpr>(S);
22750b57cec5SDimitry Andric       ExplodedNodeSet dstPrevisit;
22760b57cec5SDimitry Andric       getCheckerManager().runCheckersForPreStmt(dstPrevisit, Pred, MTE, *this);
22770b57cec5SDimitry Andric       ExplodedNodeSet dstExpr;
22780b57cec5SDimitry Andric       for (const auto i : dstPrevisit)
22790b57cec5SDimitry Andric         CreateCXXTemporaryObject(MTE, i, dstExpr);
22800b57cec5SDimitry Andric       getCheckerManager().runCheckersForPostStmt(Dst, dstExpr, MTE, *this);
22810b57cec5SDimitry Andric       Bldr.addNodes(Dst);
22820b57cec5SDimitry Andric       break;
22830b57cec5SDimitry Andric     }
22840b57cec5SDimitry Andric 
22850b57cec5SDimitry Andric     case Stmt::InitListExprClass:
22860b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
22870b57cec5SDimitry Andric       VisitInitListExpr(cast<InitListExpr>(S), Pred, Dst);
22880b57cec5SDimitry Andric       Bldr.addNodes(Dst);
22890b57cec5SDimitry Andric       break;
22900b57cec5SDimitry Andric 
22910b57cec5SDimitry Andric     case Stmt::MemberExprClass:
22920b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
22930b57cec5SDimitry Andric       VisitMemberExpr(cast<MemberExpr>(S), Pred, Dst);
22940b57cec5SDimitry Andric       Bldr.addNodes(Dst);
22950b57cec5SDimitry Andric       break;
22960b57cec5SDimitry Andric 
22970b57cec5SDimitry Andric     case Stmt::AtomicExprClass:
22980b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
22990b57cec5SDimitry Andric       VisitAtomicExpr(cast<AtomicExpr>(S), Pred, Dst);
23000b57cec5SDimitry Andric       Bldr.addNodes(Dst);
23010b57cec5SDimitry Andric       break;
23020b57cec5SDimitry Andric 
23030b57cec5SDimitry Andric     case Stmt::ObjCIvarRefExprClass:
23040b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
23050b57cec5SDimitry Andric       VisitLvalObjCIvarRefExpr(cast<ObjCIvarRefExpr>(S), Pred, Dst);
23060b57cec5SDimitry Andric       Bldr.addNodes(Dst);
23070b57cec5SDimitry Andric       break;
23080b57cec5SDimitry Andric 
23090b57cec5SDimitry Andric     case Stmt::ObjCForCollectionStmtClass:
23100b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
23110b57cec5SDimitry Andric       VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S), Pred, Dst);
23120b57cec5SDimitry Andric       Bldr.addNodes(Dst);
23130b57cec5SDimitry Andric       break;
23140b57cec5SDimitry Andric 
23150b57cec5SDimitry Andric     case Stmt::ObjCMessageExprClass:
23160b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
23170b57cec5SDimitry Andric       VisitObjCMessage(cast<ObjCMessageExpr>(S), Pred, Dst);
23180b57cec5SDimitry Andric       Bldr.addNodes(Dst);
23190b57cec5SDimitry Andric       break;
23200b57cec5SDimitry Andric 
23210b57cec5SDimitry Andric     case Stmt::ObjCAtThrowStmtClass:
23220b57cec5SDimitry Andric     case Stmt::CXXThrowExprClass:
23230b57cec5SDimitry Andric       // FIXME: This is not complete.  We basically treat @throw as
23240b57cec5SDimitry Andric       // an abort.
23250b57cec5SDimitry Andric       Bldr.generateSink(S, Pred, Pred->getState());
23260b57cec5SDimitry Andric       break;
23270b57cec5SDimitry Andric 
23280b57cec5SDimitry Andric     case Stmt::ReturnStmtClass:
23290b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
23300b57cec5SDimitry Andric       VisitReturnStmt(cast<ReturnStmt>(S), Pred, Dst);
23310b57cec5SDimitry Andric       Bldr.addNodes(Dst);
23320b57cec5SDimitry Andric       break;
23330b57cec5SDimitry Andric 
23340b57cec5SDimitry Andric     case Stmt::OffsetOfExprClass: {
23350b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
23360b57cec5SDimitry Andric       ExplodedNodeSet PreVisit;
23370b57cec5SDimitry Andric       getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
23380b57cec5SDimitry Andric 
23390b57cec5SDimitry Andric       ExplodedNodeSet PostVisit;
23400b57cec5SDimitry Andric       for (const auto Node : PreVisit)
23410b57cec5SDimitry Andric         VisitOffsetOfExpr(cast<OffsetOfExpr>(S), Node, PostVisit);
23420b57cec5SDimitry Andric 
23430b57cec5SDimitry Andric       getCheckerManager().runCheckersForPostStmt(Dst, PostVisit, S, *this);
23440b57cec5SDimitry Andric       Bldr.addNodes(Dst);
23450b57cec5SDimitry Andric       break;
23460b57cec5SDimitry Andric     }
23470b57cec5SDimitry Andric 
23480b57cec5SDimitry Andric     case Stmt::UnaryExprOrTypeTraitExprClass:
23490b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
23500b57cec5SDimitry Andric       VisitUnaryExprOrTypeTraitExpr(cast<UnaryExprOrTypeTraitExpr>(S),
23510b57cec5SDimitry Andric                                     Pred, Dst);
23520b57cec5SDimitry Andric       Bldr.addNodes(Dst);
23530b57cec5SDimitry Andric       break;
23540b57cec5SDimitry Andric 
23550b57cec5SDimitry Andric     case Stmt::StmtExprClass: {
23560b57cec5SDimitry Andric       const auto *SE = cast<StmtExpr>(S);
23570b57cec5SDimitry Andric 
23580b57cec5SDimitry Andric       if (SE->getSubStmt()->body_empty()) {
23590b57cec5SDimitry Andric         // Empty statement expression.
23600b57cec5SDimitry Andric         assert(SE->getType() == getContext().VoidTy
23610b57cec5SDimitry Andric                && "Empty statement expression must have void type.");
23620b57cec5SDimitry Andric         break;
23630b57cec5SDimitry Andric       }
23640b57cec5SDimitry Andric 
23650b57cec5SDimitry Andric       if (const auto *LastExpr =
23660b57cec5SDimitry Andric               dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) {
23670b57cec5SDimitry Andric         ProgramStateRef state = Pred->getState();
23680b57cec5SDimitry Andric         Bldr.generateNode(SE, Pred,
23690b57cec5SDimitry Andric                           state->BindExpr(SE, Pred->getLocationContext(),
23700b57cec5SDimitry Andric                                           state->getSVal(LastExpr,
23710b57cec5SDimitry Andric                                                   Pred->getLocationContext())));
23720b57cec5SDimitry Andric       }
23730b57cec5SDimitry Andric       break;
23740b57cec5SDimitry Andric     }
23750b57cec5SDimitry Andric 
23760b57cec5SDimitry Andric     case Stmt::UnaryOperatorClass: {
23770b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
23780b57cec5SDimitry Andric       const auto *U = cast<UnaryOperator>(S);
23790b57cec5SDimitry Andric       if (AMgr.options.ShouldEagerlyAssume && (U->getOpcode() == UO_LNot)) {
23800b57cec5SDimitry Andric         ExplodedNodeSet Tmp;
23810b57cec5SDimitry Andric         VisitUnaryOperator(U, Pred, Tmp);
23820b57cec5SDimitry Andric         evalEagerlyAssumeBinOpBifurcation(Dst, Tmp, U);
23830b57cec5SDimitry Andric       }
23840b57cec5SDimitry Andric       else
23850b57cec5SDimitry Andric         VisitUnaryOperator(U, Pred, Dst);
23860b57cec5SDimitry Andric       Bldr.addNodes(Dst);
23870b57cec5SDimitry Andric       break;
23880b57cec5SDimitry Andric     }
23890b57cec5SDimitry Andric 
23900b57cec5SDimitry Andric     case Stmt::PseudoObjectExprClass: {
23910b57cec5SDimitry Andric       Bldr.takeNodes(Pred);
23920b57cec5SDimitry Andric       ProgramStateRef state = Pred->getState();
23930b57cec5SDimitry Andric       const auto *PE = cast<PseudoObjectExpr>(S);
23940b57cec5SDimitry Andric       if (const Expr *Result = PE->getResultExpr()) {
23950b57cec5SDimitry Andric         SVal V = state->getSVal(Result, Pred->getLocationContext());
23960b57cec5SDimitry Andric         Bldr.generateNode(S, Pred,
23970b57cec5SDimitry Andric                           state->BindExpr(S, Pred->getLocationContext(), V));
23980b57cec5SDimitry Andric       }
23990b57cec5SDimitry Andric       else
24000b57cec5SDimitry Andric         Bldr.generateNode(S, Pred,
24010b57cec5SDimitry Andric                           state->BindExpr(S, Pred->getLocationContext(),
24020b57cec5SDimitry Andric                                                    UnknownVal()));
24030b57cec5SDimitry Andric 
24040b57cec5SDimitry Andric       Bldr.addNodes(Dst);
24050b57cec5SDimitry Andric       break;
24060b57cec5SDimitry Andric     }
24075ffd83dbSDimitry Andric 
24085ffd83dbSDimitry Andric     case Expr::ObjCIndirectCopyRestoreExprClass: {
24095ffd83dbSDimitry Andric       // ObjCIndirectCopyRestoreExpr implies passing a temporary for
24105ffd83dbSDimitry Andric       // correctness of lifetime management.  Due to limited analysis
24115ffd83dbSDimitry Andric       // of ARC, this is implemented as direct arg passing.
24125ffd83dbSDimitry Andric       Bldr.takeNodes(Pred);
24135ffd83dbSDimitry Andric       ProgramStateRef state = Pred->getState();
24145ffd83dbSDimitry Andric       const auto *OIE = cast<ObjCIndirectCopyRestoreExpr>(S);
24155ffd83dbSDimitry Andric       const Expr *E = OIE->getSubExpr();
24165ffd83dbSDimitry Andric       SVal V = state->getSVal(E, Pred->getLocationContext());
24175ffd83dbSDimitry Andric       Bldr.generateNode(S, Pred,
24185ffd83dbSDimitry Andric               state->BindExpr(S, Pred->getLocationContext(), V));
24195ffd83dbSDimitry Andric       Bldr.addNodes(Dst);
24205ffd83dbSDimitry Andric       break;
24215ffd83dbSDimitry Andric     }
24220b57cec5SDimitry Andric   }
24230b57cec5SDimitry Andric }
24240b57cec5SDimitry Andric 
replayWithoutInlining(ExplodedNode * N,const LocationContext * CalleeLC)24250b57cec5SDimitry Andric bool ExprEngine::replayWithoutInlining(ExplodedNode *N,
24260b57cec5SDimitry Andric                                        const LocationContext *CalleeLC) {
24270b57cec5SDimitry Andric   const StackFrameContext *CalleeSF = CalleeLC->getStackFrame();
24280b57cec5SDimitry Andric   const StackFrameContext *CallerSF = CalleeSF->getParent()->getStackFrame();
24290b57cec5SDimitry Andric   assert(CalleeSF && CallerSF);
24300b57cec5SDimitry Andric   ExplodedNode *BeforeProcessingCall = nullptr;
24310b57cec5SDimitry Andric   const Stmt *CE = CalleeSF->getCallSite();
24320b57cec5SDimitry Andric 
24330b57cec5SDimitry Andric   // Find the first node before we started processing the call expression.
24340b57cec5SDimitry Andric   while (N) {
24350b57cec5SDimitry Andric     ProgramPoint L = N->getLocation();
24360b57cec5SDimitry Andric     BeforeProcessingCall = N;
24370b57cec5SDimitry Andric     N = N->pred_empty() ? nullptr : *(N->pred_begin());
24380b57cec5SDimitry Andric 
24390b57cec5SDimitry Andric     // Skip the nodes corresponding to the inlined code.
24400b57cec5SDimitry Andric     if (L.getStackFrame() != CallerSF)
24410b57cec5SDimitry Andric       continue;
24420b57cec5SDimitry Andric     // We reached the caller. Find the node right before we started
24430b57cec5SDimitry Andric     // processing the call.
24440b57cec5SDimitry Andric     if (L.isPurgeKind())
24450b57cec5SDimitry Andric       continue;
24460b57cec5SDimitry Andric     if (L.getAs<PreImplicitCall>())
24470b57cec5SDimitry Andric       continue;
24480b57cec5SDimitry Andric     if (L.getAs<CallEnter>())
24490b57cec5SDimitry Andric       continue;
2450bdd1243dSDimitry Andric     if (std::optional<StmtPoint> SP = L.getAs<StmtPoint>())
24510b57cec5SDimitry Andric       if (SP->getStmt() == CE)
24520b57cec5SDimitry Andric         continue;
24530b57cec5SDimitry Andric     break;
24540b57cec5SDimitry Andric   }
24550b57cec5SDimitry Andric 
24560b57cec5SDimitry Andric   if (!BeforeProcessingCall)
24570b57cec5SDimitry Andric     return false;
24580b57cec5SDimitry Andric 
24590b57cec5SDimitry Andric   // TODO: Clean up the unneeded nodes.
24600b57cec5SDimitry Andric 
24610b57cec5SDimitry Andric   // Build an Epsilon node from which we will restart the analyzes.
24620b57cec5SDimitry Andric   // Note that CE is permitted to be NULL!
2463bdd1243dSDimitry Andric   static SimpleProgramPointTag PT("ExprEngine", "Replay without inlining");
2464bdd1243dSDimitry Andric   ProgramPoint NewNodeLoc = EpsilonPoint(
2465bdd1243dSDimitry Andric       BeforeProcessingCall->getLocationContext(), CE, nullptr, &PT);
24660b57cec5SDimitry Andric   // Add the special flag to GDM to signal retrying with no inlining.
24670b57cec5SDimitry Andric   // Note, changing the state ensures that we are not going to cache out.
24680b57cec5SDimitry Andric   ProgramStateRef NewNodeState = BeforeProcessingCall->getState();
24690b57cec5SDimitry Andric   NewNodeState =
24700b57cec5SDimitry Andric     NewNodeState->set<ReplayWithoutInlining>(const_cast<Stmt *>(CE));
24710b57cec5SDimitry Andric 
24720b57cec5SDimitry Andric   // Make the new node a successor of BeforeProcessingCall.
24730b57cec5SDimitry Andric   bool IsNew = false;
24740b57cec5SDimitry Andric   ExplodedNode *NewNode = G.getNode(NewNodeLoc, NewNodeState, false, &IsNew);
24750b57cec5SDimitry Andric   // We cached out at this point. Caching out is common due to us backtracking
24760b57cec5SDimitry Andric   // from the inlined function, which might spawn several paths.
24770b57cec5SDimitry Andric   if (!IsNew)
24780b57cec5SDimitry Andric     return true;
24790b57cec5SDimitry Andric 
24800b57cec5SDimitry Andric   NewNode->addPredecessor(BeforeProcessingCall, G);
24810b57cec5SDimitry Andric 
24820b57cec5SDimitry Andric   // Add the new node to the work list.
24830b57cec5SDimitry Andric   Engine.enqueueStmtNode(NewNode, CalleeSF->getCallSiteBlock(),
24840b57cec5SDimitry Andric                                   CalleeSF->getIndex());
24850b57cec5SDimitry Andric   NumTimesRetriedWithoutInlining++;
24860b57cec5SDimitry Andric   return true;
24870b57cec5SDimitry Andric }
24880b57cec5SDimitry Andric 
24890b57cec5SDimitry Andric /// Block entrance.  (Update counters).
processCFGBlockEntrance(const BlockEdge & L,NodeBuilderWithSinks & nodeBuilder,ExplodedNode * Pred)24900b57cec5SDimitry Andric void ExprEngine::processCFGBlockEntrance(const BlockEdge &L,
24910b57cec5SDimitry Andric                                          NodeBuilderWithSinks &nodeBuilder,
24920b57cec5SDimitry Andric                                          ExplodedNode *Pred) {
24930b57cec5SDimitry Andric   PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
24940b57cec5SDimitry Andric   // If we reach a loop which has a known bound (and meets
24950b57cec5SDimitry Andric   // other constraints) then consider completely unrolling it.
24960b57cec5SDimitry Andric   if(AMgr.options.ShouldUnrollLoops) {
24970b57cec5SDimitry Andric     unsigned maxBlockVisitOnPath = AMgr.options.maxBlockVisitOnPath;
24980b57cec5SDimitry Andric     const Stmt *Term = nodeBuilder.getContext().getBlock()->getTerminatorStmt();
24990b57cec5SDimitry Andric     if (Term) {
25000b57cec5SDimitry Andric       ProgramStateRef NewState = updateLoopStack(Term, AMgr.getASTContext(),
25010b57cec5SDimitry Andric                                                  Pred, maxBlockVisitOnPath);
25020b57cec5SDimitry Andric       if (NewState != Pred->getState()) {
25030b57cec5SDimitry Andric         ExplodedNode *UpdatedNode = nodeBuilder.generateNode(NewState, Pred);
25040b57cec5SDimitry Andric         if (!UpdatedNode)
25050b57cec5SDimitry Andric           return;
25060b57cec5SDimitry Andric         Pred = UpdatedNode;
25070b57cec5SDimitry Andric       }
25080b57cec5SDimitry Andric     }
25090b57cec5SDimitry Andric     // Is we are inside an unrolled loop then no need the check the counters.
25100b57cec5SDimitry Andric     if(isUnrolledState(Pred->getState()))
25110b57cec5SDimitry Andric       return;
25120b57cec5SDimitry Andric   }
25130b57cec5SDimitry Andric 
25140b57cec5SDimitry Andric   // If this block is terminated by a loop and it has already been visited the
25150b57cec5SDimitry Andric   // maximum number of times, widen the loop.
25160b57cec5SDimitry Andric   unsigned int BlockCount = nodeBuilder.getContext().blockCount();
25170b57cec5SDimitry Andric   if (BlockCount == AMgr.options.maxBlockVisitOnPath - 1 &&
25180b57cec5SDimitry Andric       AMgr.options.ShouldWidenLoops) {
25190b57cec5SDimitry Andric     const Stmt *Term = nodeBuilder.getContext().getBlock()->getTerminatorStmt();
25205f757f3fSDimitry Andric     if (!isa_and_nonnull<ForStmt, WhileStmt, DoStmt, CXXForRangeStmt>(Term))
25210b57cec5SDimitry Andric       return;
25220b57cec5SDimitry Andric     // Widen.
25230b57cec5SDimitry Andric     const LocationContext *LCtx = Pred->getLocationContext();
25240b57cec5SDimitry Andric     ProgramStateRef WidenedState =
25250b57cec5SDimitry Andric         getWidenedLoopState(Pred->getState(), LCtx, BlockCount, Term);
25260b57cec5SDimitry Andric     nodeBuilder.generateNode(WidenedState, Pred);
25270b57cec5SDimitry Andric     return;
25280b57cec5SDimitry Andric   }
25290b57cec5SDimitry Andric 
25300b57cec5SDimitry Andric   // FIXME: Refactor this into a checker.
25310b57cec5SDimitry Andric   if (BlockCount >= AMgr.options.maxBlockVisitOnPath) {
25320b57cec5SDimitry Andric     static SimpleProgramPointTag tag(TagProviderName, "Block count exceeded");
25330b57cec5SDimitry Andric     const ExplodedNode *Sink =
25340b57cec5SDimitry Andric                    nodeBuilder.generateSink(Pred->getState(), Pred, &tag);
25350b57cec5SDimitry Andric 
25360b57cec5SDimitry Andric     // Check if we stopped at the top level function or not.
25370b57cec5SDimitry Andric     // Root node should have the location context of the top most function.
25380b57cec5SDimitry Andric     const LocationContext *CalleeLC = Pred->getLocation().getLocationContext();
25390b57cec5SDimitry Andric     const LocationContext *CalleeSF = CalleeLC->getStackFrame();
25400b57cec5SDimitry Andric     const LocationContext *RootLC =
25410b57cec5SDimitry Andric                         (*G.roots_begin())->getLocation().getLocationContext();
25420b57cec5SDimitry Andric     if (RootLC->getStackFrame() != CalleeSF) {
25430b57cec5SDimitry Andric       Engine.FunctionSummaries->markReachedMaxBlockCount(CalleeSF->getDecl());
25440b57cec5SDimitry Andric 
25450b57cec5SDimitry Andric       // Re-run the call evaluation without inlining it, by storing the
25460b57cec5SDimitry Andric       // no-inlining policy in the state and enqueuing the new work item on
25470b57cec5SDimitry Andric       // the list. Replay should almost never fail. Use the stats to catch it
25480b57cec5SDimitry Andric       // if it does.
25490b57cec5SDimitry Andric       if ((!AMgr.options.NoRetryExhausted &&
25500b57cec5SDimitry Andric            replayWithoutInlining(Pred, CalleeLC)))
25510b57cec5SDimitry Andric         return;
25520b57cec5SDimitry Andric       NumMaxBlockCountReachedInInlined++;
25530b57cec5SDimitry Andric     } else
25540b57cec5SDimitry Andric       NumMaxBlockCountReached++;
25550b57cec5SDimitry Andric 
25560b57cec5SDimitry Andric     // Make sink nodes as exhausted(for stats) only if retry failed.
25570b57cec5SDimitry Andric     Engine.blocksExhausted.push_back(std::make_pair(L, Sink));
25580b57cec5SDimitry Andric   }
25590b57cec5SDimitry Andric }
25600b57cec5SDimitry Andric 
25610b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
25620b57cec5SDimitry Andric // Branch processing.
25630b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
25640b57cec5SDimitry Andric 
25650b57cec5SDimitry Andric /// RecoverCastedSymbol - A helper function for ProcessBranch that is used
25660b57cec5SDimitry Andric /// to try to recover some path-sensitivity for casts of symbolic
25670b57cec5SDimitry Andric /// integers that promote their values (which are currently not tracked well).
25680b57cec5SDimitry Andric /// This function returns the SVal bound to Condition->IgnoreCasts if all the
25690b57cec5SDimitry Andric //  cast(s) did was sign-extend the original value.
RecoverCastedSymbol(ProgramStateRef state,const Stmt * Condition,const LocationContext * LCtx,ASTContext & Ctx)25700b57cec5SDimitry Andric static SVal RecoverCastedSymbol(ProgramStateRef state,
25710b57cec5SDimitry Andric                                 const Stmt *Condition,
25720b57cec5SDimitry Andric                                 const LocationContext *LCtx,
25730b57cec5SDimitry Andric                                 ASTContext &Ctx) {
25740b57cec5SDimitry Andric 
25750b57cec5SDimitry Andric   const auto *Ex = dyn_cast<Expr>(Condition);
25760b57cec5SDimitry Andric   if (!Ex)
25770b57cec5SDimitry Andric     return UnknownVal();
25780b57cec5SDimitry Andric 
25790b57cec5SDimitry Andric   uint64_t bits = 0;
25800b57cec5SDimitry Andric   bool bitsInit = false;
25810b57cec5SDimitry Andric 
25820b57cec5SDimitry Andric   while (const auto *CE = dyn_cast<CastExpr>(Ex)) {
25830b57cec5SDimitry Andric     QualType T = CE->getType();
25840b57cec5SDimitry Andric 
25850b57cec5SDimitry Andric     if (!T->isIntegralOrEnumerationType())
25860b57cec5SDimitry Andric       return UnknownVal();
25870b57cec5SDimitry Andric 
25880b57cec5SDimitry Andric     uint64_t newBits = Ctx.getTypeSize(T);
25890b57cec5SDimitry Andric     if (!bitsInit || newBits < bits) {
25900b57cec5SDimitry Andric       bitsInit = true;
25910b57cec5SDimitry Andric       bits = newBits;
25920b57cec5SDimitry Andric     }
25930b57cec5SDimitry Andric 
25940b57cec5SDimitry Andric     Ex = CE->getSubExpr();
25950b57cec5SDimitry Andric   }
25960b57cec5SDimitry Andric 
25970b57cec5SDimitry Andric   // We reached a non-cast.  Is it a symbolic value?
25980b57cec5SDimitry Andric   QualType T = Ex->getType();
25990b57cec5SDimitry Andric 
26000b57cec5SDimitry Andric   if (!bitsInit || !T->isIntegralOrEnumerationType() ||
26010b57cec5SDimitry Andric       Ctx.getTypeSize(T) > bits)
26020b57cec5SDimitry Andric     return UnknownVal();
26030b57cec5SDimitry Andric 
26040b57cec5SDimitry Andric   return state->getSVal(Ex, LCtx);
26050b57cec5SDimitry Andric }
26060b57cec5SDimitry Andric 
26070b57cec5SDimitry Andric #ifndef NDEBUG
getRightmostLeaf(const Stmt * Condition)26080b57cec5SDimitry Andric static const Stmt *getRightmostLeaf(const Stmt *Condition) {
26090b57cec5SDimitry Andric   while (Condition) {
26100b57cec5SDimitry Andric     const auto *BO = dyn_cast<BinaryOperator>(Condition);
26110b57cec5SDimitry Andric     if (!BO || !BO->isLogicalOp()) {
26120b57cec5SDimitry Andric       return Condition;
26130b57cec5SDimitry Andric     }
26140b57cec5SDimitry Andric     Condition = BO->getRHS()->IgnoreParens();
26150b57cec5SDimitry Andric   }
26160b57cec5SDimitry Andric   return nullptr;
26170b57cec5SDimitry Andric }
26180b57cec5SDimitry Andric #endif
26190b57cec5SDimitry Andric 
26200b57cec5SDimitry Andric // Returns the condition the branch at the end of 'B' depends on and whose value
26210b57cec5SDimitry Andric // has been evaluated within 'B'.
26220b57cec5SDimitry Andric // In most cases, the terminator condition of 'B' will be evaluated fully in
26230b57cec5SDimitry Andric // the last statement of 'B'; in those cases, the resolved condition is the
26240b57cec5SDimitry Andric // given 'Condition'.
26250b57cec5SDimitry Andric // If the condition of the branch is a logical binary operator tree, the CFG is
26260b57cec5SDimitry Andric // optimized: in that case, we know that the expression formed by all but the
26270b57cec5SDimitry Andric // rightmost leaf of the logical binary operator tree must be true, and thus
26280b57cec5SDimitry Andric // the branch condition is at this point equivalent to the truth value of that
26290b57cec5SDimitry Andric // rightmost leaf; the CFG block thus only evaluates this rightmost leaf
26300b57cec5SDimitry Andric // expression in its final statement. As the full condition in that case was
26310b57cec5SDimitry Andric // not evaluated, and is thus not in the SVal cache, we need to use that leaf
26320b57cec5SDimitry Andric // expression to evaluate the truth value of the condition in the current state
26330b57cec5SDimitry Andric // space.
ResolveCondition(const Stmt * Condition,const CFGBlock * B)26340b57cec5SDimitry Andric static const Stmt *ResolveCondition(const Stmt *Condition,
26350b57cec5SDimitry Andric                                     const CFGBlock *B) {
26360b57cec5SDimitry Andric   if (const auto *Ex = dyn_cast<Expr>(Condition))
26370b57cec5SDimitry Andric     Condition = Ex->IgnoreParens();
26380b57cec5SDimitry Andric 
26390b57cec5SDimitry Andric   const auto *BO = dyn_cast<BinaryOperator>(Condition);
26400b57cec5SDimitry Andric   if (!BO || !BO->isLogicalOp())
26410b57cec5SDimitry Andric     return Condition;
26420b57cec5SDimitry Andric 
26430b57cec5SDimitry Andric   assert(B->getTerminator().isStmtBranch() &&
26440b57cec5SDimitry Andric          "Other kinds of branches are handled separately!");
26450b57cec5SDimitry Andric 
26460b57cec5SDimitry Andric   // For logical operations, we still have the case where some branches
26470b57cec5SDimitry Andric   // use the traditional "merge" approach and others sink the branch
26480b57cec5SDimitry Andric   // directly into the basic blocks representing the logical operation.
26490b57cec5SDimitry Andric   // We need to distinguish between those two cases here.
26500b57cec5SDimitry Andric 
26510b57cec5SDimitry Andric   // The invariants are still shifting, but it is possible that the
26520b57cec5SDimitry Andric   // last element in a CFGBlock is not a CFGStmt.  Look for the last
26530b57cec5SDimitry Andric   // CFGStmt as the value of the condition.
265406c3fb27SDimitry Andric   for (CFGElement Elem : llvm::reverse(*B)) {
2655bdd1243dSDimitry Andric     std::optional<CFGStmt> CS = Elem.getAs<CFGStmt>();
26560b57cec5SDimitry Andric     if (!CS)
26570b57cec5SDimitry Andric       continue;
26580b57cec5SDimitry Andric     const Stmt *LastStmt = CS->getStmt();
26590b57cec5SDimitry Andric     assert(LastStmt == Condition || LastStmt == getRightmostLeaf(Condition));
26600b57cec5SDimitry Andric     return LastStmt;
26610b57cec5SDimitry Andric   }
26620b57cec5SDimitry Andric   llvm_unreachable("could not resolve condition");
26630b57cec5SDimitry Andric }
26640b57cec5SDimitry Andric 
2665e8d8bef9SDimitry Andric using ObjCForLctxPair =
2666e8d8bef9SDimitry Andric     std::pair<const ObjCForCollectionStmt *, const LocationContext *>;
2667e8d8bef9SDimitry Andric 
REGISTER_MAP_WITH_PROGRAMSTATE(ObjCForHasMoreIterations,ObjCForLctxPair,bool)2668e8d8bef9SDimitry Andric REGISTER_MAP_WITH_PROGRAMSTATE(ObjCForHasMoreIterations, ObjCForLctxPair, bool)
2669e8d8bef9SDimitry Andric 
2670e8d8bef9SDimitry Andric ProgramStateRef ExprEngine::setWhetherHasMoreIteration(
2671e8d8bef9SDimitry Andric     ProgramStateRef State, const ObjCForCollectionStmt *O,
2672e8d8bef9SDimitry Andric     const LocationContext *LC, bool HasMoreIteraton) {
2673e8d8bef9SDimitry Andric   assert(!State->contains<ObjCForHasMoreIterations>({O, LC}));
2674e8d8bef9SDimitry Andric   return State->set<ObjCForHasMoreIterations>({O, LC}, HasMoreIteraton);
2675e8d8bef9SDimitry Andric }
2676e8d8bef9SDimitry Andric 
2677e8d8bef9SDimitry Andric ProgramStateRef
removeIterationState(ProgramStateRef State,const ObjCForCollectionStmt * O,const LocationContext * LC)2678e8d8bef9SDimitry Andric ExprEngine::removeIterationState(ProgramStateRef State,
2679e8d8bef9SDimitry Andric                                  const ObjCForCollectionStmt *O,
2680e8d8bef9SDimitry Andric                                  const LocationContext *LC) {
2681e8d8bef9SDimitry Andric   assert(State->contains<ObjCForHasMoreIterations>({O, LC}));
2682e8d8bef9SDimitry Andric   return State->remove<ObjCForHasMoreIterations>({O, LC});
2683e8d8bef9SDimitry Andric }
2684e8d8bef9SDimitry Andric 
hasMoreIteration(ProgramStateRef State,const ObjCForCollectionStmt * O,const LocationContext * LC)2685e8d8bef9SDimitry Andric bool ExprEngine::hasMoreIteration(ProgramStateRef State,
2686e8d8bef9SDimitry Andric                                   const ObjCForCollectionStmt *O,
2687e8d8bef9SDimitry Andric                                   const LocationContext *LC) {
2688e8d8bef9SDimitry Andric   assert(State->contains<ObjCForHasMoreIterations>({O, LC}));
2689e8d8bef9SDimitry Andric   return *State->get<ObjCForHasMoreIterations>({O, LC});
2690e8d8bef9SDimitry Andric }
2691e8d8bef9SDimitry Andric 
2692e8d8bef9SDimitry Andric /// Split the state on whether there are any more iterations left for this loop.
2693bdd1243dSDimitry Andric /// Returns a (HasMoreIteration, HasNoMoreIteration) pair, or std::nullopt when
2694bdd1243dSDimitry Andric /// the acquisition of the loop condition value failed.
2695bdd1243dSDimitry Andric static std::optional<std::pair<ProgramStateRef, ProgramStateRef>>
assumeCondition(const Stmt * Condition,ExplodedNode * N)2696e8d8bef9SDimitry Andric assumeCondition(const Stmt *Condition, ExplodedNode *N) {
2697e8d8bef9SDimitry Andric   ProgramStateRef State = N->getState();
2698e8d8bef9SDimitry Andric   if (const auto *ObjCFor = dyn_cast<ObjCForCollectionStmt>(Condition)) {
2699e8d8bef9SDimitry Andric     bool HasMoreIteraton =
2700e8d8bef9SDimitry Andric         ExprEngine::hasMoreIteration(State, ObjCFor, N->getLocationContext());
2701e8d8bef9SDimitry Andric     // Checkers have already ran on branch conditions, so the current
2702e8d8bef9SDimitry Andric     // information as to whether the loop has more iteration becomes outdated
2703e8d8bef9SDimitry Andric     // after this point.
2704e8d8bef9SDimitry Andric     State = ExprEngine::removeIterationState(State, ObjCFor,
2705e8d8bef9SDimitry Andric                                              N->getLocationContext());
2706e8d8bef9SDimitry Andric     if (HasMoreIteraton)
2707e8d8bef9SDimitry Andric       return std::pair<ProgramStateRef, ProgramStateRef>{State, nullptr};
2708e8d8bef9SDimitry Andric     else
2709e8d8bef9SDimitry Andric       return std::pair<ProgramStateRef, ProgramStateRef>{nullptr, State};
2710e8d8bef9SDimitry Andric   }
2711e8d8bef9SDimitry Andric   SVal X = State->getSVal(Condition, N->getLocationContext());
2712e8d8bef9SDimitry Andric 
2713e8d8bef9SDimitry Andric   if (X.isUnknownOrUndef()) {
2714e8d8bef9SDimitry Andric     // Give it a chance to recover from unknown.
2715e8d8bef9SDimitry Andric     if (const auto *Ex = dyn_cast<Expr>(Condition)) {
2716e8d8bef9SDimitry Andric       if (Ex->getType()->isIntegralOrEnumerationType()) {
2717e8d8bef9SDimitry Andric         // Try to recover some path-sensitivity.  Right now casts of symbolic
2718e8d8bef9SDimitry Andric         // integers that promote their values are currently not tracked well.
2719e8d8bef9SDimitry Andric         // If 'Condition' is such an expression, try and recover the
2720e8d8bef9SDimitry Andric         // underlying value and use that instead.
2721e8d8bef9SDimitry Andric         SVal recovered =
2722e8d8bef9SDimitry Andric             RecoverCastedSymbol(State, Condition, N->getLocationContext(),
2723e8d8bef9SDimitry Andric                                 N->getState()->getStateManager().getContext());
2724e8d8bef9SDimitry Andric 
2725e8d8bef9SDimitry Andric         if (!recovered.isUnknown()) {
2726e8d8bef9SDimitry Andric           X = recovered;
2727e8d8bef9SDimitry Andric         }
2728e8d8bef9SDimitry Andric       }
2729e8d8bef9SDimitry Andric     }
2730e8d8bef9SDimitry Andric   }
2731e8d8bef9SDimitry Andric 
2732e8d8bef9SDimitry Andric   // If the condition is still unknown, give up.
2733e8d8bef9SDimitry Andric   if (X.isUnknownOrUndef())
2734bdd1243dSDimitry Andric     return std::nullopt;
2735e8d8bef9SDimitry Andric 
2736e8d8bef9SDimitry Andric   DefinedSVal V = X.castAs<DefinedSVal>();
2737e8d8bef9SDimitry Andric 
2738e8d8bef9SDimitry Andric   ProgramStateRef StTrue, StFalse;
2739e8d8bef9SDimitry Andric   return State->assume(V);
2740e8d8bef9SDimitry Andric }
2741e8d8bef9SDimitry Andric 
processBranch(const Stmt * Condition,NodeBuilderContext & BldCtx,ExplodedNode * Pred,ExplodedNodeSet & Dst,const CFGBlock * DstT,const CFGBlock * DstF)27420b57cec5SDimitry Andric void ExprEngine::processBranch(const Stmt *Condition,
27430b57cec5SDimitry Andric                                NodeBuilderContext& BldCtx,
27440b57cec5SDimitry Andric                                ExplodedNode *Pred,
27450b57cec5SDimitry Andric                                ExplodedNodeSet &Dst,
27460b57cec5SDimitry Andric                                const CFGBlock *DstT,
27470b57cec5SDimitry Andric                                const CFGBlock *DstF) {
27480b57cec5SDimitry Andric   assert((!Condition || !isa<CXXBindTemporaryExpr>(Condition)) &&
27490b57cec5SDimitry Andric          "CXXBindTemporaryExprs are handled by processBindTemporary.");
27500b57cec5SDimitry Andric   const LocationContext *LCtx = Pred->getLocationContext();
27510b57cec5SDimitry Andric   PrettyStackTraceLocationContext StackCrashInfo(LCtx);
27520b57cec5SDimitry Andric   currBldrCtx = &BldCtx;
27530b57cec5SDimitry Andric 
27540b57cec5SDimitry Andric   // Check for NULL conditions; e.g. "for(;;)"
27550b57cec5SDimitry Andric   if (!Condition) {
27560b57cec5SDimitry Andric     BranchNodeBuilder NullCondBldr(Pred, Dst, BldCtx, DstT, DstF);
27570b57cec5SDimitry Andric     NullCondBldr.markInfeasible(false);
27580b57cec5SDimitry Andric     NullCondBldr.generateNode(Pred->getState(), true, Pred);
27590b57cec5SDimitry Andric     return;
27600b57cec5SDimitry Andric   }
27610b57cec5SDimitry Andric 
27620b57cec5SDimitry Andric   if (const auto *Ex = dyn_cast<Expr>(Condition))
27630b57cec5SDimitry Andric     Condition = Ex->IgnoreParens();
27640b57cec5SDimitry Andric 
27650b57cec5SDimitry Andric   Condition = ResolveCondition(Condition, BldCtx.getBlock());
27660b57cec5SDimitry Andric   PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
27670b57cec5SDimitry Andric                                 Condition->getBeginLoc(),
27680b57cec5SDimitry Andric                                 "Error evaluating branch");
27690b57cec5SDimitry Andric 
27700b57cec5SDimitry Andric   ExplodedNodeSet CheckersOutSet;
27710b57cec5SDimitry Andric   getCheckerManager().runCheckersForBranchCondition(Condition, CheckersOutSet,
27720b57cec5SDimitry Andric                                                     Pred, *this);
27730b57cec5SDimitry Andric   // We generated only sinks.
27740b57cec5SDimitry Andric   if (CheckersOutSet.empty())
27750b57cec5SDimitry Andric     return;
27760b57cec5SDimitry Andric 
27770b57cec5SDimitry Andric   BranchNodeBuilder builder(CheckersOutSet, Dst, BldCtx, DstT, DstF);
2778e8d8bef9SDimitry Andric   for (ExplodedNode *PredN : CheckersOutSet) {
2779e8d8bef9SDimitry Andric     if (PredN->isSink())
27800b57cec5SDimitry Andric       continue;
27810b57cec5SDimitry Andric 
2782e8d8bef9SDimitry Andric     ProgramStateRef PrevState = PredN->getState();
27830b57cec5SDimitry Andric 
27840b57cec5SDimitry Andric     ProgramStateRef StTrue, StFalse;
2785e8d8bef9SDimitry Andric     if (const auto KnownCondValueAssumption = assumeCondition(Condition, PredN))
2786e8d8bef9SDimitry Andric       std::tie(StTrue, StFalse) = *KnownCondValueAssumption;
2787e8d8bef9SDimitry Andric     else {
2788e8d8bef9SDimitry Andric       assert(!isa<ObjCForCollectionStmt>(Condition));
2789e8d8bef9SDimitry Andric       builder.generateNode(PrevState, true, PredN);
2790e8d8bef9SDimitry Andric       builder.generateNode(PrevState, false, PredN);
2791e8d8bef9SDimitry Andric       continue;
2792e8d8bef9SDimitry Andric     }
2793e8d8bef9SDimitry Andric     if (StTrue && StFalse)
2794349cc55cSDimitry Andric       assert(!isa<ObjCForCollectionStmt>(Condition));
27950b57cec5SDimitry Andric 
27960b57cec5SDimitry Andric     // Process the true branch.
27970b57cec5SDimitry Andric     if (builder.isFeasible(true)) {
27980b57cec5SDimitry Andric       if (StTrue)
2799e8d8bef9SDimitry Andric         builder.generateNode(StTrue, true, PredN);
28000b57cec5SDimitry Andric       else
28010b57cec5SDimitry Andric         builder.markInfeasible(true);
28020b57cec5SDimitry Andric     }
28030b57cec5SDimitry Andric 
28040b57cec5SDimitry Andric     // Process the false branch.
28050b57cec5SDimitry Andric     if (builder.isFeasible(false)) {
28060b57cec5SDimitry Andric       if (StFalse)
2807e8d8bef9SDimitry Andric         builder.generateNode(StFalse, false, PredN);
28080b57cec5SDimitry Andric       else
28090b57cec5SDimitry Andric         builder.markInfeasible(false);
28100b57cec5SDimitry Andric     }
28110b57cec5SDimitry Andric   }
28120b57cec5SDimitry Andric   currBldrCtx = nullptr;
28130b57cec5SDimitry Andric }
28140b57cec5SDimitry Andric 
28150b57cec5SDimitry Andric /// The GDM component containing the set of global variables which have been
28160b57cec5SDimitry Andric /// previously initialized with explicit initializers.
REGISTER_TRAIT_WITH_PROGRAMSTATE(InitializedGlobalsSet,llvm::ImmutableSet<const VarDecl * >)28170b57cec5SDimitry Andric REGISTER_TRAIT_WITH_PROGRAMSTATE(InitializedGlobalsSet,
28180b57cec5SDimitry Andric                                  llvm::ImmutableSet<const VarDecl *>)
28190b57cec5SDimitry Andric 
28200b57cec5SDimitry Andric void ExprEngine::processStaticInitializer(const DeclStmt *DS,
28210b57cec5SDimitry Andric                                           NodeBuilderContext &BuilderCtx,
28220b57cec5SDimitry Andric                                           ExplodedNode *Pred,
28230b57cec5SDimitry Andric                                           ExplodedNodeSet &Dst,
28240b57cec5SDimitry Andric                                           const CFGBlock *DstT,
28250b57cec5SDimitry Andric                                           const CFGBlock *DstF) {
28260b57cec5SDimitry Andric   PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
28270b57cec5SDimitry Andric   currBldrCtx = &BuilderCtx;
28280b57cec5SDimitry Andric 
28290b57cec5SDimitry Andric   const auto *VD = cast<VarDecl>(DS->getSingleDecl());
28300b57cec5SDimitry Andric   ProgramStateRef state = Pred->getState();
28310b57cec5SDimitry Andric   bool initHasRun = state->contains<InitializedGlobalsSet>(VD);
28320b57cec5SDimitry Andric   BranchNodeBuilder builder(Pred, Dst, BuilderCtx, DstT, DstF);
28330b57cec5SDimitry Andric 
28340b57cec5SDimitry Andric   if (!initHasRun) {
28350b57cec5SDimitry Andric     state = state->add<InitializedGlobalsSet>(VD);
28360b57cec5SDimitry Andric   }
28370b57cec5SDimitry Andric 
28380b57cec5SDimitry Andric   builder.generateNode(state, initHasRun, Pred);
28390b57cec5SDimitry Andric   builder.markInfeasible(!initHasRun);
28400b57cec5SDimitry Andric 
28410b57cec5SDimitry Andric   currBldrCtx = nullptr;
28420b57cec5SDimitry Andric }
28430b57cec5SDimitry Andric 
28440b57cec5SDimitry Andric /// processIndirectGoto - Called by CoreEngine.  Used to generate successor
28450b57cec5SDimitry Andric ///  nodes by processing the 'effects' of a computed goto jump.
processIndirectGoto(IndirectGotoNodeBuilder & builder)28460b57cec5SDimitry Andric void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) {
28470b57cec5SDimitry Andric   ProgramStateRef state = builder.getState();
28480b57cec5SDimitry Andric   SVal V = state->getSVal(builder.getTarget(), builder.getLocationContext());
28490b57cec5SDimitry Andric 
28500b57cec5SDimitry Andric   // Three possibilities:
28510b57cec5SDimitry Andric   //
28520b57cec5SDimitry Andric   //   (1) We know the computed label.
28530b57cec5SDimitry Andric   //   (2) The label is NULL (or some other constant), or Undefined.
28540b57cec5SDimitry Andric   //   (3) We have no clue about the label.  Dispatch to all targets.
28550b57cec5SDimitry Andric   //
28560b57cec5SDimitry Andric 
28570b57cec5SDimitry Andric   using iterator = IndirectGotoNodeBuilder::iterator;
28580b57cec5SDimitry Andric 
2859bdd1243dSDimitry Andric   if (std::optional<loc::GotoLabel> LV = V.getAs<loc::GotoLabel>()) {
28600b57cec5SDimitry Andric     const LabelDecl *L = LV->getLabel();
28610b57cec5SDimitry Andric 
286206c3fb27SDimitry Andric     for (iterator Succ : builder) {
286306c3fb27SDimitry Andric       if (Succ.getLabel() == L) {
286406c3fb27SDimitry Andric         builder.generateNode(Succ, state);
28650b57cec5SDimitry Andric         return;
28660b57cec5SDimitry Andric       }
28670b57cec5SDimitry Andric     }
28680b57cec5SDimitry Andric 
28690b57cec5SDimitry Andric     llvm_unreachable("No block with label.");
28700b57cec5SDimitry Andric   }
28710b57cec5SDimitry Andric 
287281ad6265SDimitry Andric   if (isa<UndefinedVal, loc::ConcreteInt>(V)) {
28730b57cec5SDimitry Andric     // Dispatch to the first target and mark it as a sink.
28740b57cec5SDimitry Andric     //ExplodedNode* N = builder.generateNode(builder.begin(), state, true);
28750b57cec5SDimitry Andric     // FIXME: add checker visit.
28760b57cec5SDimitry Andric     //    UndefBranches.insert(N);
28770b57cec5SDimitry Andric     return;
28780b57cec5SDimitry Andric   }
28790b57cec5SDimitry Andric 
28800b57cec5SDimitry Andric   // This is really a catch-all.  We don't support symbolics yet.
28810b57cec5SDimitry Andric   // FIXME: Implement dispatch for symbolic pointers.
28820b57cec5SDimitry Andric 
288306c3fb27SDimitry Andric   for (iterator Succ : builder)
288406c3fb27SDimitry Andric     builder.generateNode(Succ, state);
28850b57cec5SDimitry Andric }
28860b57cec5SDimitry Andric 
processBeginOfFunction(NodeBuilderContext & BC,ExplodedNode * Pred,ExplodedNodeSet & Dst,const BlockEdge & L)28870b57cec5SDimitry Andric void ExprEngine::processBeginOfFunction(NodeBuilderContext &BC,
28880b57cec5SDimitry Andric                                         ExplodedNode *Pred,
28890b57cec5SDimitry Andric                                         ExplodedNodeSet &Dst,
28900b57cec5SDimitry Andric                                         const BlockEdge &L) {
28910b57cec5SDimitry Andric   SaveAndRestore<const NodeBuilderContext *> NodeContextRAII(currBldrCtx, &BC);
28920b57cec5SDimitry Andric   getCheckerManager().runCheckersForBeginFunction(Dst, L, Pred, *this);
28930b57cec5SDimitry Andric }
28940b57cec5SDimitry Andric 
28950b57cec5SDimitry Andric /// ProcessEndPath - Called by CoreEngine.  Used to generate end-of-path
28960b57cec5SDimitry Andric ///  nodes when the control reaches the end of a function.
processEndOfFunction(NodeBuilderContext & BC,ExplodedNode * Pred,const ReturnStmt * RS)28970b57cec5SDimitry Andric void ExprEngine::processEndOfFunction(NodeBuilderContext& BC,
28980b57cec5SDimitry Andric                                       ExplodedNode *Pred,
28990b57cec5SDimitry Andric                                       const ReturnStmt *RS) {
29000b57cec5SDimitry Andric   ProgramStateRef State = Pred->getState();
29010b57cec5SDimitry Andric 
29020b57cec5SDimitry Andric   if (!Pred->getStackFrame()->inTopFrame())
29030b57cec5SDimitry Andric     State = finishArgumentConstruction(
29040b57cec5SDimitry Andric         State, *getStateManager().getCallEventManager().getCaller(
29050b57cec5SDimitry Andric                    Pred->getStackFrame(), Pred->getState()));
29060b57cec5SDimitry Andric 
29070b57cec5SDimitry Andric   // FIXME: We currently cannot assert that temporaries are clear, because
29080b57cec5SDimitry Andric   // lifetime extended temporaries are not always modelled correctly. In some
29090b57cec5SDimitry Andric   // cases when we materialize the temporary, we do
29100b57cec5SDimitry Andric   // createTemporaryRegionIfNeeded(), and the region changes, and also the
29110b57cec5SDimitry Andric   // respective destructor becomes automatic from temporary. So for now clean up
29120b57cec5SDimitry Andric   // the state manually before asserting. Ideally, this braced block of code
29130b57cec5SDimitry Andric   // should go away.
29140b57cec5SDimitry Andric   {
29150b57cec5SDimitry Andric     const LocationContext *FromLC = Pred->getLocationContext();
29160b57cec5SDimitry Andric     const LocationContext *ToLC = FromLC->getStackFrame()->getParent();
29170b57cec5SDimitry Andric     const LocationContext *LC = FromLC;
29180b57cec5SDimitry Andric     while (LC != ToLC) {
29190b57cec5SDimitry Andric       assert(LC && "ToLC must be a parent of FromLC!");
29200b57cec5SDimitry Andric       for (auto I : State->get<ObjectsUnderConstruction>())
29210b57cec5SDimitry Andric         if (I.first.getLocationContext() == LC) {
29220b57cec5SDimitry Andric           // The comment above only pardons us for not cleaning up a
29230b57cec5SDimitry Andric           // temporary destructor. If any other statements are found here,
29240b57cec5SDimitry Andric           // it must be a separate problem.
29250b57cec5SDimitry Andric           assert(I.first.getItem().getKind() ==
29260b57cec5SDimitry Andric                      ConstructionContextItem::TemporaryDestructorKind ||
29270b57cec5SDimitry Andric                  I.first.getItem().getKind() ==
29280b57cec5SDimitry Andric                      ConstructionContextItem::ElidedDestructorKind);
29290b57cec5SDimitry Andric           State = State->remove<ObjectsUnderConstruction>(I.first);
29300b57cec5SDimitry Andric         }
29310b57cec5SDimitry Andric       LC = LC->getParent();
29320b57cec5SDimitry Andric     }
29330b57cec5SDimitry Andric   }
29340b57cec5SDimitry Andric 
29350b57cec5SDimitry Andric   // Perform the transition with cleanups.
29360b57cec5SDimitry Andric   if (State != Pred->getState()) {
29370b57cec5SDimitry Andric     ExplodedNodeSet PostCleanup;
29380b57cec5SDimitry Andric     NodeBuilder Bldr(Pred, PostCleanup, BC);
29390b57cec5SDimitry Andric     Pred = Bldr.generateNode(Pred->getLocation(), State, Pred);
29400b57cec5SDimitry Andric     if (!Pred) {
29410b57cec5SDimitry Andric       // The node with clean temporaries already exists. We might have reached
29420b57cec5SDimitry Andric       // it on a path on which we initialize different temporaries.
29430b57cec5SDimitry Andric       return;
29440b57cec5SDimitry Andric     }
29450b57cec5SDimitry Andric   }
29460b57cec5SDimitry Andric 
29470b57cec5SDimitry Andric   assert(areAllObjectsFullyConstructed(Pred->getState(),
29480b57cec5SDimitry Andric                                        Pred->getLocationContext(),
29490b57cec5SDimitry Andric                                        Pred->getStackFrame()->getParent()));
29500b57cec5SDimitry Andric 
29510b57cec5SDimitry Andric   PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
29520b57cec5SDimitry Andric 
29530b57cec5SDimitry Andric   ExplodedNodeSet Dst;
29540b57cec5SDimitry Andric   if (Pred->getLocationContext()->inTopFrame()) {
29550b57cec5SDimitry Andric     // Remove dead symbols.
29560b57cec5SDimitry Andric     ExplodedNodeSet AfterRemovedDead;
29570b57cec5SDimitry Andric     removeDeadOnEndOfFunction(BC, Pred, AfterRemovedDead);
29580b57cec5SDimitry Andric 
29590b57cec5SDimitry Andric     // Notify checkers.
29600b57cec5SDimitry Andric     for (const auto I : AfterRemovedDead)
29610b57cec5SDimitry Andric       getCheckerManager().runCheckersForEndFunction(BC, Dst, I, *this, RS);
29620b57cec5SDimitry Andric   } else {
29630b57cec5SDimitry Andric     getCheckerManager().runCheckersForEndFunction(BC, Dst, Pred, *this, RS);
29640b57cec5SDimitry Andric   }
29650b57cec5SDimitry Andric 
29660b57cec5SDimitry Andric   Engine.enqueueEndOfFunction(Dst, RS);
29670b57cec5SDimitry Andric }
29680b57cec5SDimitry Andric 
29690b57cec5SDimitry Andric /// ProcessSwitch - Called by CoreEngine.  Used to generate successor
29700b57cec5SDimitry Andric ///  nodes by processing the 'effects' of a switch statement.
processSwitch(SwitchNodeBuilder & builder)29710b57cec5SDimitry Andric void ExprEngine::processSwitch(SwitchNodeBuilder& builder) {
29720b57cec5SDimitry Andric   using iterator = SwitchNodeBuilder::iterator;
29730b57cec5SDimitry Andric 
29740b57cec5SDimitry Andric   ProgramStateRef state = builder.getState();
29750b57cec5SDimitry Andric   const Expr *CondE = builder.getCondition();
29760b57cec5SDimitry Andric   SVal  CondV_untested = state->getSVal(CondE, builder.getLocationContext());
29770b57cec5SDimitry Andric 
29780b57cec5SDimitry Andric   if (CondV_untested.isUndef()) {
29790b57cec5SDimitry Andric     //ExplodedNode* N = builder.generateDefaultCaseNode(state, true);
29800b57cec5SDimitry Andric     // FIXME: add checker
29810b57cec5SDimitry Andric     //UndefBranches.insert(N);
29820b57cec5SDimitry Andric 
29830b57cec5SDimitry Andric     return;
29840b57cec5SDimitry Andric   }
29850b57cec5SDimitry Andric   DefinedOrUnknownSVal CondV = CondV_untested.castAs<DefinedOrUnknownSVal>();
29860b57cec5SDimitry Andric 
29870b57cec5SDimitry Andric   ProgramStateRef DefaultSt = state;
29880b57cec5SDimitry Andric 
29890b57cec5SDimitry Andric   iterator I = builder.begin(), EI = builder.end();
29900b57cec5SDimitry Andric   bool defaultIsFeasible = I == EI;
29910b57cec5SDimitry Andric 
29920b57cec5SDimitry Andric   for ( ; I != EI; ++I) {
29930b57cec5SDimitry Andric     // Successor may be pruned out during CFG construction.
29940b57cec5SDimitry Andric     if (!I.getBlock())
29950b57cec5SDimitry Andric       continue;
29960b57cec5SDimitry Andric 
29970b57cec5SDimitry Andric     const CaseStmt *Case = I.getCase();
29980b57cec5SDimitry Andric 
29990b57cec5SDimitry Andric     // Evaluate the LHS of the case value.
30000b57cec5SDimitry Andric     llvm::APSInt V1 = Case->getLHS()->EvaluateKnownConstInt(getContext());
30010b57cec5SDimitry Andric     assert(V1.getBitWidth() == getContext().getIntWidth(CondE->getType()));
30020b57cec5SDimitry Andric 
30030b57cec5SDimitry Andric     // Get the RHS of the case, if it exists.
30040b57cec5SDimitry Andric     llvm::APSInt V2;
30050b57cec5SDimitry Andric     if (const Expr *E = Case->getRHS())
30060b57cec5SDimitry Andric       V2 = E->EvaluateKnownConstInt(getContext());
30070b57cec5SDimitry Andric     else
30080b57cec5SDimitry Andric       V2 = V1;
30090b57cec5SDimitry Andric 
30100b57cec5SDimitry Andric     ProgramStateRef StateCase;
3011bdd1243dSDimitry Andric     if (std::optional<NonLoc> NL = CondV.getAs<NonLoc>())
30120b57cec5SDimitry Andric       std::tie(StateCase, DefaultSt) =
30130b57cec5SDimitry Andric           DefaultSt->assumeInclusiveRange(*NL, V1, V2);
30140b57cec5SDimitry Andric     else // UnknownVal
30150b57cec5SDimitry Andric       StateCase = DefaultSt;
30160b57cec5SDimitry Andric 
30170b57cec5SDimitry Andric     if (StateCase)
30180b57cec5SDimitry Andric       builder.generateCaseStmtNode(I, StateCase);
30190b57cec5SDimitry Andric 
30200b57cec5SDimitry Andric     // Now "assume" that the case doesn't match.  Add this state
30210b57cec5SDimitry Andric     // to the default state (if it is feasible).
30220b57cec5SDimitry Andric     if (DefaultSt)
30230b57cec5SDimitry Andric       defaultIsFeasible = true;
30240b57cec5SDimitry Andric     else {
30250b57cec5SDimitry Andric       defaultIsFeasible = false;
30260b57cec5SDimitry Andric       break;
30270b57cec5SDimitry Andric     }
30280b57cec5SDimitry Andric   }
30290b57cec5SDimitry Andric 
30300b57cec5SDimitry Andric   if (!defaultIsFeasible)
30310b57cec5SDimitry Andric     return;
30320b57cec5SDimitry Andric 
30330b57cec5SDimitry Andric   // If we have switch(enum value), the default branch is not
30340b57cec5SDimitry Andric   // feasible if all of the enum constants not covered by 'case:' statements
30350b57cec5SDimitry Andric   // are not feasible values for the switch condition.
30360b57cec5SDimitry Andric   //
30370b57cec5SDimitry Andric   // Note that this isn't as accurate as it could be.  Even if there isn't
30380b57cec5SDimitry Andric   // a case for a particular enum value as long as that enum value isn't
30390b57cec5SDimitry Andric   // feasible then it shouldn't be considered for making 'default:' reachable.
30400b57cec5SDimitry Andric   const SwitchStmt *SS = builder.getSwitch();
30410b57cec5SDimitry Andric   const Expr *CondExpr = SS->getCond()->IgnoreParenImpCasts();
30420b57cec5SDimitry Andric   if (CondExpr->getType()->getAs<EnumType>()) {
30430b57cec5SDimitry Andric     if (SS->isAllEnumCasesCovered())
30440b57cec5SDimitry Andric       return;
30450b57cec5SDimitry Andric   }
30460b57cec5SDimitry Andric 
30470b57cec5SDimitry Andric   builder.generateDefaultCaseNode(DefaultSt);
30480b57cec5SDimitry Andric }
30490b57cec5SDimitry Andric 
30500b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
30510b57cec5SDimitry Andric // Transfer functions: Loads and stores.
30520b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
30530b57cec5SDimitry Andric 
VisitCommonDeclRefExpr(const Expr * Ex,const NamedDecl * D,ExplodedNode * Pred,ExplodedNodeSet & Dst)30540b57cec5SDimitry Andric void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
30550b57cec5SDimitry Andric                                         ExplodedNode *Pred,
30560b57cec5SDimitry Andric                                         ExplodedNodeSet &Dst) {
30570b57cec5SDimitry Andric   StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
30580b57cec5SDimitry Andric 
30590b57cec5SDimitry Andric   ProgramStateRef state = Pred->getState();
30600b57cec5SDimitry Andric   const LocationContext *LCtx = Pred->getLocationContext();
30610b57cec5SDimitry Andric 
30620b57cec5SDimitry Andric   if (const auto *VD = dyn_cast<VarDecl>(D)) {
30630b57cec5SDimitry Andric     // C permits "extern void v", and if you cast the address to a valid type,
30640b57cec5SDimitry Andric     // you can even do things with it. We simply pretend
30650b57cec5SDimitry Andric     assert(Ex->isGLValue() || VD->getType()->isVoidType());
30660b57cec5SDimitry Andric     const LocationContext *LocCtxt = Pred->getLocationContext();
30670b57cec5SDimitry Andric     const Decl *D = LocCtxt->getDecl();
30680b57cec5SDimitry Andric     const auto *MD = dyn_cast_or_null<CXXMethodDecl>(D);
30690b57cec5SDimitry Andric     const auto *DeclRefEx = dyn_cast<DeclRefExpr>(Ex);
3070bdd1243dSDimitry Andric     std::optional<std::pair<SVal, QualType>> VInfo;
30710b57cec5SDimitry Andric 
30720b57cec5SDimitry Andric     if (AMgr.options.ShouldInlineLambdas && DeclRefEx &&
30730b57cec5SDimitry Andric         DeclRefEx->refersToEnclosingVariableOrCapture() && MD &&
30740b57cec5SDimitry Andric         MD->getParent()->isLambda()) {
30750b57cec5SDimitry Andric       // Lookup the field of the lambda.
30760b57cec5SDimitry Andric       const CXXRecordDecl *CXXRec = MD->getParent();
3077bdd1243dSDimitry Andric       llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;
30780b57cec5SDimitry Andric       FieldDecl *LambdaThisCaptureField;
30790b57cec5SDimitry Andric       CXXRec->getCaptureFields(LambdaCaptureFields, LambdaThisCaptureField);
30800b57cec5SDimitry Andric 
30810b57cec5SDimitry Andric       // Sema follows a sequence of complex rules to determine whether the
30820b57cec5SDimitry Andric       // variable should be captured.
30830b57cec5SDimitry Andric       if (const FieldDecl *FD = LambdaCaptureFields[VD]) {
30840b57cec5SDimitry Andric         Loc CXXThis =
30850b57cec5SDimitry Andric             svalBuilder.getCXXThis(MD, LocCtxt->getStackFrame());
30860b57cec5SDimitry Andric         SVal CXXThisVal = state->getSVal(CXXThis);
30870b57cec5SDimitry Andric         VInfo = std::make_pair(state->getLValue(FD, CXXThisVal), FD->getType());
30880b57cec5SDimitry Andric       }
30890b57cec5SDimitry Andric     }
30900b57cec5SDimitry Andric 
30910b57cec5SDimitry Andric     if (!VInfo)
30920b57cec5SDimitry Andric       VInfo = std::make_pair(state->getLValue(VD, LocCtxt), VD->getType());
30930b57cec5SDimitry Andric 
30940b57cec5SDimitry Andric     SVal V = VInfo->first;
30950b57cec5SDimitry Andric     bool IsReference = VInfo->second->isReferenceType();
30960b57cec5SDimitry Andric 
30970b57cec5SDimitry Andric     // For references, the 'lvalue' is the pointer address stored in the
30980b57cec5SDimitry Andric     // reference region.
30990b57cec5SDimitry Andric     if (IsReference) {
31000b57cec5SDimitry Andric       if (const MemRegion *R = V.getAsRegion())
31010b57cec5SDimitry Andric         V = state->getSVal(R);
31020b57cec5SDimitry Andric       else
31030b57cec5SDimitry Andric         V = UnknownVal();
31040b57cec5SDimitry Andric     }
31050b57cec5SDimitry Andric 
31060b57cec5SDimitry Andric     Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,
31070b57cec5SDimitry Andric                       ProgramPoint::PostLValueKind);
31080b57cec5SDimitry Andric     return;
31090b57cec5SDimitry Andric   }
31100b57cec5SDimitry Andric   if (const auto *ED = dyn_cast<EnumConstantDecl>(D)) {
31110b57cec5SDimitry Andric     assert(!Ex->isGLValue());
31120b57cec5SDimitry Andric     SVal V = svalBuilder.makeIntVal(ED->getInitVal());
31130b57cec5SDimitry Andric     Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V));
31140b57cec5SDimitry Andric     return;
31150b57cec5SDimitry Andric   }
31160b57cec5SDimitry Andric   if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
31170b57cec5SDimitry Andric     SVal V = svalBuilder.getFunctionPointer(FD);
31180b57cec5SDimitry Andric     Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,
31190b57cec5SDimitry Andric                       ProgramPoint::PostLValueKind);
31200b57cec5SDimitry Andric     return;
31210b57cec5SDimitry Andric   }
3122349cc55cSDimitry Andric   if (isa<FieldDecl, IndirectFieldDecl>(D)) {
3123e8d8bef9SDimitry Andric     // Delegate all work related to pointer to members to the surrounding
3124e8d8bef9SDimitry Andric     // operator&.
31250b57cec5SDimitry Andric     return;
31260b57cec5SDimitry Andric   }
312781ad6265SDimitry Andric   if (const auto *BD = dyn_cast<BindingDecl>(D)) {
312881ad6265SDimitry Andric     const auto *DD = cast<DecompositionDecl>(BD->getDecomposedDecl());
312981ad6265SDimitry Andric 
313081ad6265SDimitry Andric     SVal Base = state->getLValue(DD, LCtx);
313181ad6265SDimitry Andric     if (DD->getType()->isReferenceType()) {
3132972a253aSDimitry Andric       if (const MemRegion *R = Base.getAsRegion())
3133972a253aSDimitry Andric         Base = state->getSVal(R);
3134972a253aSDimitry Andric       else
3135972a253aSDimitry Andric         Base = UnknownVal();
313681ad6265SDimitry Andric     }
313781ad6265SDimitry Andric 
313881ad6265SDimitry Andric     SVal V = UnknownVal();
313981ad6265SDimitry Andric 
314081ad6265SDimitry Andric     // Handle binding to data members
314181ad6265SDimitry Andric     if (const auto *ME = dyn_cast<MemberExpr>(BD->getBinding())) {
314281ad6265SDimitry Andric       const auto *Field = cast<FieldDecl>(ME->getMemberDecl());
314381ad6265SDimitry Andric       V = state->getLValue(Field, Base);
314481ad6265SDimitry Andric     }
314581ad6265SDimitry Andric     // Handle binding to arrays
314681ad6265SDimitry Andric     else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(BD->getBinding())) {
314781ad6265SDimitry Andric       SVal Idx = state->getSVal(ASE->getIdx(), LCtx);
314881ad6265SDimitry Andric 
314981ad6265SDimitry Andric       // Note: the index of an element in a structured binding is automatically
315081ad6265SDimitry Andric       // created and it is a unique identifier of the specific element. Thus it
315181ad6265SDimitry Andric       // cannot be a value that varies at runtime.
315281ad6265SDimitry Andric       assert(Idx.isConstant() && "BindingDecl array index is not a constant!");
315381ad6265SDimitry Andric 
315481ad6265SDimitry Andric       V = state->getLValue(BD->getType(), Idx, Base);
315581ad6265SDimitry Andric     }
3156972a253aSDimitry Andric     // Handle binding to tuple-like structures
3157972a253aSDimitry Andric     else if (const auto *HV = BD->getHoldingVar()) {
3158972a253aSDimitry Andric       V = state->getLValue(HV, LCtx);
3159972a253aSDimitry Andric 
3160972a253aSDimitry Andric       if (HV->getType()->isReferenceType()) {
3161972a253aSDimitry Andric         if (const MemRegion *R = V.getAsRegion())
3162972a253aSDimitry Andric           V = state->getSVal(R);
3163972a253aSDimitry Andric         else
3164972a253aSDimitry Andric           V = UnknownVal();
3165972a253aSDimitry Andric       }
316681ad6265SDimitry Andric     } else
316781ad6265SDimitry Andric       llvm_unreachable("An unknown case of structured binding encountered!");
316881ad6265SDimitry Andric 
3169972a253aSDimitry Andric     // In case of tuple-like types the references are already handled, so we
3170972a253aSDimitry Andric     // don't want to handle them again.
3171972a253aSDimitry Andric     if (BD->getType()->isReferenceType() && !BD->getHoldingVar()) {
3172972a253aSDimitry Andric       if (const MemRegion *R = V.getAsRegion())
3173972a253aSDimitry Andric         V = state->getSVal(R);
3174972a253aSDimitry Andric       else
3175972a253aSDimitry Andric         V = UnknownVal();
3176972a253aSDimitry Andric     }
317781ad6265SDimitry Andric 
317881ad6265SDimitry Andric     Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,
317981ad6265SDimitry Andric                       ProgramPoint::PostLValueKind);
318081ad6265SDimitry Andric 
31810b57cec5SDimitry Andric     return;
31820b57cec5SDimitry Andric   }
31830b57cec5SDimitry Andric 
3184f3fd488fSDimitry Andric   if (const auto *TPO = dyn_cast<TemplateParamObjectDecl>(D)) {
3185f3fd488fSDimitry Andric     // FIXME: We should meaningfully implement this.
3186f3fd488fSDimitry Andric     (void)TPO;
3187f3fd488fSDimitry Andric     return;
3188f3fd488fSDimitry Andric   }
3189f3fd488fSDimitry Andric 
31900b57cec5SDimitry Andric   llvm_unreachable("Support for this Decl not implemented.");
31910b57cec5SDimitry Andric }
31920b57cec5SDimitry Andric 
319381ad6265SDimitry Andric /// VisitArrayInitLoopExpr - Transfer function for array init loop.
VisitArrayInitLoopExpr(const ArrayInitLoopExpr * Ex,ExplodedNode * Pred,ExplodedNodeSet & Dst)319481ad6265SDimitry Andric void ExprEngine::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *Ex,
319581ad6265SDimitry Andric                                         ExplodedNode *Pred,
319681ad6265SDimitry Andric                                         ExplodedNodeSet &Dst) {
319781ad6265SDimitry Andric   ExplodedNodeSet CheckerPreStmt;
319881ad6265SDimitry Andric   getCheckerManager().runCheckersForPreStmt(CheckerPreStmt, Pred, Ex, *this);
319981ad6265SDimitry Andric 
320081ad6265SDimitry Andric   ExplodedNodeSet EvalSet;
320181ad6265SDimitry Andric   StmtNodeBuilder Bldr(CheckerPreStmt, EvalSet, *currBldrCtx);
320281ad6265SDimitry Andric 
320381ad6265SDimitry Andric   const Expr *Arr = Ex->getCommonExpr()->getSourceExpr();
320481ad6265SDimitry Andric 
320581ad6265SDimitry Andric   for (auto *Node : CheckerPreStmt) {
3206972a253aSDimitry Andric 
3207972a253aSDimitry Andric     // The constructor visitior has already taken care of everything.
3208bdd1243dSDimitry Andric     if (isa<CXXConstructExpr>(Ex->getSubExpr()))
3209972a253aSDimitry Andric       break;
3210972a253aSDimitry Andric 
321181ad6265SDimitry Andric     const LocationContext *LCtx = Node->getLocationContext();
321281ad6265SDimitry Andric     ProgramStateRef state = Node->getState();
321381ad6265SDimitry Andric 
321481ad6265SDimitry Andric     SVal Base = UnknownVal();
321581ad6265SDimitry Andric 
321681ad6265SDimitry Andric     // As in case of this expression the sub-expressions are not visited by any
321781ad6265SDimitry Andric     // other transfer functions, they are handled by matching their AST.
321881ad6265SDimitry Andric 
321981ad6265SDimitry Andric     // Case of implicit copy or move ctor of object with array member
322081ad6265SDimitry Andric     //
322181ad6265SDimitry Andric     // Note: ExprEngine::VisitMemberExpr is not able to bind the array to the
322281ad6265SDimitry Andric     // environment.
322381ad6265SDimitry Andric     //
322481ad6265SDimitry Andric     //    struct S {
322581ad6265SDimitry Andric     //      int arr[2];
322681ad6265SDimitry Andric     //    };
322781ad6265SDimitry Andric     //
322881ad6265SDimitry Andric     //
322981ad6265SDimitry Andric     //    S a;
323081ad6265SDimitry Andric     //    S b = a;
323181ad6265SDimitry Andric     //
323281ad6265SDimitry Andric     // The AST in case of a *copy constructor* looks like this:
323381ad6265SDimitry Andric     //    ArrayInitLoopExpr
323481ad6265SDimitry Andric     //    |-OpaqueValueExpr
323581ad6265SDimitry Andric     //    | `-MemberExpr              <-- match this
323681ad6265SDimitry Andric     //    |   `-DeclRefExpr
323781ad6265SDimitry Andric     //    ` ...
323881ad6265SDimitry Andric     //
323981ad6265SDimitry Andric     //
324081ad6265SDimitry Andric     //    S c;
324181ad6265SDimitry Andric     //    S d = std::move(d);
324281ad6265SDimitry Andric     //
324381ad6265SDimitry Andric     // In case of a *move constructor* the resulting AST looks like:
324481ad6265SDimitry Andric     //    ArrayInitLoopExpr
324581ad6265SDimitry Andric     //    |-OpaqueValueExpr
324681ad6265SDimitry Andric     //    | `-MemberExpr              <-- match this first
324781ad6265SDimitry Andric     //    |   `-CXXStaticCastExpr     <-- match this after
324881ad6265SDimitry Andric     //    |     `-DeclRefExpr
324981ad6265SDimitry Andric     //    ` ...
325081ad6265SDimitry Andric     if (const auto *ME = dyn_cast<MemberExpr>(Arr)) {
325181ad6265SDimitry Andric       Expr *MEBase = ME->getBase();
325281ad6265SDimitry Andric 
325381ad6265SDimitry Andric       // Move ctor
325481ad6265SDimitry Andric       if (auto CXXSCE = dyn_cast<CXXStaticCastExpr>(MEBase)) {
325581ad6265SDimitry Andric         MEBase = CXXSCE->getSubExpr();
325681ad6265SDimitry Andric       }
325781ad6265SDimitry Andric 
325881ad6265SDimitry Andric       auto ObjDeclExpr = cast<DeclRefExpr>(MEBase);
325981ad6265SDimitry Andric       SVal Obj = state->getLValue(cast<VarDecl>(ObjDeclExpr->getDecl()), LCtx);
326081ad6265SDimitry Andric 
326181ad6265SDimitry Andric       Base = state->getLValue(cast<FieldDecl>(ME->getMemberDecl()), Obj);
326281ad6265SDimitry Andric     }
326381ad6265SDimitry Andric 
326481ad6265SDimitry Andric     // Case of lambda capture and decomposition declaration
326581ad6265SDimitry Andric     //
326681ad6265SDimitry Andric     //    int arr[2];
326781ad6265SDimitry Andric     //
326881ad6265SDimitry Andric     //    [arr]{ int a = arr[0]; }();
326981ad6265SDimitry Andric     //    auto[a, b] = arr;
327081ad6265SDimitry Andric     //
327181ad6265SDimitry Andric     // In both of these cases the AST looks like the following:
327281ad6265SDimitry Andric     //    ArrayInitLoopExpr
327381ad6265SDimitry Andric     //    |-OpaqueValueExpr
327481ad6265SDimitry Andric     //    | `-DeclRefExpr             <-- match this
327581ad6265SDimitry Andric     //    ` ...
327681ad6265SDimitry Andric     if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Arr))
327781ad6265SDimitry Andric       Base = state->getLValue(cast<VarDecl>(DRE->getDecl()), LCtx);
327881ad6265SDimitry Andric 
327981ad6265SDimitry Andric     // Create a lazy compound value to the original array
328081ad6265SDimitry Andric     if (const MemRegion *R = Base.getAsRegion())
328181ad6265SDimitry Andric       Base = state->getSVal(R);
328281ad6265SDimitry Andric     else
328381ad6265SDimitry Andric       Base = UnknownVal();
328481ad6265SDimitry Andric 
328581ad6265SDimitry Andric     Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, Base));
328681ad6265SDimitry Andric   }
328781ad6265SDimitry Andric 
328881ad6265SDimitry Andric   getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, Ex, *this);
328981ad6265SDimitry Andric }
329081ad6265SDimitry Andric 
32910b57cec5SDimitry Andric /// VisitArraySubscriptExpr - Transfer function for array accesses
VisitArraySubscriptExpr(const ArraySubscriptExpr * A,ExplodedNode * Pred,ExplodedNodeSet & Dst)32920b57cec5SDimitry Andric void ExprEngine::VisitArraySubscriptExpr(const ArraySubscriptExpr *A,
32930b57cec5SDimitry Andric                                              ExplodedNode *Pred,
32940b57cec5SDimitry Andric                                              ExplodedNodeSet &Dst){
32950b57cec5SDimitry Andric   const Expr *Base = A->getBase()->IgnoreParens();
32960b57cec5SDimitry Andric   const Expr *Idx  = A->getIdx()->IgnoreParens();
32970b57cec5SDimitry Andric 
32980b57cec5SDimitry Andric   ExplodedNodeSet CheckerPreStmt;
32990b57cec5SDimitry Andric   getCheckerManager().runCheckersForPreStmt(CheckerPreStmt, Pred, A, *this);
33000b57cec5SDimitry Andric 
33010b57cec5SDimitry Andric   ExplodedNodeSet EvalSet;
33020b57cec5SDimitry Andric   StmtNodeBuilder Bldr(CheckerPreStmt, EvalSet, *currBldrCtx);
33030b57cec5SDimitry Andric 
33040b57cec5SDimitry Andric   bool IsVectorType = A->getBase()->getType()->isVectorType();
33050b57cec5SDimitry Andric 
33060b57cec5SDimitry Andric   // The "like" case is for situations where C standard prohibits the type to
33070b57cec5SDimitry Andric   // be an lvalue, e.g. taking the address of a subscript of an expression of
33080b57cec5SDimitry Andric   // type "void *".
33090b57cec5SDimitry Andric   bool IsGLValueLike = A->isGLValue() ||
33100b57cec5SDimitry Andric     (A->getType().isCForbiddenLValueType() && !AMgr.getLangOpts().CPlusPlus);
33110b57cec5SDimitry Andric 
33120b57cec5SDimitry Andric   for (auto *Node : CheckerPreStmt) {
33130b57cec5SDimitry Andric     const LocationContext *LCtx = Node->getLocationContext();
33140b57cec5SDimitry Andric     ProgramStateRef state = Node->getState();
33150b57cec5SDimitry Andric 
33160b57cec5SDimitry Andric     if (IsGLValueLike) {
33170b57cec5SDimitry Andric       QualType T = A->getType();
33180b57cec5SDimitry Andric 
33190b57cec5SDimitry Andric       // One of the forbidden LValue types! We still need to have sensible
33200b57cec5SDimitry Andric       // symbolic locations to represent this stuff. Note that arithmetic on
33210b57cec5SDimitry Andric       // void pointers is a GCC extension.
33220b57cec5SDimitry Andric       if (T->isVoidType())
33230b57cec5SDimitry Andric         T = getContext().CharTy;
33240b57cec5SDimitry Andric 
33250b57cec5SDimitry Andric       SVal V = state->getLValue(T,
33260b57cec5SDimitry Andric                                 state->getSVal(Idx, LCtx),
33270b57cec5SDimitry Andric                                 state->getSVal(Base, LCtx));
33280b57cec5SDimitry Andric       Bldr.generateNode(A, Node, state->BindExpr(A, LCtx, V), nullptr,
33290b57cec5SDimitry Andric           ProgramPoint::PostLValueKind);
33300b57cec5SDimitry Andric     } else if (IsVectorType) {
33310b57cec5SDimitry Andric       // FIXME: non-glvalue vector reads are not modelled.
33320b57cec5SDimitry Andric       Bldr.generateNode(A, Node, state, nullptr);
33330b57cec5SDimitry Andric     } else {
33340b57cec5SDimitry Andric       llvm_unreachable("Array subscript should be an lValue when not \
33350b57cec5SDimitry Andric a vector and not a forbidden lvalue type");
33360b57cec5SDimitry Andric     }
33370b57cec5SDimitry Andric   }
33380b57cec5SDimitry Andric 
33390b57cec5SDimitry Andric   getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, A, *this);
33400b57cec5SDimitry Andric }
33410b57cec5SDimitry Andric 
33420b57cec5SDimitry Andric /// VisitMemberExpr - Transfer function for member expressions.
VisitMemberExpr(const MemberExpr * M,ExplodedNode * Pred,ExplodedNodeSet & Dst)33430b57cec5SDimitry Andric void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
33440b57cec5SDimitry Andric                                  ExplodedNodeSet &Dst) {
33450b57cec5SDimitry Andric   // FIXME: Prechecks eventually go in ::Visit().
33460b57cec5SDimitry Andric   ExplodedNodeSet CheckedSet;
33470b57cec5SDimitry Andric   getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, M, *this);
33480b57cec5SDimitry Andric 
33490b57cec5SDimitry Andric   ExplodedNodeSet EvalSet;
33500b57cec5SDimitry Andric   ValueDecl *Member = M->getMemberDecl();
33510b57cec5SDimitry Andric 
33520b57cec5SDimitry Andric   // Handle static member variables and enum constants accessed via
33530b57cec5SDimitry Andric   // member syntax.
3354349cc55cSDimitry Andric   if (isa<VarDecl, EnumConstantDecl>(Member)) {
33550b57cec5SDimitry Andric     for (const auto I : CheckedSet)
33560b57cec5SDimitry Andric       VisitCommonDeclRefExpr(M, Member, I, EvalSet);
33570b57cec5SDimitry Andric   } else {
33580b57cec5SDimitry Andric     StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx);
33590b57cec5SDimitry Andric     ExplodedNodeSet Tmp;
33600b57cec5SDimitry Andric 
33610b57cec5SDimitry Andric     for (const auto I : CheckedSet) {
33620b57cec5SDimitry Andric       ProgramStateRef state = I->getState();
33630b57cec5SDimitry Andric       const LocationContext *LCtx = I->getLocationContext();
33640b57cec5SDimitry Andric       Expr *BaseExpr = M->getBase();
33650b57cec5SDimitry Andric 
33660b57cec5SDimitry Andric       // Handle C++ method calls.
33670b57cec5SDimitry Andric       if (const auto *MD = dyn_cast<CXXMethodDecl>(Member)) {
33685f757f3fSDimitry Andric         if (MD->isImplicitObjectMemberFunction())
33690b57cec5SDimitry Andric           state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr);
33700b57cec5SDimitry Andric 
33710b57cec5SDimitry Andric         SVal MDVal = svalBuilder.getFunctionPointer(MD);
33720b57cec5SDimitry Andric         state = state->BindExpr(M, LCtx, MDVal);
33730b57cec5SDimitry Andric 
33740b57cec5SDimitry Andric         Bldr.generateNode(M, I, state);
33750b57cec5SDimitry Andric         continue;
33760b57cec5SDimitry Andric       }
33770b57cec5SDimitry Andric 
33780b57cec5SDimitry Andric       // Handle regular struct fields / member variables.
33790b57cec5SDimitry Andric       const SubRegion *MR = nullptr;
33800b57cec5SDimitry Andric       state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr,
33810b57cec5SDimitry Andric                                             /*Result=*/nullptr,
33820b57cec5SDimitry Andric                                             /*OutRegionWithAdjustments=*/&MR);
33830b57cec5SDimitry Andric       SVal baseExprVal =
33840b57cec5SDimitry Andric           MR ? loc::MemRegionVal(MR) : state->getSVal(BaseExpr, LCtx);
33850b57cec5SDimitry Andric 
3386bdd1243dSDimitry Andric       // FIXME: Copied from RegionStoreManager::bind()
3387bdd1243dSDimitry Andric       if (const auto *SR =
3388bdd1243dSDimitry Andric               dyn_cast_or_null<SymbolicRegion>(baseExprVal.getAsRegion())) {
3389bdd1243dSDimitry Andric         QualType T = SR->getPointeeStaticType();
3390bdd1243dSDimitry Andric         baseExprVal =
3391bdd1243dSDimitry Andric             loc::MemRegionVal(getStoreManager().GetElementZeroRegion(SR, T));
3392bdd1243dSDimitry Andric       }
3393bdd1243dSDimitry Andric 
33940b57cec5SDimitry Andric       const auto *field = cast<FieldDecl>(Member);
33950b57cec5SDimitry Andric       SVal L = state->getLValue(field, baseExprVal);
33960b57cec5SDimitry Andric 
33970b57cec5SDimitry Andric       if (M->isGLValue() || M->getType()->isArrayType()) {
33980b57cec5SDimitry Andric         // We special-case rvalues of array type because the analyzer cannot
33990b57cec5SDimitry Andric         // reason about them, since we expect all regions to be wrapped in Locs.
34000b57cec5SDimitry Andric         // We instead treat these as lvalues and assume that they will decay to
34010b57cec5SDimitry Andric         // pointers as soon as they are used.
34020b57cec5SDimitry Andric         if (!M->isGLValue()) {
34030b57cec5SDimitry Andric           assert(M->getType()->isArrayType());
34040b57cec5SDimitry Andric           const auto *PE =
34050b57cec5SDimitry Andric             dyn_cast<ImplicitCastExpr>(I->getParentMap().getParentIgnoreParens(M));
34060b57cec5SDimitry Andric           if (!PE || PE->getCastKind() != CK_ArrayToPointerDecay) {
34070b57cec5SDimitry Andric             llvm_unreachable("should always be wrapped in ArrayToPointerDecay");
34080b57cec5SDimitry Andric           }
34090b57cec5SDimitry Andric         }
34100b57cec5SDimitry Andric 
34110b57cec5SDimitry Andric         if (field->getType()->isReferenceType()) {
34120b57cec5SDimitry Andric           if (const MemRegion *R = L.getAsRegion())
34130b57cec5SDimitry Andric             L = state->getSVal(R);
34140b57cec5SDimitry Andric           else
34150b57cec5SDimitry Andric             L = UnknownVal();
34160b57cec5SDimitry Andric         }
34170b57cec5SDimitry Andric 
34180b57cec5SDimitry Andric         Bldr.generateNode(M, I, state->BindExpr(M, LCtx, L), nullptr,
34190b57cec5SDimitry Andric                           ProgramPoint::PostLValueKind);
34200b57cec5SDimitry Andric       } else {
34210b57cec5SDimitry Andric         Bldr.takeNodes(I);
34220b57cec5SDimitry Andric         evalLoad(Tmp, M, M, I, state, L);
34230b57cec5SDimitry Andric         Bldr.addNodes(Tmp);
34240b57cec5SDimitry Andric       }
34250b57cec5SDimitry Andric     }
34260b57cec5SDimitry Andric   }
34270b57cec5SDimitry Andric 
34280b57cec5SDimitry Andric   getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, M, *this);
34290b57cec5SDimitry Andric }
34300b57cec5SDimitry Andric 
VisitAtomicExpr(const AtomicExpr * AE,ExplodedNode * Pred,ExplodedNodeSet & Dst)34310b57cec5SDimitry Andric void ExprEngine::VisitAtomicExpr(const AtomicExpr *AE, ExplodedNode *Pred,
34320b57cec5SDimitry Andric                                  ExplodedNodeSet &Dst) {
34330b57cec5SDimitry Andric   ExplodedNodeSet AfterPreSet;
34340b57cec5SDimitry Andric   getCheckerManager().runCheckersForPreStmt(AfterPreSet, Pred, AE, *this);
34350b57cec5SDimitry Andric 
34360b57cec5SDimitry Andric   // For now, treat all the arguments to C11 atomics as escaping.
34370b57cec5SDimitry Andric   // FIXME: Ideally we should model the behavior of the atomics precisely here.
34380b57cec5SDimitry Andric 
34390b57cec5SDimitry Andric   ExplodedNodeSet AfterInvalidateSet;
34400b57cec5SDimitry Andric   StmtNodeBuilder Bldr(AfterPreSet, AfterInvalidateSet, *currBldrCtx);
34410b57cec5SDimitry Andric 
34420b57cec5SDimitry Andric   for (const auto I : AfterPreSet) {
34430b57cec5SDimitry Andric     ProgramStateRef State = I->getState();
34440b57cec5SDimitry Andric     const LocationContext *LCtx = I->getLocationContext();
34450b57cec5SDimitry Andric 
34460b57cec5SDimitry Andric     SmallVector<SVal, 8> ValuesToInvalidate;
34470b57cec5SDimitry Andric     for (unsigned SI = 0, Count = AE->getNumSubExprs(); SI != Count; SI++) {
34480b57cec5SDimitry Andric       const Expr *SubExpr = AE->getSubExprs()[SI];
34490b57cec5SDimitry Andric       SVal SubExprVal = State->getSVal(SubExpr, LCtx);
34500b57cec5SDimitry Andric       ValuesToInvalidate.push_back(SubExprVal);
34510b57cec5SDimitry Andric     }
34520b57cec5SDimitry Andric 
34530b57cec5SDimitry Andric     State = State->invalidateRegions(ValuesToInvalidate, AE,
34540b57cec5SDimitry Andric                                     currBldrCtx->blockCount(),
34550b57cec5SDimitry Andric                                     LCtx,
34560b57cec5SDimitry Andric                                     /*CausedByPointerEscape*/true,
34570b57cec5SDimitry Andric                                     /*Symbols=*/nullptr);
34580b57cec5SDimitry Andric 
34590b57cec5SDimitry Andric     SVal ResultVal = UnknownVal();
34600b57cec5SDimitry Andric     State = State->BindExpr(AE, LCtx, ResultVal);
34610b57cec5SDimitry Andric     Bldr.generateNode(AE, I, State, nullptr,
34620b57cec5SDimitry Andric                       ProgramPoint::PostStmtKind);
34630b57cec5SDimitry Andric   }
34640b57cec5SDimitry Andric 
34650b57cec5SDimitry Andric   getCheckerManager().runCheckersForPostStmt(Dst, AfterInvalidateSet, AE, *this);
34660b57cec5SDimitry Andric }
34670b57cec5SDimitry Andric 
34680b57cec5SDimitry Andric // A value escapes in four possible cases:
34690b57cec5SDimitry Andric // (1) We are binding to something that is not a memory region.
34700b57cec5SDimitry Andric // (2) We are binding to a MemRegion that does not have stack storage.
34710b57cec5SDimitry Andric // (3) We are binding to a top-level parameter region with a non-trivial
34720b57cec5SDimitry Andric //     destructor. We won't see the destructor during analysis, but it's there.
34730b57cec5SDimitry Andric // (4) We are binding to a MemRegion with stack storage that the store
34740b57cec5SDimitry Andric //     does not understand.
processPointerEscapedOnBind(ProgramStateRef State,ArrayRef<std::pair<SVal,SVal>> LocAndVals,const LocationContext * LCtx,PointerEscapeKind Kind,const CallEvent * Call)3475480093f4SDimitry Andric ProgramStateRef ExprEngine::processPointerEscapedOnBind(
3476480093f4SDimitry Andric     ProgramStateRef State, ArrayRef<std::pair<SVal, SVal>> LocAndVals,
3477480093f4SDimitry Andric     const LocationContext *LCtx, PointerEscapeKind Kind,
3478480093f4SDimitry Andric     const CallEvent *Call) {
3479480093f4SDimitry Andric   SmallVector<SVal, 8> Escaped;
3480480093f4SDimitry Andric   for (const std::pair<SVal, SVal> &LocAndVal : LocAndVals) {
34810b57cec5SDimitry Andric     // Cases (1) and (2).
3482480093f4SDimitry Andric     const MemRegion *MR = LocAndVal.first.getAsRegion();
3483bdd1243dSDimitry Andric     if (!MR ||
3484bdd1243dSDimitry Andric         !isa<StackSpaceRegion, StaticGlobalSpaceRegion>(MR->getMemorySpace())) {
3485480093f4SDimitry Andric       Escaped.push_back(LocAndVal.second);
3486480093f4SDimitry Andric       continue;
3487480093f4SDimitry Andric     }
34880b57cec5SDimitry Andric 
34890b57cec5SDimitry Andric     // Case (3).
34900b57cec5SDimitry Andric     if (const auto *VR = dyn_cast<VarRegion>(MR->getBaseRegion()))
34910b57cec5SDimitry Andric       if (VR->hasStackParametersStorage() && VR->getStackFrame()->inTopFrame())
34920b57cec5SDimitry Andric         if (const auto *RD = VR->getValueType()->getAsCXXRecordDecl())
3493480093f4SDimitry Andric           if (!RD->hasTrivialDestructor()) {
3494480093f4SDimitry Andric             Escaped.push_back(LocAndVal.second);
3495480093f4SDimitry Andric             continue;
3496480093f4SDimitry Andric           }
34970b57cec5SDimitry Andric 
34980b57cec5SDimitry Andric     // Case (4): in order to test that, generate a new state with the binding
34990b57cec5SDimitry Andric     // added. If it is the same state, then it escapes (since the store cannot
35000b57cec5SDimitry Andric     // represent the binding).
35010b57cec5SDimitry Andric     // Do this only if we know that the store is not supposed to generate the
35020b57cec5SDimitry Andric     // same state.
35030b57cec5SDimitry Andric     SVal StoredVal = State->getSVal(MR);
3504480093f4SDimitry Andric     if (StoredVal != LocAndVal.second)
3505480093f4SDimitry Andric       if (State ==
3506480093f4SDimitry Andric           (State->bindLoc(loc::MemRegionVal(MR), LocAndVal.second, LCtx)))
3507480093f4SDimitry Andric         Escaped.push_back(LocAndVal.second);
3508480093f4SDimitry Andric   }
35090b57cec5SDimitry Andric 
3510480093f4SDimitry Andric   if (Escaped.empty())
35110b57cec5SDimitry Andric     return State;
3512480093f4SDimitry Andric 
3513480093f4SDimitry Andric   return escapeValues(State, Escaped, Kind, Call);
3514480093f4SDimitry Andric }
3515480093f4SDimitry Andric 
3516480093f4SDimitry Andric ProgramStateRef
processPointerEscapedOnBind(ProgramStateRef State,SVal Loc,SVal Val,const LocationContext * LCtx)3517480093f4SDimitry Andric ExprEngine::processPointerEscapedOnBind(ProgramStateRef State, SVal Loc,
3518480093f4SDimitry Andric                                         SVal Val, const LocationContext *LCtx) {
3519480093f4SDimitry Andric   std::pair<SVal, SVal> LocAndVal(Loc, Val);
3520480093f4SDimitry Andric   return processPointerEscapedOnBind(State, LocAndVal, LCtx, PSK_EscapeOnBind,
3521480093f4SDimitry Andric                                      nullptr);
35220b57cec5SDimitry Andric }
35230b57cec5SDimitry Andric 
35240b57cec5SDimitry Andric ProgramStateRef
notifyCheckersOfPointerEscape(ProgramStateRef State,const InvalidatedSymbols * Invalidated,ArrayRef<const MemRegion * > ExplicitRegions,const CallEvent * Call,RegionAndSymbolInvalidationTraits & ITraits)35250b57cec5SDimitry Andric ExprEngine::notifyCheckersOfPointerEscape(ProgramStateRef State,
35260b57cec5SDimitry Andric     const InvalidatedSymbols *Invalidated,
35270b57cec5SDimitry Andric     ArrayRef<const MemRegion *> ExplicitRegions,
35280b57cec5SDimitry Andric     const CallEvent *Call,
35290b57cec5SDimitry Andric     RegionAndSymbolInvalidationTraits &ITraits) {
35300b57cec5SDimitry Andric   if (!Invalidated || Invalidated->empty())
35310b57cec5SDimitry Andric     return State;
35320b57cec5SDimitry Andric 
35330b57cec5SDimitry Andric   if (!Call)
35340b57cec5SDimitry Andric     return getCheckerManager().runCheckersForPointerEscape(State,
35350b57cec5SDimitry Andric                                                            *Invalidated,
35360b57cec5SDimitry Andric                                                            nullptr,
35370b57cec5SDimitry Andric                                                            PSK_EscapeOther,
35380b57cec5SDimitry Andric                                                            &ITraits);
35390b57cec5SDimitry Andric 
35400b57cec5SDimitry Andric   // If the symbols were invalidated by a call, we want to find out which ones
35410b57cec5SDimitry Andric   // were invalidated directly due to being arguments to the call.
35420b57cec5SDimitry Andric   InvalidatedSymbols SymbolsDirectlyInvalidated;
35430b57cec5SDimitry Andric   for (const auto I : ExplicitRegions) {
35440b57cec5SDimitry Andric     if (const SymbolicRegion *R = I->StripCasts()->getAs<SymbolicRegion>())
35450b57cec5SDimitry Andric       SymbolsDirectlyInvalidated.insert(R->getSymbol());
35460b57cec5SDimitry Andric   }
35470b57cec5SDimitry Andric 
35480b57cec5SDimitry Andric   InvalidatedSymbols SymbolsIndirectlyInvalidated;
35490b57cec5SDimitry Andric   for (const auto &sym : *Invalidated) {
35500b57cec5SDimitry Andric     if (SymbolsDirectlyInvalidated.count(sym))
35510b57cec5SDimitry Andric       continue;
35520b57cec5SDimitry Andric     SymbolsIndirectlyInvalidated.insert(sym);
35530b57cec5SDimitry Andric   }
35540b57cec5SDimitry Andric 
35550b57cec5SDimitry Andric   if (!SymbolsDirectlyInvalidated.empty())
35560b57cec5SDimitry Andric     State = getCheckerManager().runCheckersForPointerEscape(State,
35570b57cec5SDimitry Andric         SymbolsDirectlyInvalidated, Call, PSK_DirectEscapeOnCall, &ITraits);
35580b57cec5SDimitry Andric 
35590b57cec5SDimitry Andric   // Notify about the symbols that get indirectly invalidated by the call.
35600b57cec5SDimitry Andric   if (!SymbolsIndirectlyInvalidated.empty())
35610b57cec5SDimitry Andric     State = getCheckerManager().runCheckersForPointerEscape(State,
35620b57cec5SDimitry Andric         SymbolsIndirectlyInvalidated, Call, PSK_IndirectEscapeOnCall, &ITraits);
35630b57cec5SDimitry Andric 
35640b57cec5SDimitry Andric   return State;
35650b57cec5SDimitry Andric }
35660b57cec5SDimitry Andric 
35670b57cec5SDimitry Andric /// evalBind - Handle the semantics of binding a value to a specific location.
35680b57cec5SDimitry Andric ///  This method is used by evalStore and (soon) VisitDeclStmt, and others.
evalBind(ExplodedNodeSet & Dst,const Stmt * StoreE,ExplodedNode * Pred,SVal location,SVal Val,bool atDeclInit,const ProgramPoint * PP)35690b57cec5SDimitry Andric void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
35700b57cec5SDimitry Andric                           ExplodedNode *Pred,
35710b57cec5SDimitry Andric                           SVal location, SVal Val,
35720b57cec5SDimitry Andric                           bool atDeclInit, const ProgramPoint *PP) {
35730b57cec5SDimitry Andric   const LocationContext *LC = Pred->getLocationContext();
35740b57cec5SDimitry Andric   PostStmt PS(StoreE, LC);
35750b57cec5SDimitry Andric   if (!PP)
35760b57cec5SDimitry Andric     PP = &PS;
35770b57cec5SDimitry Andric 
35780b57cec5SDimitry Andric   // Do a previsit of the bind.
35790b57cec5SDimitry Andric   ExplodedNodeSet CheckedSet;
35800b57cec5SDimitry Andric   getCheckerManager().runCheckersForBind(CheckedSet, Pred, location, Val,
35810b57cec5SDimitry Andric                                          StoreE, *this, *PP);
35820b57cec5SDimitry Andric 
35830b57cec5SDimitry Andric   StmtNodeBuilder Bldr(CheckedSet, Dst, *currBldrCtx);
35840b57cec5SDimitry Andric 
35850b57cec5SDimitry Andric   // If the location is not a 'Loc', it will already be handled by
35860b57cec5SDimitry Andric   // the checkers.  There is nothing left to do.
358781ad6265SDimitry Andric   if (!isa<Loc>(location)) {
35880b57cec5SDimitry Andric     const ProgramPoint L = PostStore(StoreE, LC, /*Loc*/nullptr,
35890b57cec5SDimitry Andric                                      /*tag*/nullptr);
35900b57cec5SDimitry Andric     ProgramStateRef state = Pred->getState();
35910b57cec5SDimitry Andric     state = processPointerEscapedOnBind(state, location, Val, LC);
35920b57cec5SDimitry Andric     Bldr.generateNode(L, state, Pred);
35930b57cec5SDimitry Andric     return;
35940b57cec5SDimitry Andric   }
35950b57cec5SDimitry Andric 
35960b57cec5SDimitry Andric   for (const auto PredI : CheckedSet) {
35970b57cec5SDimitry Andric     ProgramStateRef state = PredI->getState();
35980b57cec5SDimitry Andric 
35990b57cec5SDimitry Andric     state = processPointerEscapedOnBind(state, location, Val, LC);
36000b57cec5SDimitry Andric 
36010b57cec5SDimitry Andric     // When binding the value, pass on the hint that this is a initialization.
36020b57cec5SDimitry Andric     // For initializations, we do not need to inform clients of region
36030b57cec5SDimitry Andric     // changes.
36040b57cec5SDimitry Andric     state = state->bindLoc(location.castAs<Loc>(),
36050b57cec5SDimitry Andric                            Val, LC, /* notifyChanges = */ !atDeclInit);
36060b57cec5SDimitry Andric 
36070b57cec5SDimitry Andric     const MemRegion *LocReg = nullptr;
3608bdd1243dSDimitry Andric     if (std::optional<loc::MemRegionVal> LocRegVal =
36090b57cec5SDimitry Andric             location.getAs<loc::MemRegionVal>()) {
36100b57cec5SDimitry Andric       LocReg = LocRegVal->getRegion();
36110b57cec5SDimitry Andric     }
36120b57cec5SDimitry Andric 
36130b57cec5SDimitry Andric     const ProgramPoint L = PostStore(StoreE, LC, LocReg, nullptr);
36140b57cec5SDimitry Andric     Bldr.generateNode(L, state, PredI);
36150b57cec5SDimitry Andric   }
36160b57cec5SDimitry Andric }
36170b57cec5SDimitry Andric 
36180b57cec5SDimitry Andric /// evalStore - Handle the semantics of a store via an assignment.
36190b57cec5SDimitry Andric ///  @param Dst The node set to store generated state nodes
36200b57cec5SDimitry Andric ///  @param AssignE The assignment expression if the store happens in an
36210b57cec5SDimitry Andric ///         assignment.
36220b57cec5SDimitry Andric ///  @param LocationE The location expression that is stored to.
36230b57cec5SDimitry Andric ///  @param state The current simulation state
36240b57cec5SDimitry Andric ///  @param location The location to store the value
36250b57cec5SDimitry Andric ///  @param Val The value to be stored
evalStore(ExplodedNodeSet & Dst,const Expr * AssignE,const Expr * LocationE,ExplodedNode * Pred,ProgramStateRef state,SVal location,SVal Val,const ProgramPointTag * tag)36260b57cec5SDimitry Andric void ExprEngine::evalStore(ExplodedNodeSet &Dst, const Expr *AssignE,
36270b57cec5SDimitry Andric                              const Expr *LocationE,
36280b57cec5SDimitry Andric                              ExplodedNode *Pred,
36290b57cec5SDimitry Andric                              ProgramStateRef state, SVal location, SVal Val,
36300b57cec5SDimitry Andric                              const ProgramPointTag *tag) {
36310b57cec5SDimitry Andric   // Proceed with the store.  We use AssignE as the anchor for the PostStore
36320b57cec5SDimitry Andric   // ProgramPoint if it is non-NULL, and LocationE otherwise.
36330b57cec5SDimitry Andric   const Expr *StoreE = AssignE ? AssignE : LocationE;
36340b57cec5SDimitry Andric 
36350b57cec5SDimitry Andric   // Evaluate the location (checks for bad dereferences).
36360b57cec5SDimitry Andric   ExplodedNodeSet Tmp;
36370b57cec5SDimitry Andric   evalLocation(Tmp, AssignE, LocationE, Pred, state, location, false);
36380b57cec5SDimitry Andric 
36390b57cec5SDimitry Andric   if (Tmp.empty())
36400b57cec5SDimitry Andric     return;
36410b57cec5SDimitry Andric 
36420b57cec5SDimitry Andric   if (location.isUndef())
36430b57cec5SDimitry Andric     return;
36440b57cec5SDimitry Andric 
36450b57cec5SDimitry Andric   for (const auto I : Tmp)
36460b57cec5SDimitry Andric     evalBind(Dst, StoreE, I, location, Val, false);
36470b57cec5SDimitry Andric }
36480b57cec5SDimitry Andric 
evalLoad(ExplodedNodeSet & Dst,const Expr * NodeEx,const Expr * BoundEx,ExplodedNode * Pred,ProgramStateRef state,SVal location,const ProgramPointTag * tag,QualType LoadTy)36490b57cec5SDimitry Andric void ExprEngine::evalLoad(ExplodedNodeSet &Dst,
36500b57cec5SDimitry Andric                           const Expr *NodeEx,
36510b57cec5SDimitry Andric                           const Expr *BoundEx,
36520b57cec5SDimitry Andric                           ExplodedNode *Pred,
36530b57cec5SDimitry Andric                           ProgramStateRef state,
36540b57cec5SDimitry Andric                           SVal location,
36550b57cec5SDimitry Andric                           const ProgramPointTag *tag,
36560b57cec5SDimitry Andric                           QualType LoadTy) {
365781ad6265SDimitry Andric   assert(!isa<NonLoc>(location) && "location cannot be a NonLoc.");
36580b57cec5SDimitry Andric   assert(NodeEx);
36590b57cec5SDimitry Andric   assert(BoundEx);
36600b57cec5SDimitry Andric   // Evaluate the location (checks for bad dereferences).
36610b57cec5SDimitry Andric   ExplodedNodeSet Tmp;
36620b57cec5SDimitry Andric   evalLocation(Tmp, NodeEx, BoundEx, Pred, state, location, true);
36630b57cec5SDimitry Andric   if (Tmp.empty())
36640b57cec5SDimitry Andric     return;
36650b57cec5SDimitry Andric 
36660b57cec5SDimitry Andric   StmtNodeBuilder Bldr(Tmp, Dst, *currBldrCtx);
36670b57cec5SDimitry Andric   if (location.isUndef())
36680b57cec5SDimitry Andric     return;
36690b57cec5SDimitry Andric 
36700b57cec5SDimitry Andric   // Proceed with the load.
36710b57cec5SDimitry Andric   for (const auto I : Tmp) {
36720b57cec5SDimitry Andric     state = I->getState();
36730b57cec5SDimitry Andric     const LocationContext *LCtx = I->getLocationContext();
36740b57cec5SDimitry Andric 
36750b57cec5SDimitry Andric     SVal V = UnknownVal();
36760b57cec5SDimitry Andric     if (location.isValid()) {
36770b57cec5SDimitry Andric       if (LoadTy.isNull())
36780b57cec5SDimitry Andric         LoadTy = BoundEx->getType();
36790b57cec5SDimitry Andric       V = state->getSVal(location.castAs<Loc>(), LoadTy);
36800b57cec5SDimitry Andric     }
36810b57cec5SDimitry Andric 
36820b57cec5SDimitry Andric     Bldr.generateNode(NodeEx, I, state->BindExpr(BoundEx, LCtx, V), tag,
36830b57cec5SDimitry Andric                       ProgramPoint::PostLoadKind);
36840b57cec5SDimitry Andric   }
36850b57cec5SDimitry Andric }
36860b57cec5SDimitry Andric 
evalLocation(ExplodedNodeSet & Dst,const Stmt * NodeEx,const Stmt * BoundEx,ExplodedNode * Pred,ProgramStateRef state,SVal location,bool isLoad)36870b57cec5SDimitry Andric void ExprEngine::evalLocation(ExplodedNodeSet &Dst,
36880b57cec5SDimitry Andric                               const Stmt *NodeEx,
36890b57cec5SDimitry Andric                               const Stmt *BoundEx,
36900b57cec5SDimitry Andric                               ExplodedNode *Pred,
36910b57cec5SDimitry Andric                               ProgramStateRef state,
36920b57cec5SDimitry Andric                               SVal location,
36930b57cec5SDimitry Andric                               bool isLoad) {
36940b57cec5SDimitry Andric   StmtNodeBuilder BldrTop(Pred, Dst, *currBldrCtx);
36950b57cec5SDimitry Andric   // Early checks for performance reason.
36960b57cec5SDimitry Andric   if (location.isUnknown()) {
36970b57cec5SDimitry Andric     return;
36980b57cec5SDimitry Andric   }
36990b57cec5SDimitry Andric 
37000b57cec5SDimitry Andric   ExplodedNodeSet Src;
37010b57cec5SDimitry Andric   BldrTop.takeNodes(Pred);
37020b57cec5SDimitry Andric   StmtNodeBuilder Bldr(Pred, Src, *currBldrCtx);
37030b57cec5SDimitry Andric   if (Pred->getState() != state) {
37040b57cec5SDimitry Andric     // Associate this new state with an ExplodedNode.
37050b57cec5SDimitry Andric     // FIXME: If I pass null tag, the graph is incorrect, e.g for
37060b57cec5SDimitry Andric     //   int *p;
37070b57cec5SDimitry Andric     //   p = 0;
37080b57cec5SDimitry Andric     //   *p = 0xDEADBEEF;
37090b57cec5SDimitry Andric     // "p = 0" is not noted as "Null pointer value stored to 'p'" but
37100b57cec5SDimitry Andric     // instead "int *p" is noted as
37110b57cec5SDimitry Andric     // "Variable 'p' initialized to a null pointer value"
37120b57cec5SDimitry Andric 
37130b57cec5SDimitry Andric     static SimpleProgramPointTag tag(TagProviderName, "Location");
37140b57cec5SDimitry Andric     Bldr.generateNode(NodeEx, Pred, state, &tag);
37150b57cec5SDimitry Andric   }
37160b57cec5SDimitry Andric   ExplodedNodeSet Tmp;
37170b57cec5SDimitry Andric   getCheckerManager().runCheckersForLocation(Tmp, Src, location, isLoad,
37180b57cec5SDimitry Andric                                              NodeEx, BoundEx, *this);
37190b57cec5SDimitry Andric   BldrTop.addNodes(Tmp);
37200b57cec5SDimitry Andric }
37210b57cec5SDimitry Andric 
37220b57cec5SDimitry Andric std::pair<const ProgramPointTag *, const ProgramPointTag*>
geteagerlyAssumeBinOpBifurcationTags()37230b57cec5SDimitry Andric ExprEngine::geteagerlyAssumeBinOpBifurcationTags() {
37240b57cec5SDimitry Andric   static SimpleProgramPointTag
37250b57cec5SDimitry Andric          eagerlyAssumeBinOpBifurcationTrue(TagProviderName,
37260b57cec5SDimitry Andric                                            "Eagerly Assume True"),
37270b57cec5SDimitry Andric          eagerlyAssumeBinOpBifurcationFalse(TagProviderName,
37280b57cec5SDimitry Andric                                             "Eagerly Assume False");
37290b57cec5SDimitry Andric   return std::make_pair(&eagerlyAssumeBinOpBifurcationTrue,
37300b57cec5SDimitry Andric                         &eagerlyAssumeBinOpBifurcationFalse);
37310b57cec5SDimitry Andric }
37320b57cec5SDimitry Andric 
evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet & Dst,ExplodedNodeSet & Src,const Expr * Ex)37330b57cec5SDimitry Andric void ExprEngine::evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet &Dst,
37340b57cec5SDimitry Andric                                                    ExplodedNodeSet &Src,
37350b57cec5SDimitry Andric                                                    const Expr *Ex) {
37360b57cec5SDimitry Andric   StmtNodeBuilder Bldr(Src, Dst, *currBldrCtx);
37370b57cec5SDimitry Andric 
37380b57cec5SDimitry Andric   for (const auto Pred : Src) {
37390b57cec5SDimitry Andric     // Test if the previous node was as the same expression.  This can happen
37400b57cec5SDimitry Andric     // when the expression fails to evaluate to anything meaningful and
37410b57cec5SDimitry Andric     // (as an optimization) we don't generate a node.
37420b57cec5SDimitry Andric     ProgramPoint P = Pred->getLocation();
37430b57cec5SDimitry Andric     if (!P.getAs<PostStmt>() || P.castAs<PostStmt>().getStmt() != Ex) {
37440b57cec5SDimitry Andric       continue;
37450b57cec5SDimitry Andric     }
37460b57cec5SDimitry Andric 
37470b57cec5SDimitry Andric     ProgramStateRef state = Pred->getState();
37480b57cec5SDimitry Andric     SVal V = state->getSVal(Ex, Pred->getLocationContext());
3749bdd1243dSDimitry Andric     std::optional<nonloc::SymbolVal> SEV = V.getAs<nonloc::SymbolVal>();
37500b57cec5SDimitry Andric     if (SEV && SEV->isExpression()) {
37510b57cec5SDimitry Andric       const std::pair<const ProgramPointTag *, const ProgramPointTag*> &tags =
37520b57cec5SDimitry Andric         geteagerlyAssumeBinOpBifurcationTags();
37530b57cec5SDimitry Andric 
37540b57cec5SDimitry Andric       ProgramStateRef StateTrue, StateFalse;
37550b57cec5SDimitry Andric       std::tie(StateTrue, StateFalse) = state->assume(*SEV);
37560b57cec5SDimitry Andric 
37570b57cec5SDimitry Andric       // First assume that the condition is true.
37580b57cec5SDimitry Andric       if (StateTrue) {
37590b57cec5SDimitry Andric         SVal Val = svalBuilder.makeIntVal(1U, Ex->getType());
37600b57cec5SDimitry Andric         StateTrue = StateTrue->BindExpr(Ex, Pred->getLocationContext(), Val);
37610b57cec5SDimitry Andric         Bldr.generateNode(Ex, Pred, StateTrue, tags.first);
37620b57cec5SDimitry Andric       }
37630b57cec5SDimitry Andric 
37640b57cec5SDimitry Andric       // Next, assume that the condition is false.
37650b57cec5SDimitry Andric       if (StateFalse) {
37660b57cec5SDimitry Andric         SVal Val = svalBuilder.makeIntVal(0U, Ex->getType());
37670b57cec5SDimitry Andric         StateFalse = StateFalse->BindExpr(Ex, Pred->getLocationContext(), Val);
37680b57cec5SDimitry Andric         Bldr.generateNode(Ex, Pred, StateFalse, tags.second);
37690b57cec5SDimitry Andric       }
37700b57cec5SDimitry Andric     }
37710b57cec5SDimitry Andric   }
37720b57cec5SDimitry Andric }
37730b57cec5SDimitry Andric 
VisitGCCAsmStmt(const GCCAsmStmt * A,ExplodedNode * Pred,ExplodedNodeSet & Dst)37740b57cec5SDimitry Andric void ExprEngine::VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred,
37750b57cec5SDimitry Andric                                  ExplodedNodeSet &Dst) {
37760b57cec5SDimitry Andric   StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
37770b57cec5SDimitry Andric   // We have processed both the inputs and the outputs.  All of the outputs
37780b57cec5SDimitry Andric   // should evaluate to Locs.  Nuke all of their values.
37790b57cec5SDimitry Andric 
37800b57cec5SDimitry Andric   // FIXME: Some day in the future it would be nice to allow a "plug-in"
37810b57cec5SDimitry Andric   // which interprets the inline asm and stores proper results in the
37820b57cec5SDimitry Andric   // outputs.
37830b57cec5SDimitry Andric 
37840b57cec5SDimitry Andric   ProgramStateRef state = Pred->getState();
37850b57cec5SDimitry Andric 
37860b57cec5SDimitry Andric   for (const Expr *O : A->outputs()) {
37870b57cec5SDimitry Andric     SVal X = state->getSVal(O, Pred->getLocationContext());
378881ad6265SDimitry Andric     assert(!isa<NonLoc>(X)); // Should be an Lval, or unknown, undef.
37890b57cec5SDimitry Andric 
3790bdd1243dSDimitry Andric     if (std::optional<Loc> LV = X.getAs<Loc>())
37910b57cec5SDimitry Andric       state = state->bindLoc(*LV, UnknownVal(), Pred->getLocationContext());
37920b57cec5SDimitry Andric   }
37930b57cec5SDimitry Andric 
37940b57cec5SDimitry Andric   Bldr.generateNode(A, Pred, state);
37950b57cec5SDimitry Andric }
37960b57cec5SDimitry Andric 
VisitMSAsmStmt(const MSAsmStmt * A,ExplodedNode * Pred,ExplodedNodeSet & Dst)37970b57cec5SDimitry Andric void ExprEngine::VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred,
37980b57cec5SDimitry Andric                                 ExplodedNodeSet &Dst) {
37990b57cec5SDimitry Andric   StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
38000b57cec5SDimitry Andric   Bldr.generateNode(A, Pred, Pred->getState());
38010b57cec5SDimitry Andric }
38020b57cec5SDimitry Andric 
38030b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
38040b57cec5SDimitry Andric // Visualization.
38050b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
38060b57cec5SDimitry Andric 
38070b57cec5SDimitry Andric namespace llvm {
38080b57cec5SDimitry Andric 
38090b57cec5SDimitry Andric template<>
38100b57cec5SDimitry Andric struct DOTGraphTraits<ExplodedGraph*> : public DefaultDOTGraphTraits {
DOTGraphTraitsllvm::DOTGraphTraits38110b57cec5SDimitry Andric   DOTGraphTraits (bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
38120b57cec5SDimitry Andric 
nodeHasBugReportllvm::DOTGraphTraits38130b57cec5SDimitry Andric   static bool nodeHasBugReport(const ExplodedNode *N) {
38140b57cec5SDimitry Andric     BugReporter &BR = static_cast<ExprEngine &>(
38150b57cec5SDimitry Andric       N->getState()->getStateManager().getOwningEngine()).getBugReporter();
38160b57cec5SDimitry Andric 
381706c3fb27SDimitry Andric     for (const auto &Class : BR.equivalenceClasses()) {
381806c3fb27SDimitry Andric       for (const auto &Report : Class.getReports()) {
381906c3fb27SDimitry Andric         const auto *PR = dyn_cast<PathSensitiveBugReport>(Report.get());
3820a7dea167SDimitry Andric         if (!PR)
3821a7dea167SDimitry Andric           continue;
3822a7dea167SDimitry Andric         const ExplodedNode *EN = PR->getErrorNode();
3823a7dea167SDimitry Andric         if (EN->getState() == N->getState() &&
3824a7dea167SDimitry Andric             EN->getLocation() == N->getLocation())
38250b57cec5SDimitry Andric           return true;
38260b57cec5SDimitry Andric       }
38270b57cec5SDimitry Andric     }
38280b57cec5SDimitry Andric     return false;
38290b57cec5SDimitry Andric   }
38300b57cec5SDimitry Andric 
38310b57cec5SDimitry Andric   /// \p PreCallback: callback before break.
38320b57cec5SDimitry Andric   /// \p PostCallback: callback after break.
3833fe6060f1SDimitry Andric   /// \p Stop: stop iteration if returns @c true
3834fe6060f1SDimitry Andric   /// \return Whether @c Stop ever returned @c true.
traverseHiddenNodesllvm::DOTGraphTraits38350b57cec5SDimitry Andric   static bool traverseHiddenNodes(
38360b57cec5SDimitry Andric       const ExplodedNode *N,
38370b57cec5SDimitry Andric       llvm::function_ref<void(const ExplodedNode *)> PreCallback,
38380b57cec5SDimitry Andric       llvm::function_ref<void(const ExplodedNode *)> PostCallback,
38390b57cec5SDimitry Andric       llvm::function_ref<bool(const ExplodedNode *)> Stop) {
38400b57cec5SDimitry Andric     while (true) {
3841a7dea167SDimitry Andric       PreCallback(N);
3842a7dea167SDimitry Andric       if (Stop(N))
38430b57cec5SDimitry Andric         return true;
38440b57cec5SDimitry Andric 
3845e8d8bef9SDimitry Andric       if (N->succ_size() != 1 || !isNodeHidden(N->getFirstSucc(), nullptr))
38460b57cec5SDimitry Andric         break;
3847a7dea167SDimitry Andric       PostCallback(N);
38480b57cec5SDimitry Andric 
3849a7dea167SDimitry Andric       N = N->getFirstSucc();
38500b57cec5SDimitry Andric     }
38510b57cec5SDimitry Andric     return false;
38520b57cec5SDimitry Andric   }
38530b57cec5SDimitry Andric 
isNodeHiddenllvm::DOTGraphTraits3854e8d8bef9SDimitry Andric   static bool isNodeHidden(const ExplodedNode *N, const ExplodedGraph *G) {
38550b57cec5SDimitry Andric     return N->isTrivial();
38560b57cec5SDimitry Andric   }
38570b57cec5SDimitry Andric 
getNodeLabelllvm::DOTGraphTraits38580b57cec5SDimitry Andric   static std::string getNodeLabel(const ExplodedNode *N, ExplodedGraph *G){
38590b57cec5SDimitry Andric     std::string Buf;
38600b57cec5SDimitry Andric     llvm::raw_string_ostream Out(Buf);
38610b57cec5SDimitry Andric 
38620b57cec5SDimitry Andric     const bool IsDot = true;
38630b57cec5SDimitry Andric     const unsigned int Space = 1;
38640b57cec5SDimitry Andric     ProgramStateRef State = N->getState();
38650b57cec5SDimitry Andric 
3866a7dea167SDimitry Andric     Out << "{ \"state_id\": " << State->getID()
38670b57cec5SDimitry Andric         << ",\\l";
38680b57cec5SDimitry Andric 
38690b57cec5SDimitry Andric     Indent(Out, Space, IsDot) << "\"program_points\": [\\l";
38700b57cec5SDimitry Andric 
38710b57cec5SDimitry Andric     // Dump program point for all the previously skipped nodes.
38720b57cec5SDimitry Andric     traverseHiddenNodes(
38730b57cec5SDimitry Andric         N,
38740b57cec5SDimitry Andric         [&](const ExplodedNode *OtherNode) {
38750b57cec5SDimitry Andric           Indent(Out, Space + 1, IsDot) << "{ ";
38760b57cec5SDimitry Andric           OtherNode->getLocation().printJson(Out, /*NL=*/"\\l");
38770b57cec5SDimitry Andric           Out << ", \"tag\": ";
38780b57cec5SDimitry Andric           if (const ProgramPointTag *Tag = OtherNode->getLocation().getTag())
3879bdd1243dSDimitry Andric             Out << '\"' << Tag->getTagDescription() << '\"';
38800b57cec5SDimitry Andric           else
3881a7dea167SDimitry Andric             Out << "null";
3882a7dea167SDimitry Andric           Out << ", \"node_id\": " << OtherNode->getID() <<
3883a7dea167SDimitry Andric                  ", \"is_sink\": " << OtherNode->isSink() <<
3884a7dea167SDimitry Andric                  ", \"has_report\": " << nodeHasBugReport(OtherNode) << " }";
38850b57cec5SDimitry Andric         },
38860b57cec5SDimitry Andric         // Adds a comma and a new-line between each program point.
38870b57cec5SDimitry Andric         [&](const ExplodedNode *) { Out << ",\\l"; },
38880b57cec5SDimitry Andric         [&](const ExplodedNode *) { return false; });
38890b57cec5SDimitry Andric 
38900b57cec5SDimitry Andric     Out << "\\l"; // Adds a new-line to the last program point.
38910b57cec5SDimitry Andric     Indent(Out, Space, IsDot) << "],\\l";
38920b57cec5SDimitry Andric 
38930b57cec5SDimitry Andric     State->printDOT(Out, N->getLocationContext(), Space);
38940b57cec5SDimitry Andric 
38950b57cec5SDimitry Andric     Out << "\\l}\\l";
38960b57cec5SDimitry Andric     return Out.str();
38970b57cec5SDimitry Andric   }
38980b57cec5SDimitry Andric };
38990b57cec5SDimitry Andric 
39000b57cec5SDimitry Andric } // namespace llvm
39010b57cec5SDimitry Andric 
ViewGraph(bool trim)39020b57cec5SDimitry Andric void ExprEngine::ViewGraph(bool trim) {
39030b57cec5SDimitry Andric   std::string Filename = DumpGraph(trim);
39040b57cec5SDimitry Andric   llvm::DisplayGraph(Filename, false, llvm::GraphProgram::DOT);
39050b57cec5SDimitry Andric }
39060b57cec5SDimitry Andric 
ViewGraph(ArrayRef<const ExplodedNode * > Nodes)39070b57cec5SDimitry Andric void ExprEngine::ViewGraph(ArrayRef<const ExplodedNode *> Nodes) {
39080b57cec5SDimitry Andric   std::string Filename = DumpGraph(Nodes);
39090b57cec5SDimitry Andric   llvm::DisplayGraph(Filename, false, llvm::GraphProgram::DOT);
39100b57cec5SDimitry Andric }
39110b57cec5SDimitry Andric 
DumpGraph(bool trim,StringRef Filename)39120b57cec5SDimitry Andric std::string ExprEngine::DumpGraph(bool trim, StringRef Filename) {
39130b57cec5SDimitry Andric   if (trim) {
39140b57cec5SDimitry Andric     std::vector<const ExplodedNode *> Src;
39150b57cec5SDimitry Andric 
39160b57cec5SDimitry Andric     // Iterate through the reports and get their nodes.
391706c3fb27SDimitry Andric     for (const auto &Class : BR.equivalenceClasses()) {
3918a7dea167SDimitry Andric       const auto *R =
391906c3fb27SDimitry Andric           dyn_cast<PathSensitiveBugReport>(Class.getReports()[0].get());
3920a7dea167SDimitry Andric       if (!R)
3921a7dea167SDimitry Andric         continue;
3922a7dea167SDimitry Andric       const auto *N = const_cast<ExplodedNode *>(R->getErrorNode());
3923a7dea167SDimitry Andric       Src.push_back(N);
39240b57cec5SDimitry Andric     }
39250b57cec5SDimitry Andric     return DumpGraph(Src, Filename);
392681ad6265SDimitry Andric   }
392781ad6265SDimitry Andric 
39280b57cec5SDimitry Andric   return llvm::WriteGraph(&G, "ExprEngine", /*ShortNames=*/false,
39295ffd83dbSDimitry Andric                           /*Title=*/"Exploded Graph",
39305ffd83dbSDimitry Andric                           /*Filename=*/std::string(Filename));
39310b57cec5SDimitry Andric }
39320b57cec5SDimitry Andric 
DumpGraph(ArrayRef<const ExplodedNode * > Nodes,StringRef Filename)39330b57cec5SDimitry Andric std::string ExprEngine::DumpGraph(ArrayRef<const ExplodedNode *> Nodes,
39340b57cec5SDimitry Andric                                   StringRef Filename) {
39350b57cec5SDimitry Andric   std::unique_ptr<ExplodedGraph> TrimmedG(G.trim(Nodes));
39360b57cec5SDimitry Andric 
39370b57cec5SDimitry Andric   if (!TrimmedG.get()) {
39380b57cec5SDimitry Andric     llvm::errs() << "warning: Trimmed ExplodedGraph is empty.\n";
3939e8d8bef9SDimitry Andric     return "";
394081ad6265SDimitry Andric   }
394181ad6265SDimitry Andric 
39420b57cec5SDimitry Andric   return llvm::WriteGraph(TrimmedG.get(), "TrimmedExprEngine",
39430b57cec5SDimitry Andric                           /*ShortNames=*/false,
39440b57cec5SDimitry Andric                           /*Title=*/"Trimmed Exploded Graph",
39455ffd83dbSDimitry Andric                           /*Filename=*/std::string(Filename));
39460b57cec5SDimitry Andric }
39470b57cec5SDimitry Andric 
GDMIndex()39480b57cec5SDimitry Andric void *ProgramStateTrait<ReplayWithoutInlining>::GDMIndex() {
39490b57cec5SDimitry Andric   static int index = 0;
39500b57cec5SDimitry Andric   return &index;
39510b57cec5SDimitry Andric }
39525ffd83dbSDimitry Andric 
anchor()39535ffd83dbSDimitry Andric void ExprEngine::anchor() { }
3954