diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h index c530dff495238..cbbea1b56bb40 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h @@ -113,10 +113,10 @@ class SymbolConjured : public SymbolData { void dumpToStream(raw_ostream &os) const override; - static void Profile(llvm::FoldingSetNodeID& profile, const Stmt *S, - QualType T, unsigned Count, const LocationContext *LCtx, + static void Profile(llvm::FoldingSetNodeID &profile, const Stmt *S, + const LocationContext *LCtx, QualType T, unsigned Count, const void *SymbolTag) { - profile.AddInteger((unsigned) SymbolConjuredKind); + profile.AddInteger((unsigned)SymbolConjuredKind); profile.AddPointer(S); profile.AddPointer(LCtx); profile.Add(T); @@ -125,7 +125,7 @@ class SymbolConjured : public SymbolData { } void Profile(llvm::FoldingSetNodeID& profile) override { - Profile(profile, S, T, Count, LCtx, SymbolTag); + Profile(profile, S, LCtx, T, Count, SymbolTag); } // Implement isa support. @@ -224,6 +224,8 @@ class SymbolMetadata : public SymbolData { const Stmt *S; QualType T; const LocationContext *LCtx; + /// Count can be used to differentiate regions corresponding to + /// different loop iterations, thus, making the symbol path-dependent. unsigned Count; const void *Tag; @@ -525,14 +527,18 @@ class SymbolManager { static bool canSymbolicate(QualType T); - /// Make a unique symbol for MemRegion R according to its kind. - const SymbolRegionValue* getRegionValueSymbol(const TypedValueRegion* R); + /// Create or retrieve a SymExpr of type \p SymExprT for the given arguments. + /// Use the arguments to check for an existing SymExpr and return it, + /// otherwise, create a new one and keep a pointer to it to avoid duplicates. + template + const SymExprT *acquire(Args &&...args); - const SymbolConjured* conjureSymbol(const Stmt *E, - const LocationContext *LCtx, - QualType T, + const SymbolConjured *conjureSymbol(const Stmt *E, + const LocationContext *LCtx, QualType T, unsigned VisitCount, - const void *SymbolTag = nullptr); + const void *SymbolTag = nullptr) { + return acquire(E, LCtx, T, VisitCount, SymbolTag); + } const SymbolConjured* conjureSymbol(const Expr *E, const LocationContext *LCtx, @@ -541,41 +547,6 @@ class SymbolManager { return conjureSymbol(E, LCtx, E->getType(), VisitCount, SymbolTag); } - const SymbolDerived *getDerivedSymbol(SymbolRef parentSymbol, - const TypedValueRegion *R); - - const SymbolExtent *getExtentSymbol(const SubRegion *R); - - /// Creates a metadata symbol associated with a specific region. - /// - /// VisitCount can be used to differentiate regions corresponding to - /// different loop iterations, thus, making the symbol path-dependent. - const SymbolMetadata *getMetadataSymbol(const MemRegion *R, const Stmt *S, - QualType T, - const LocationContext *LCtx, - unsigned VisitCount, - const void *SymbolTag = nullptr); - - const SymbolCast* getCastSymbol(const SymExpr *Operand, - QualType From, QualType To); - - const SymIntExpr *getSymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op, - APSIntPtr rhs, QualType t); - - const SymIntExpr *getSymIntExpr(const SymExpr &lhs, BinaryOperator::Opcode op, - APSIntPtr rhs, QualType t) { - return getSymIntExpr(&lhs, op, rhs, t); - } - - const IntSymExpr *getIntSymExpr(APSIntPtr lhs, BinaryOperator::Opcode op, - const SymExpr *rhs, QualType t); - - const SymSymExpr *getSymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, - const SymExpr *rhs, QualType t); - - const UnarySymExpr *getUnarySymExpr(const SymExpr *operand, - UnaryOperator::Opcode op, QualType t); - QualType getType(const SymExpr *SE) const { return SE->getType(); } @@ -707,6 +678,19 @@ class SymbolVisitor { virtual bool VisitMemRegion(const MemRegion *) { return true; } }; +template +const T *SymbolManager::acquire(Args &&...args) { + llvm::FoldingSetNodeID profile; + T::Profile(profile, args...); + void *InsertPos; + SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); + if (!SD) { + SD = Alloc.make(std::forward(args)...); + DataSet.InsertNode(SD, InsertPos); + } + return cast(SD); +} + } // namespace ento } // namespace clang diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp index 559c80634c12e..2c5cd2cf7630f 100644 --- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -811,7 +811,7 @@ DefinedOrUnknownSVal MemRegionManager::getStaticSize(const MemRegion *MR, switch (SR->getKind()) { case MemRegion::AllocaRegionKind: case MemRegion::SymbolicRegionKind: - return nonloc::SymbolVal(SymMgr.getExtentSymbol(SR)); + return nonloc::SymbolVal(SymMgr.acquire(SR)); case MemRegion::StringRegionKind: return SVB.makeIntVal( cast(SR)->getStringLiteral()->getByteLength() + 1, @@ -829,7 +829,7 @@ DefinedOrUnknownSVal MemRegionManager::getStaticSize(const MemRegion *MR, case MemRegion::ObjCStringRegionKind: { QualType Ty = cast(SR)->getDesugaredValueType(Ctx); if (isa(Ty)) - return nonloc::SymbolVal(SymMgr.getExtentSymbol(SR)); + return nonloc::SymbolVal(SymMgr.acquire(SR)); if (Ty->isIncompleteType()) return UnknownVal(); @@ -897,7 +897,7 @@ DefinedOrUnknownSVal MemRegionManager::getStaticSize(const MemRegion *MR, case MemRegion::BlockDataRegionKind: case MemRegion::BlockCodeRegionKind: case MemRegion::FunctionCodeRegionKind: - return nonloc::SymbolVal(SymMgr.getExtentSymbol(SR)); + return nonloc::SymbolVal(SymMgr.acquire(SR)); default: llvm_unreachable("Unhandled region"); } diff --git a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp index c39fa81109c85..ab45e678bafd5 100644 --- a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp @@ -1471,7 +1471,7 @@ class SymbolicRangeInferrer return getRangeForNegatedExpr( [SSE, State = this->State]() -> SymbolRef { if (SSE->getOpcode() == BO_Sub) - return State->getSymbolManager().getSymSymExpr( + return State->getSymbolManager().acquire( SSE->getRHS(), BO_Sub, SSE->getLHS(), SSE->getType()); return nullptr; }, @@ -1481,8 +1481,8 @@ class SymbolicRangeInferrer std::optional getRangeForNegatedSym(SymbolRef Sym) { return getRangeForNegatedExpr( [Sym, State = this->State]() { - return State->getSymbolManager().getUnarySymExpr(Sym, UO_Minus, - Sym->getType()); + return State->getSymbolManager().acquire( + Sym, UO_Minus, Sym->getType()); }, Sym->getType()); } @@ -1495,7 +1495,7 @@ class SymbolicRangeInferrer if (!IsCommutative) return std::nullopt; - SymbolRef Commuted = State->getSymbolManager().getSymSymExpr( + SymbolRef Commuted = State->getSymbolManager().acquire( SSE->getRHS(), Op, SSE->getLHS(), SSE->getType()); if (const RangeSet *Range = getConstraint(State, Commuted)) return *Range; @@ -1540,7 +1540,8 @@ class SymbolicRangeInferrer // Let's find an expression e.g. (x < y). BinaryOperatorKind QueriedOP = OperatorRelationsTable::getOpFromIndex(i); - const SymSymExpr *SymSym = SymMgr.getSymSymExpr(LHS, QueriedOP, RHS, T); + const SymSymExpr *SymSym = + SymMgr.acquire(LHS, QueriedOP, RHS, T); const RangeSet *QueriedRangeSet = getConstraint(State, SymSym); // If ranges were not previously found, @@ -1548,7 +1549,7 @@ class SymbolicRangeInferrer if (!QueriedRangeSet) { const BinaryOperatorKind ROP = BinaryOperator::reverseComparisonOp(QueriedOP); - SymSym = SymMgr.getSymSymExpr(RHS, ROP, LHS, T); + SymSym = SymMgr.acquire(RHS, ROP, LHS, T); QueriedRangeSet = getConstraint(State, SymSym); } diff --git a/clang/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp b/clang/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp index 4bbe933be2129..94dcdaf327689 100644 --- a/clang/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/RangedConstraintManager.cpp @@ -62,8 +62,8 @@ ProgramStateRef RangedConstraintManager::assumeSym(ProgramStateRef State, SymbolManager &SymMgr = getSymbolManager(); QualType DiffTy = SymMgr.getContext().getPointerDiffType(); - SymbolRef Subtraction = - SymMgr.getSymSymExpr(SSE->getRHS(), BO_Sub, SSE->getLHS(), DiffTy); + SymbolRef Subtraction = SymMgr.acquire( + SSE->getRHS(), BO_Sub, SSE->getLHS(), DiffTy); const llvm::APSInt &Zero = getBasicVals().getValue(0, DiffTy); Op = BinaryOperator::reverseComparisonOp(Op); @@ -76,8 +76,8 @@ ProgramStateRef RangedConstraintManager::assumeSym(ProgramStateRef State, SymbolManager &SymMgr = getSymbolManager(); QualType ExprType = SSE->getType(); - SymbolRef CanonicalEquality = - SymMgr.getSymSymExpr(SSE->getLHS(), BO_EQ, SSE->getRHS(), ExprType); + SymbolRef CanonicalEquality = SymMgr.acquire( + SSE->getLHS(), BO_EQ, SSE->getRHS(), ExprType); bool WasEqual = SSE->getOpcode() == BO_EQ; bool IsExpectedEqual = WasEqual == Assumption; diff --git a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp index 2b85580186381..4f45b24be86c1 100644 --- a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -79,7 +79,7 @@ nonloc::SymbolVal SValBuilder::makeNonLoc(const SymExpr *lhs, APSIntPtr rhs, QualType type) { assert(lhs); assert(!Loc::isLocType(type)); - return nonloc::SymbolVal(SymMgr.getSymIntExpr(lhs, op, rhs, type)); + return nonloc::SymbolVal(SymMgr.acquire(lhs, op, rhs, type)); } nonloc::SymbolVal SValBuilder::makeNonLoc(APSIntPtr lhs, @@ -87,7 +87,7 @@ nonloc::SymbolVal SValBuilder::makeNonLoc(APSIntPtr lhs, const SymExpr *rhs, QualType type) { assert(rhs); assert(!Loc::isLocType(type)); - return nonloc::SymbolVal(SymMgr.getIntSymExpr(lhs, op, rhs, type)); + return nonloc::SymbolVal(SymMgr.acquire(lhs, op, rhs, type)); } nonloc::SymbolVal SValBuilder::makeNonLoc(const SymExpr *lhs, @@ -95,14 +95,14 @@ nonloc::SymbolVal SValBuilder::makeNonLoc(const SymExpr *lhs, const SymExpr *rhs, QualType type) { assert(lhs && rhs); assert(!Loc::isLocType(type)); - return nonloc::SymbolVal(SymMgr.getSymSymExpr(lhs, op, rhs, type)); + return nonloc::SymbolVal(SymMgr.acquire(lhs, op, rhs, type)); } NonLoc SValBuilder::makeNonLoc(const SymExpr *operand, UnaryOperator::Opcode op, QualType type) { assert(operand); assert(!Loc::isLocType(type)); - return nonloc::SymbolVal(SymMgr.getUnarySymExpr(operand, op, type)); + return nonloc::SymbolVal(SymMgr.acquire(operand, op, type)); } nonloc::SymbolVal SValBuilder::makeNonLoc(const SymExpr *operand, @@ -111,7 +111,7 @@ nonloc::SymbolVal SValBuilder::makeNonLoc(const SymExpr *operand, assert(!Loc::isLocType(toTy)); if (fromTy == toTy) return nonloc::SymbolVal(operand); - return nonloc::SymbolVal(SymMgr.getCastSymbol(operand, fromTy, toTy)); + return nonloc::SymbolVal(SymMgr.acquire(operand, fromTy, toTy)); } SVal SValBuilder::convertToArrayIndex(SVal val) { @@ -143,7 +143,7 @@ SValBuilder::getRegionValueSymbolVal(const TypedValueRegion *region) { if (!SymbolManager::canSymbolicate(T)) return UnknownVal(); - SymbolRef sym = SymMgr.getRegionValueSymbol(region); + SymbolRef sym = SymMgr.acquire(region); if (Loc::isLocType(T)) return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym)); @@ -244,8 +244,8 @@ DefinedSVal SValBuilder::getMetadataSymbolVal(const void *symbolTag, unsigned count) { assert(SymbolManager::canSymbolicate(type) && "Invalid metadata symbol type"); - SymbolRef sym = - SymMgr.getMetadataSymbol(region, expr, type, LCtx, count, symbolTag); + SymbolRef sym = SymMgr.acquire(region, expr, type, LCtx, + count, symbolTag); if (Loc::isLocType(type)) return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym)); @@ -264,7 +264,7 @@ SValBuilder::getDerivedRegionValueSymbolVal(SymbolRef parentSymbol, if (!SymbolManager::canSymbolicate(T)) return UnknownVal(); - SymbolRef sym = SymMgr.getDerivedSymbol(parentSymbol, region); + SymbolRef sym = SymMgr.acquire(parentSymbol, region); if (Loc::isLocType(T)) return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym)); @@ -724,7 +724,7 @@ class EvalCastVisitor : public SValVisitor { // because there are no generic region address metadata // symbols to use, only content metadata. return nonloc::SymbolVal( - VB.getSymbolManager().getExtentSymbol(FTR)); + VB.getSymbolManager().acquire(FTR)); if (const SymbolicRegion *SymR = R->getSymbolicBase()) { SymbolRef Sym = SymR->getSymbol(); diff --git a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp index 455621739f693..afb0273d23bd4 100644 --- a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp +++ b/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp @@ -328,16 +328,16 @@ static NonLoc doRearrangeUnchecked(ProgramStateRef State, // FIXME: Maybe it'd be better to have consistency in // "$x - $y" vs. "$y - $x" because those are solver's keys. if (LInt > RInt) { - ResultSym = SymMgr.getSymSymExpr(RSym, BO_Sub, LSym, SymTy); + ResultSym = SymMgr.acquire(RSym, BO_Sub, LSym, SymTy); ResultOp = BinaryOperator::reverseComparisonOp(Op); ResultInt = LInt - RInt; // Opposite order! } else { - ResultSym = SymMgr.getSymSymExpr(LSym, BO_Sub, RSym, SymTy); + ResultSym = SymMgr.acquire(LSym, BO_Sub, RSym, SymTy); ResultOp = Op; ResultInt = RInt - LInt; // Opposite order! } } else { - ResultSym = SymMgr.getSymSymExpr(LSym, Op, RSym, SymTy); + ResultSym = SymMgr.acquire(LSym, Op, RSym, SymTy); ResultInt = (Op == BO_Add) ? (LInt + RInt) : (LInt - RInt); ResultOp = BO_Add; // Bring back the cosmetic difference. @@ -350,8 +350,8 @@ static NonLoc doRearrangeUnchecked(ProgramStateRef State, } } APSIntPtr PersistentResultInt = BV.getValue(ResultInt); - return nonloc::SymbolVal( - SymMgr.getSymIntExpr(ResultSym, ResultOp, PersistentResultInt, ResultTy)); + return nonloc::SymbolVal(SymMgr.acquire( + ResultSym, ResultOp, PersistentResultInt, ResultTy)); } // Rearrange if symbol type matches the result type and if the operator is a diff --git a/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp b/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp index 738b6a175ce6d..a4648f5922ef1 100644 --- a/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp @@ -163,161 +163,6 @@ void SymExpr::symbol_iterator::expand() { llvm_unreachable("unhandled expansion case"); } -const SymbolRegionValue* -SymbolManager::getRegionValueSymbol(const TypedValueRegion* R) { - llvm::FoldingSetNodeID profile; - SymbolRegionValue::Profile(profile, R); - void *InsertPos; - SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); - if (!SD) { - SD = Alloc.make(R); - DataSet.InsertNode(SD, InsertPos); - } - - return cast(SD); -} - -const SymbolConjured* SymbolManager::conjureSymbol(const Stmt *E, - const LocationContext *LCtx, - QualType T, - unsigned Count, - const void *SymbolTag) { - llvm::FoldingSetNodeID profile; - SymbolConjured::Profile(profile, E, T, Count, LCtx, SymbolTag); - void *InsertPos; - SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); - if (!SD) { - SD = Alloc.make(E, LCtx, T, Count, SymbolTag); - DataSet.InsertNode(SD, InsertPos); - } - - return cast(SD); -} - -const SymbolDerived* -SymbolManager::getDerivedSymbol(SymbolRef parentSymbol, - const TypedValueRegion *R) { - llvm::FoldingSetNodeID profile; - SymbolDerived::Profile(profile, parentSymbol, R); - void *InsertPos; - SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); - if (!SD) { - SD = Alloc.make(parentSymbol, R); - DataSet.InsertNode(SD, InsertPos); - } - - return cast(SD); -} - -const SymbolExtent* -SymbolManager::getExtentSymbol(const SubRegion *R) { - llvm::FoldingSetNodeID profile; - SymbolExtent::Profile(profile, R); - void *InsertPos; - SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); - if (!SD) { - SD = Alloc.make(R); - DataSet.InsertNode(SD, InsertPos); - } - - return cast(SD); -} - -const SymbolMetadata * -SymbolManager::getMetadataSymbol(const MemRegion* R, const Stmt *S, QualType T, - const LocationContext *LCtx, - unsigned Count, const void *SymbolTag) { - llvm::FoldingSetNodeID profile; - SymbolMetadata::Profile(profile, R, S, T, LCtx, Count, SymbolTag); - void *InsertPos; - SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); - if (!SD) { - SD = Alloc.make(R, S, T, LCtx, Count, SymbolTag); - DataSet.InsertNode(SD, InsertPos); - } - - return cast(SD); -} - -const SymbolCast* -SymbolManager::getCastSymbol(const SymExpr *Op, - QualType From, QualType To) { - llvm::FoldingSetNodeID ID; - SymbolCast::Profile(ID, Op, From, To); - void *InsertPos; - SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos); - if (!data) { - data = Alloc.make(Op, From, To); - DataSet.InsertNode(data, InsertPos); - } - - return cast(data); -} - -const SymIntExpr *SymbolManager::getSymIntExpr(const SymExpr *lhs, - BinaryOperator::Opcode op, - APSIntPtr v, QualType t) { - llvm::FoldingSetNodeID ID; - SymIntExpr::Profile(ID, lhs, op, v, t); - void *InsertPos; - SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos); - - if (!data) { - data = Alloc.make(lhs, op, v, t); - DataSet.InsertNode(data, InsertPos); - } - - return cast(data); -} - -const IntSymExpr *SymbolManager::getIntSymExpr(APSIntPtr lhs, - BinaryOperator::Opcode op, - const SymExpr *rhs, QualType t) { - llvm::FoldingSetNodeID ID; - IntSymExpr::Profile(ID, lhs, op, rhs, t); - void *InsertPos; - SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos); - - if (!data) { - data = Alloc.make(lhs, op, rhs, t); - DataSet.InsertNode(data, InsertPos); - } - - return cast(data); -} - -const SymSymExpr *SymbolManager::getSymSymExpr(const SymExpr *lhs, - BinaryOperator::Opcode op, - const SymExpr *rhs, - QualType t) { - llvm::FoldingSetNodeID ID; - SymSymExpr::Profile(ID, lhs, op, rhs, t); - void *InsertPos; - SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos); - - if (!data) { - data = Alloc.make(lhs, op, rhs, t); - DataSet.InsertNode(data, InsertPos); - } - - return cast(data); -} - -const UnarySymExpr *SymbolManager::getUnarySymExpr(const SymExpr *Operand, - UnaryOperator::Opcode Opc, - QualType T) { - llvm::FoldingSetNodeID ID; - UnarySymExpr::Profile(ID, Operand, Opc, T); - void *InsertPos; - SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos); - if (!data) { - data = Alloc.make(Operand, Opc, T); - DataSet.InsertNode(data, InsertPos); - } - - return cast(data); -} - QualType SymbolConjured::getType() const { return T; }