diff options
Diffstat (limited to 'include/clang/StaticAnalyzer/Core/PathSensitive')
14 files changed, 136 insertions, 109 deletions
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h index 4c50eafbde..a53e8ee693 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -921,15 +921,30 @@ public: return getOriginExpr()->getOperatorNew(); } + /// Number of non-placement arguments to the call. It is equal to 2 for + /// C++17 aligned operator new() calls that have alignment implicitly + /// passed as the second argument, and to 1 for other operator new() calls. + unsigned getNumImplicitArgs() const { + return getOriginExpr()->passAlignment() ? 2 : 1; + } + unsigned getNumArgs() const override { - return getOriginExpr()->getNumPlacementArgs() + 1; + return getOriginExpr()->getNumPlacementArgs() + getNumImplicitArgs(); } const Expr *getArgExpr(unsigned Index) const override { // The first argument of an allocator call is the size of the allocation. - if (Index == 0) + if (Index < getNumImplicitArgs()) return nullptr; - return getOriginExpr()->getPlacementArg(Index - 1); + return getOriginExpr()->getPlacementArg(Index - getNumImplicitArgs()); + } + + /// Number of placement arguments to the operator new() call. For example, + /// standard std::nothrow operator new and standard placement new both have + /// 1 implicit argument (size) and 1 placement argument, while regular + /// operator new() has 1 implicit argument and 0 placement arguments. + const Expr *getPlacementArgExpr(unsigned Index) const { + return getOriginExpr()->getPlacementArg(Index); } Kind getKind() const override { return CE_CXXAllocator; } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h index 2f8ead0746..b0d514dc28 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h @@ -36,10 +36,7 @@ using DynamicTypeMapImpl = template <> struct ProgramStateTrait<DynamicTypeMap> : public ProgramStatePartialTrait<DynamicTypeMapImpl> { - static void *GDMIndex() { - static int index = 0; - return &index; - } + static void *GDMIndex(); }; /// Get dynamic type information for a region. diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h index cf4164dcd2..bf460df278 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h @@ -210,10 +210,14 @@ public: return const_cast<ExplodedNode*>(this)->getFirstPred(); } - const ExplodedNode *getFirstSucc() const { + ExplodedNode *getFirstSucc() { return succ_empty() ? nullptr : *(succ_begin()); } + const ExplodedNode *getFirstSucc() const { + return const_cast<ExplodedNode*>(this)->getFirstSucc(); + } + // Iterators over successor and predecessor vertices. using succ_iterator = ExplodedNode * const *; using const_succ_iterator = const ExplodedNode * const *; @@ -243,8 +247,10 @@ public: int64_t getID(ExplodedGraph *G) const; /// The node is trivial if it has only one successor, only one predecessor, + /// it's predecessor has only one successor, /// and its program state is the same as the program state of the previous /// node. + /// Trivial nodes may be skipped while printing exploded graph. bool isTrivial() const; private: @@ -460,7 +466,6 @@ public: // GraphTraits namespace llvm { - template <> struct GraphTraits<clang::ento::ExplodedGraph *> { using GraphTy = clang::ento::ExplodedGraph *; using NodeRef = clang::ento::ExplodedNode *; @@ -471,17 +476,19 @@ namespace llvm { return *G->roots_begin(); } + static bool predecessorOfTrivial(NodeRef N) { + return N->succ_size() == 1 && N->getFirstSucc()->isTrivial(); + } + static ChildIteratorType child_begin(NodeRef N) { - if (N->succ_size() == 1 && (*N->succ_begin())->isTrivial()) { + if (predecessorOfTrivial(N)) return child_begin(*N->succ_begin()); - } return N->succ_begin(); } static ChildIteratorType child_end(NodeRef N) { - if (N->succ_size() == 1 && (*N->succ_begin())->isTrivial()) { - return child_end(*N->succ_begin()); - } + if (predecessorOfTrivial(N)) + return child_end(N->getFirstSucc()); return N->succ_end(); } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 91e47b37b7..86b776afb8 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -832,7 +832,7 @@ struct ReplayWithoutInlining{}; template <> struct ProgramStateTrait<ReplayWithoutInlining> : public ProgramStatePartialTrait<const void*> { - static void *GDMIndex() { static int index = 0; return &index; } + static void *GDMIndex(); }; } // namespace ento diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index 0b0e32b8e3..bf01289a40 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -118,6 +118,10 @@ public: const MemRegion *getBaseRegion() const; + /// Recursively retrieve the region of the most derived class instance of + /// regions of C++ base class instances. + const MemRegion *getMostDerivedObjectRegion() const; + /// Check if the region is a subregion of the given region. /// Each region is a subregion of itself. virtual bool isSubRegionOf(const MemRegion *R) const; @@ -1077,7 +1081,7 @@ public: void dump() const; }; -/// ElementRegin is used to represent both array elements and casts. +/// ElementRegion is used to represent both array elements and casts. class ElementRegion : public TypedValueRegion { friend class MemRegionManager; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index 13f5b14378..f544204497 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -348,6 +348,8 @@ public: /// a value of such type. SVal getSValAsScalarOrLoc(const MemRegion *R) const; + using region_iterator = const MemRegion **; + /// Visits the symbols reachable from the given SVal using the provided /// SymbolVisitor. /// @@ -357,24 +359,14 @@ public: /// \sa ScanReachableSymbols bool scanReachableSymbols(SVal val, SymbolVisitor& visitor) const; - /// Visits the symbols reachable from the SVals in the given range - /// using the provided SymbolVisitor. - bool scanReachableSymbols(const SVal *I, const SVal *E, - SymbolVisitor &visitor) const; - /// Visits the symbols reachable from the regions in the given /// MemRegions range using the provided SymbolVisitor. - bool scanReachableSymbols(const MemRegion * const *I, - const MemRegion * const *E, + bool scanReachableSymbols(llvm::iterator_range<region_iterator> Reachable, SymbolVisitor &visitor) const; template <typename CB> CB scanReachableSymbols(SVal val) const; - template <typename CB> CB scanReachableSymbols(const SVal *beg, - const SVal *end) const; - template <typename CB> CB - scanReachableSymbols(const MemRegion * const *beg, - const MemRegion * const *end) const; + scanReachableSymbols(llvm::iterator_range<region_iterator> Reachable) const; /// Create a new state in which the statement is marked as tainted. LLVM_NODISCARD ProgramStateRef @@ -883,17 +875,10 @@ CB ProgramState::scanReachableSymbols(SVal val) const { } template <typename CB> -CB ProgramState::scanReachableSymbols(const SVal *beg, const SVal *end) const { - CB cb(this); - scanReachableSymbols(beg, end, cb); - return cb; -} - -template <typename CB> -CB ProgramState::scanReachableSymbols(const MemRegion * const *beg, - const MemRegion * const *end) const { +CB ProgramState::scanReachableSymbols( + llvm::iterator_range<region_iterator> Reachable) const { CB cb(this); - scanReachableSymbols(beg, end, cb); + scanReachableSymbols(Reachable, cb); return cb; } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h index d2ba1f7c95..1b12a4edc2 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h @@ -131,7 +131,7 @@ using ConstraintRangeTy = llvm::ImmutableMap<SymbolRef, RangeSet>; template <> struct ProgramStateTrait<ConstraintRange> : public ProgramStatePartialTrait<ConstraintRangeTy> { - static void *GDMIndex() { static int Index; return &Index; } + static void *GDMIndex(); }; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h index 1a645cb870..8eaa9365be 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h @@ -134,9 +134,9 @@ public: // A value has been obtained, check if it is the only value SMTExprRef NotExp = SMTConv::fromBinOp( Solver, Exp, BO_NE, - Ty->isBooleanType() ? Solver->fromBoolean(Value.getBoolValue()) - : Solver->fromAPSInt(Value), - false); + Ty->isBooleanType() ? Solver->mkBoolean(Value.getBoolValue()) + : Solver->mkBitvector(Value, Value.getBitWidth()), + /*isSigned=*/false); Solver->addConstraint(NotExp); @@ -198,7 +198,7 @@ public: auto &CZFactory = State->get_context<ConstraintSMT>(); for (auto I = CZ.begin(), E = CZ.end(); I != E; ++I) { - if (SymReaper.maybeDead(I->first)) + if (SymReaper.isDead(I->first)) CZ = CZFactory.remove(CZ, *I); } @@ -218,6 +218,52 @@ public: OS << nl; } + bool canReasonAbout(SVal X) const override { + const TargetInfo &TI = getBasicVals().getContext().getTargetInfo(); + + Optional<nonloc::SymbolVal> SymVal = X.getAs<nonloc::SymbolVal>(); + if (!SymVal) + return true; + + const SymExpr *Sym = SymVal->getSymbol(); + QualType Ty = Sym->getType(); + + // Complex types are not modeled + if (Ty->isComplexType() || Ty->isComplexIntegerType()) + return false; + + // Non-IEEE 754 floating-point types are not modeled + if ((Ty->isSpecificBuiltinType(BuiltinType::LongDouble) && + (&TI.getLongDoubleFormat() == &llvm::APFloat::x87DoubleExtended() || + &TI.getLongDoubleFormat() == &llvm::APFloat::PPCDoubleDouble()))) + return false; + + if (Ty->isRealFloatingType()) + return Solver->isFPSupported(); + + if (isa<SymbolData>(Sym)) + return true; + + SValBuilder &SVB = getSValBuilder(); + + if (const SymbolCast *SC = dyn_cast<SymbolCast>(Sym)) + return canReasonAbout(SVB.makeSymbolVal(SC->getOperand())); + + if (const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) { + if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(BSE)) + return canReasonAbout(SVB.makeSymbolVal(SIE->getLHS())); + + if (const IntSymExpr *ISE = dyn_cast<IntSymExpr>(BSE)) + return canReasonAbout(SVB.makeSymbolVal(ISE->getRHS())); + + if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(BSE)) + return canReasonAbout(SVB.makeSymbolVal(SSE->getLHS())) && + canReasonAbout(SVB.makeSymbolVal(SSE->getRHS())); + } + + llvm_unreachable("Unsupported expression to reason about!"); + } + /// Dumps SMT formula LLVM_DUMP_METHOD void dump() const { Solver->dump(); } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h index 8be7d4c467..cdca2a0970 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h @@ -246,7 +246,7 @@ public: // Logical operators case BO_LAnd: case BO_LOr: - return fromBinOp(Solver, LHS, Op, RHS, false); + return fromBinOp(Solver, LHS, Op, RHS, /*isSigned=*/false); default:; } @@ -294,14 +294,14 @@ public: if (FromTy->isIntegralOrEnumerationType() && ToTy->isRealFloatingType()) { SMTSortRef Sort = Solver->getFloatSort(ToBitWidth); return FromTy->isSignedIntegerOrEnumerationType() - ? Solver->mkFPtoSBV(Exp, Sort) - : Solver->mkFPtoUBV(Exp, Sort); + ? Solver->mkSBVtoFP(Exp, Sort) + : Solver->mkUBVtoFP(Exp, Sort); } if (FromTy->isRealFloatingType() && ToTy->isIntegralOrEnumerationType()) return ToTy->isSignedIntegerOrEnumerationType() - ? Solver->mkSBVtoFP(Exp, ToBitWidth) - : Solver->mkUBVtoFP(Exp, ToBitWidth); + ? Solver->mkFPtoSBV(Exp, ToBitWidth) + : Solver->mkFPtoUBV(Exp, ToBitWidth); llvm_unreachable("Unsupported explicit type cast!"); } @@ -379,14 +379,14 @@ public: getSymExpr(Solver, Ctx, SIE->getLHS(), <y, hasComparison); llvm::APSInt NewRInt; std::tie(NewRInt, RTy) = fixAPSInt(Ctx, SIE->getRHS()); - SMTExprRef RHS = Solver->fromAPSInt(NewRInt); + SMTExprRef RHS = Solver->mkBitvector(NewRInt, NewRInt.getBitWidth()); return getBinExpr(Solver, Ctx, LHS, LTy, Op, RHS, RTy, RetTy); } if (const IntSymExpr *ISE = dyn_cast<IntSymExpr>(BSE)) { llvm::APSInt NewLInt; std::tie(NewLInt, LTy) = fixAPSInt(Ctx, ISE->getLHS()); - SMTExprRef LHS = Solver->fromAPSInt(NewLInt); + SMTExprRef LHS = Solver->mkBitvector(NewLInt, NewLInt.getBitWidth()); SMTExprRef RHS = getSymExpr(Solver, Ctx, ISE->getRHS(), &RTy, hasComparison); return getBinExpr(Solver, Ctx, LHS, LTy, Op, RHS, RTy, RetTy); @@ -466,7 +466,7 @@ public: llvm::APFloat Zero = llvm::APFloat::getZero(Ctx.getFloatTypeSemantics(Ty)); return fromFloatBinOp(Solver, Exp, Assumption ? BO_EQ : BO_NE, - Solver->fromAPFloat(Zero)); + Solver->mkFloat(Zero)); } if (Ty->isIntegralOrEnumerationType() || Ty->isAnyPointerType() || @@ -477,8 +477,10 @@ public: if (Ty->isBooleanType()) return Assumption ? fromUnOp(Solver, UO_LNot, Exp) : Exp; - return fromBinOp(Solver, Exp, Assumption ? BO_EQ : BO_NE, - Solver->fromInt("0", Ctx.getTypeSize(Ty)), isSigned); + return fromBinOp( + Solver, Exp, Assumption ? BO_EQ : BO_NE, + Solver->mkBitvector(llvm::APSInt("0"), Ctx.getTypeSize(Ty)), + isSigned); } llvm_unreachable("Unsupported type for zero value!"); @@ -493,7 +495,8 @@ public: QualType FromTy; llvm::APSInt NewFromInt; std::tie(NewFromInt, FromTy) = fixAPSInt(Ctx, From); - SMTExprRef FromExp = Solver->fromAPSInt(NewFromInt); + SMTExprRef FromExp = + Solver->mkBitvector(NewFromInt, NewFromInt.getBitWidth()); // Convert symbol QualType SymTy; @@ -507,7 +510,7 @@ public: QualType ToTy; llvm::APSInt NewToInt; std::tie(NewToInt, ToTy) = fixAPSInt(Ctx, To); - SMTExprRef ToExp = Solver->fromAPSInt(NewToInt); + SMTExprRef ToExp = Solver->mkBitvector(NewToInt, NewToInt.getBitWidth()); assert(FromTy == ToTy && "Range values have different types!"); // Construct two (in)equalities, and a logical and/or diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h index 71bfb400fc..2abe5fc987 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h @@ -226,23 +226,23 @@ public: /// operation virtual SMTExprRef mkFPtoFP(const SMTExprRef &From, const SMTSortRef &To) = 0; - /// Creates a floating-point conversion from floatint-point to signed - /// bitvector operation - virtual SMTExprRef mkFPtoSBV(const SMTExprRef &From, - const SMTSortRef &To) = 0; - - /// Creates a floating-point conversion from floatint-point to unsigned - /// bitvector operation - virtual SMTExprRef mkFPtoUBV(const SMTExprRef &From, - const SMTSortRef &To) = 0; - /// Creates a floating-point conversion from signed bitvector to /// floatint-point operation - virtual SMTExprRef mkSBVtoFP(const SMTExprRef &From, unsigned ToWidth) = 0; + virtual SMTExprRef mkSBVtoFP(const SMTExprRef &From, + const SMTSortRef &To) = 0; /// Creates a floating-point conversion from unsigned bitvector to /// floatint-point operation - virtual SMTExprRef mkUBVtoFP(const SMTExprRef &From, unsigned ToWidth) = 0; + virtual SMTExprRef mkUBVtoFP(const SMTExprRef &From, + const SMTSortRef &To) = 0; + + /// Creates a floating-point conversion from floatint-point to signed + /// bitvector operation + virtual SMTExprRef mkFPtoSBV(const SMTExprRef &From, unsigned ToWidth) = 0; + + /// Creates a floating-point conversion from floatint-point to unsigned + /// bitvector operation + virtual SMTExprRef mkFPtoUBV(const SMTExprRef &From, unsigned ToWidth) = 0; /// Creates a new symbol, given a name and a sort virtual SMTExprRef mkSymbol(const char *Name, SMTSortRef Sort) = 0; @@ -273,18 +273,6 @@ public: virtual bool getInterpretation(const SMTExprRef &Exp, llvm::APFloat &Float) = 0; - /// Construct an SMTExprRef value from a boolean. - virtual SMTExprRef fromBoolean(const bool Bool) = 0; - - /// Construct an SMTExprRef value from a finite APFloat. - virtual SMTExprRef fromAPFloat(const llvm::APFloat &Float) = 0; - - /// Construct an SMTExprRef value from an APSInt. - virtual SMTExprRef fromAPSInt(const llvm::APSInt &Int) = 0; - - /// Construct an SMTExprRef value from an integer. - virtual SMTExprRef fromInt(const char *Int, uint64_t BitWidth) = 0; - /// Check if the constraints are satisfiable virtual Optional<bool> check() const = 0; @@ -295,7 +283,10 @@ public: virtual void pop(unsigned NumStates = 1) = 0; /// Reset the solver and remove all constraints. - virtual void reset() const = 0; + virtual void reset() = 0; + + /// Checks if the solver supports floating-points. + virtual bool isFPSupported() = 0; virtual void print(raw_ostream &OS) const = 0; }; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h index 4ab7161459..f49f761c77 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h @@ -260,12 +260,12 @@ public: public: virtual ~BindingsHandler(); + /// \return whether the iteration should continue. virtual bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion *region, SVal val) = 0; }; - class FindUniqueBinding : - public BindingsHandler { + class FindUniqueBinding : public BindingsHandler { SymbolRef Sym; const MemRegion* Binding = nullptr; bool First = true; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h index b014c63709..d02a8abd11 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h @@ -558,7 +558,6 @@ class SymbolReaper { SymbolMapTy TheLiving; SymbolSetTy MetadataInUse; - SymbolSetTy TheDead; RegionSetTy RegionRoots; @@ -603,21 +602,6 @@ public: /// symbol marking has occurred, i.e. in the MarkLiveSymbols callback. void markInUse(SymbolRef sym); - /// If a symbol is known to be live, marks the symbol as live. - /// - /// Otherwise, if the symbol cannot be proven live, it is marked as dead. - /// Returns true if the symbol is dead, false if live. - bool maybeDead(SymbolRef sym); - - using dead_iterator = SymbolSetTy::const_iterator; - - dead_iterator dead_begin() const { return TheDead.begin(); } - dead_iterator dead_end() const { return TheDead.end(); } - - bool hasDeadSymbols() const { - return !TheDead.empty(); - } - using region_iterator = RegionSetTy::const_iterator; region_iterator region_begin() const { return RegionRoots.begin(); } @@ -626,9 +610,9 @@ public: /// Returns whether or not a symbol has been confirmed dead. /// /// This should only be called once all marking of dead symbols has completed. - /// (For checkers, this means only in the evalDeadSymbols callback.) - bool isDead(SymbolRef sym) const { - return TheDead.count(sym); + /// (For checkers, this means only in the checkDeadSymbols callback.) + bool isDead(SymbolRef sym) { + return !isLive(sym); } void markLive(const MemRegion *region); diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h index ce19b7131d..8218fb1eea 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h @@ -34,10 +34,7 @@ using TaintMapImpl = llvm::ImmutableMap<SymbolRef, TaintTagType>; template<> struct ProgramStateTrait<TaintMap> : public ProgramStatePartialTrait<TaintMapImpl> { - static void *GDMIndex() { - static int index = 0; - return &index; - } + static void *GDMIndex(); }; /// The GDM component mapping derived symbols' parent symbols to their @@ -49,10 +46,7 @@ using DerivedSymTaintImpl = llvm::ImmutableMap<SymbolRef, TaintedSubRegions>; template<> struct ProgramStateTrait<DerivedSymTaint> : public ProgramStatePartialTrait<DerivedSymTaintImpl> { - static void *GDMIndex() { - static int index; - return &index; - } + static void *GDMIndex(); }; class TaintManager { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h index 07edd35ff9..ef3c2694b2 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h @@ -85,6 +85,7 @@ public: static std::unique_ptr<WorkList> makeBFSBlockDFSContents(); static std::unique_ptr<WorkList> makeUnexploredFirst(); static std::unique_ptr<WorkList> makeUnexploredFirstPriorityQueue(); + static std::unique_ptr<WorkList> makeUnexploredFirstPriorityLocationQueue(); }; } // end ento namespace |