llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-static-analyzer-1 Author: Balázs Benics (steakhal) <details> <summary>Changes</summary> Implementation of https://discourse.llvm.org/t/memory-region-invalidation-tracking-improvements/62432 I plan to lan each commit as a separate PR. I'm just posting this in a single PR for now to let you review commit by commit, or to see the grand picture. The code was written by claude, but I've carefully vetted and tuned it. --- Patch is 105.78 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/207155.diff 42 Files Affected: - (modified) clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h (+10) - (modified) clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h (+9) - (added) clang/include/clang/StaticAnalyzer/Core/PathSensitive/InvalidationCause.h (+206) - (modified) clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h (+7-2) - (modified) clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h (+9-2) - (modified) clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h (+11) - (modified) clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h (+7-1) - (modified) clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h (+113) - (modified) clang/include/clang/StaticAnalyzer/Core/PathSensitive/Symbols.def (+2-1) - (modified) clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp (+42-42) - (modified) clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp (+8-3) - (modified) clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.h (+2-1) - (modified) clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (+6-4) - (modified) clang/lib/StaticAnalyzer/Checkers/MismatchedIteratorChecker.cpp (+4-4) - (modified) clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp (+8-1) - (modified) clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp (+2-1) - (modified) clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp (+1-2) - (modified) clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp (+8-5) - (modified) clang/lib/StaticAnalyzer/Core/CMakeLists.txt (+1) - (modified) clang/lib/StaticAnalyzer/Core/CallEvent.cpp (+6-1) - (modified) clang/lib/StaticAnalyzer/Core/ExprEngine.cpp (+22-10) - (modified) clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp (+5-3) - (added) clang/lib/StaticAnalyzer/Core/InvalidationCause.cpp (+47) - (modified) clang/lib/StaticAnalyzer/Core/LoopWidening.cpp (+8-4) - (modified) clang/lib/StaticAnalyzer/Core/ProgramState.cpp (+6-4) - (modified) clang/lib/StaticAnalyzer/Core/RegionStore.cpp (+56-18) - (modified) clang/lib/StaticAnalyzer/Core/SValBuilder.cpp (+21) - (modified) clang/lib/StaticAnalyzer/Core/SymbolManager.cpp (+22) - (modified) clang/test/Analysis/PR57270.cpp (+2-2) - (modified) clang/test/Analysis/ctor-trivial-copy.cpp (+6-6) - (modified) clang/test/Analysis/dtor-array.cpp (+1-1) - (modified) clang/test/Analysis/dump_egraph.cpp (+1-1) - (modified) clang/test/Analysis/explain-svals.cpp (+3-3) - (modified) clang/test/Analysis/fread.c (+28-28) - (modified) clang/test/Analysis/getline-unixapi.c (+4-4) - (added) clang/test/Analysis/invalidation-artifact-dump.c (+82) - (added) clang/test/Analysis/invalidation-artifact-loop-widening.c (+19) - (added) clang/test/Analysis/invalidation-artifact-partial-call.c (+30) - (added) clang/test/Analysis/invalidation-artifact-unmodeled-expr.c (+18) - (modified) clang/test/Analysis/store-dump-orders.cpp (+2-2) - (modified) clang/test/Analysis/stream-invalidate.c (+12-12) - (modified) clang/test/Analysis/taint-generic.c (+3-3) ``````````diff diff --git a/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h b/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h index 6c1025ecc7f4d..bce3934ba0f4b 100644 --- a/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h +++ b/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h @@ -126,6 +126,16 @@ class SValExplainer : public FullSValVisitor<SValExplainer, std::string> { printCFGElementRef(S->getCFGElementRef()) + "'"; } + std::string + VisitSymbolInvalidationArtifact(const SymbolInvalidationArtifact *S) { + std::string CauseStr; + llvm::raw_string_ostream OS(CauseStr); + S->getCause()->dumpToStream(OS); + return "invalidation artifact (" + CauseStr + ") of type '" + + S->getType().getAsString() + "' at CFG element '" + + printCFGElementRef(S->getCFGElementRef()) + "'"; + } + std::string VisitSymbolDerived(const SymbolDerived *S) { return "value derived from (" + Visit(S->getParentSymbol()) + ") for " + Visit(S->getRegion()); diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h index 3252421414181..28e653c3a4680 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -29,6 +29,7 @@ #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/InvalidationCause.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" @@ -263,6 +264,14 @@ class CallEvent { return Origin.dyn_cast<const Expr *>(); } + template <class CauseT> const CauseT *tryCreateInvalidationCause() const { + static_assert(std::is_base_of_v<UnmodeledCall, CauseT>, + "forInvalidation<T> requires T : UnmodeledCall"); + const auto *CE = dyn_cast_or_null<CallExpr>(getOriginExpr()); + auto &SymMgr = State->getStateManager().getSymbolManager(); + return SymMgr.acquireCause<CauseT>(CE); + } + /// Returns the number of arguments (explicit and implicit). /// /// Note that this may be greater than the number of parameters in the diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/InvalidationCause.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/InvalidationCause.h new file mode 100644 index 0000000000000..42dc48faa12aa --- /dev/null +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/InvalidationCause.h @@ -0,0 +1,206 @@ +//===- InvalidationCause.h - Cause of a region invalidation ------*- C++ -*-==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines InvalidationCause, a small class hierarchy describing why +// a memory region was invalidated by ProgramState::invalidateRegions. The +// cause is carried by SymbolInvalidationArtifact symbols so that downstream +// machinery (bug-report suppression, diagnostics) can distinguish symbolic +// values produced by an invalidation event from ordinary conjured symbols. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_INVALIDATIONCAUSE_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_INVALIDATIONCAUSE_H + +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/Compiler.h" + +namespace clang { + +class CallExpr; +class Stmt; + +namespace ento { + +class SymbolManager; + +/// Describes why a memory region was invalidated. Instances are uniqued by +/// SymbolManager::acquireCause<T>(...) and are stable for the analysis +/// lifetime; callers must not allocate them on the stack. +class InvalidationCause : public llvm::FoldingSetNode { +public: + virtual ~InvalidationCause() = default; + + enum Kind { + // UnmodeledCall range + ConservativeEvalCallKind, + PartiallyModeledCallKind, + BEGIN_UNMODELED_CALL = ConservativeEvalCallKind, + END_UNMODELED_CALL = PartiallyModeledCallKind, + + // UnmodeledStmt range + UnmodeledExprKind, + LoopWideningKind, + BEGIN_UNMODELED_STMT = UnmodeledExprKind, + END_UNMODELED_STMT = LoopWideningKind, + }; + + Kind getKind() const { return K; } + + virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0; + virtual void dumpToStream(raw_ostream &OS) const = 0; + + LLVM_DUMP_METHOD void dump() const; + +protected: + explicit InvalidationCause(Kind K) : K(K) {} + virtual void anchor(); + +private: + Kind K; +}; + +/// Abstract base for invalidations triggered by an unmodeled or partially +/// modeled call. +class UnmodeledCall : public InvalidationCause { +public: + /// Returns the expression whose value will be the result of this call. + /// Null if and only if 'this' is a CXXDestructorCall. + const CallExpr *getCallExpr() const { return CE; } + + static bool classof(const InvalidationCause *C) { + return C->getKind() >= BEGIN_UNMODELED_CALL && + C->getKind() <= END_UNMODELED_CALL; + } + +protected: + const CallExpr *CE; + UnmodeledCall(Kind K, const CallExpr *CE) : InvalidationCause(K), CE(CE) {} + void anchor() override; +}; + +/// Conservative evaluation of a call: the call's body wasn't inlined and we +/// fall back to invalidating its arguments / reachable globals. +class ConservativeEvalCall final : public UnmodeledCall { +public: + void Profile(llvm::FoldingSetNodeID &ID) const override { Profile(ID, CE); } + + static void Profile(llvm::FoldingSetNodeID &ID, const CallExpr *CE) { + ID.AddInteger((unsigned)ConservativeEvalCallKind); + ID.AddPointer(CE); + } + + void dumpToStream(raw_ostream &OS) const override; + + static bool classof(const InvalidationCause *C) { + return C->getKind() == ConservativeEvalCallKind; + } + +protected: + friend class SymbolManager; + explicit ConservativeEvalCall(const CallExpr *CE) + : UnmodeledCall(ConservativeEvalCallKind, CE) {} + void anchor() override; +}; + +/// A call that the analyzer models but bails out of for some operands (e.g. +/// CStringChecker's memcpy fallback, MallocChecker's free invalidation, +/// SmartPtrModeling's ostream<< handling). +class PartiallyModeledCall final : public UnmodeledCall { +public: + void Profile(llvm::FoldingSetNodeID &ID) const override { Profile(ID, CE); } + + static void Profile(llvm::FoldingSetNodeID &ID, const CallExpr *CE) { + ID.AddInteger((unsigned)PartiallyModeledCallKind); + ID.AddPointer(CE); + } + + void dumpToStream(raw_ostream &OS) const override; + + static bool classof(const InvalidationCause *C) { + return C->getKind() == PartiallyModeledCallKind; + } + +protected: + friend class SymbolManager; + explicit PartiallyModeledCall(const CallExpr *CE) + : UnmodeledCall(PartiallyModeledCallKind, CE) {} + void anchor() override; +}; + +/// Abstract base for invalidations triggered by an unmodeled statement +/// (atomics, inline asm) or a widened loop. +class UnmodeledStmt : public InvalidationCause { +public: + LLVM_ATTRIBUTE_RETURNS_NONNULL + const Stmt *getStmt() const { return S; } + + static bool classof(const InvalidationCause *C) { + return C->getKind() >= BEGIN_UNMODELED_STMT && + C->getKind() <= END_UNMODELED_STMT; + } + +protected: + const Stmt *S; + UnmodeledStmt(Kind K, const Stmt *S) : InvalidationCause(K), S(S) { + assert(S); + } + void anchor() override; +}; + +/// An expression we don't model (e.g. AtomicExpr, GCCAsmStmt). +class UnmodeledExpr final : public UnmodeledStmt { +public: + void Profile(llvm::FoldingSetNodeID &ID) const override { Profile(ID, S); } + + static void Profile(llvm::FoldingSetNodeID &ID, const Stmt *S) { + ID.AddInteger((unsigned)UnmodeledExprKind); + ID.AddPointer(S); + } + + void dumpToStream(raw_ostream &OS) const override; + + static bool classof(const InvalidationCause *C) { + return C->getKind() == UnmodeledExprKind; + } + +private: + friend class SymbolManager; + explicit UnmodeledExpr(const Stmt *S) : UnmodeledStmt(UnmodeledExprKind, S) {} + void anchor() override; +}; + +/// The widened loop's invalidation event. +class LoopWidening final : public UnmodeledStmt { +public: + void Profile(llvm::FoldingSetNodeID &ID) const override { Profile(ID, S); } + + static void Profile(llvm::FoldingSetNodeID &ID, const Stmt *S) { + ID.AddInteger((unsigned)LoopWideningKind); + ID.AddPointer(S); + } + + void dumpToStream(raw_ostream &OS) const override; + + static bool classof(const InvalidationCause *C) { + return C->getKind() == LoopWideningKind; + } + +protected: + friend class SymbolManager; + explicit LoopWidening(const Stmt *S) : UnmodeledStmt(LoopWideningKind, S) {} + void anchor() override; +}; + +raw_ostream &operator<<(raw_ostream &OS, const InvalidationCause &C); + +} // namespace ento +} // namespace clang + +#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_INVALIDATIONCAUSE_H diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h index b9e7732a4fee3..22b67eb7e44a7 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h @@ -15,17 +15,22 @@ #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_LOOPWIDENING_H #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_LOOPWIDENING_H +#include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Analysis/CFG.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" namespace clang { +class StackFrame; namespace ento { /// Get the states that result from widening the loop. /// /// Widen the loop by invalidating anything that might be modified /// by the loop body in any iteration. -ProgramStateRef getWidenedLoopState(ProgramStateRef PrevState, +/// statement of the widened loop (if available); when non-null it is +/// attached to the resulting invalidation symbols as a LoopWidening cause. +ProgramStateRef getWidenedLoopState(const Stmt *LoopStmt, + ProgramStateRef PrevState, const StackFrame *SF, unsigned BlockCount, ConstCFGElementRef Elem); diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index 3458fa9fe27a4..15cbcd10f5055 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -38,6 +38,7 @@ namespace ento { class AnalysisManager; class CallEvent; class CallEventManager; +class InvalidationCause; typedef std::unique_ptr<ConstraintManager>(*ConstraintManagerCreator)( ProgramStateManager &, ExprEngine *); @@ -327,18 +328,24 @@ class ProgramState : public llvm::FoldingSetNode { /// the call and should be considered directly invalidated. /// \param ITraits information about special handling for particular regions /// or symbols. + /// \param Cause if non-null, identifies the reason for the invalidation; + /// regions invalidated under such a cause receive a + /// SymbolInvalidationArtifact symbol carrying the cause instead of a + /// plain SymbolConjured. [[nodiscard]] ProgramStateRef invalidateRegions( ArrayRef<const MemRegion *> Regions, ConstCFGElementRef Elem, unsigned BlockCount, const StackFrame *SF, bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr, const CallEvent *Call = nullptr, - RegionAndSymbolInvalidationTraits *ITraits = nullptr) const; + RegionAndSymbolInvalidationTraits *ITraits = nullptr, + const InvalidationCause *Cause = nullptr) const; [[nodiscard]] ProgramStateRef invalidateRegions(ArrayRef<SVal> Values, ConstCFGElementRef Elem, unsigned BlockCount, const StackFrame *SF, bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr, const CallEvent *Call = nullptr, - RegionAndSymbolInvalidationTraits *ITraits = nullptr) const; + RegionAndSymbolInvalidationTraits *ITraits = nullptr, + const InvalidationCause *Cause = nullptr) const; /// enterStackFrame - Returns the state for entry to the given stack frame, /// preserving the current state. diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h index a92acfea8f702..927da06b20755 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -48,6 +48,7 @@ namespace ento { class CallEvent; class ConditionTruthVal; +class InvalidationCause; class ProgramStateManager; class StoreRef; class SValBuilder { @@ -207,6 +208,16 @@ class SValBuilder { unsigned visitCount, const void *symbolTag = nullptr); + /// Manufacture a value bound to a region during an invalidation event. The + /// resulting symbol is a SymbolInvalidationArtifact carrying \p Cause and, + /// when \p PreviousSym is non-null, the symbol that was bound to the region + /// before the invalidation. + DefinedOrUnknownSVal + conjureInvalidationArtifactVal(const void *symbolTag, ConstCFGElementRef elem, + const StackFrame *SF, QualType type, + unsigned count, const InvalidationCause *Cause, + SymbolRef PreviousSym = nullptr); + /// Conjure a symbol representing heap allocated memory region. DefinedSVal getConjuredHeapSymbolVal(ConstCFGElementRef elem, const StackFrame *SF, QualType type, diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h index cda21138fe5e3..657c8c0772124 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h @@ -43,6 +43,7 @@ class StackFrame; namespace ento { class CallEvent; +class InvalidationCause; class ProgramStateManager; class ScanReachableSymbols; class SymbolReaper; @@ -239,11 +240,16 @@ class StoreManager { /// invalidated. This should include any regions explicitly invalidated /// even if they do not currently have bindings. Pass \c NULL if this /// information will not be used. + /// \param[in] Cause If non-null, the reason for the invalidation. Conjured + /// replacement symbols become SymbolInvalidationArtifact carrying this + /// cause; if null, plain SymbolConjured values are produced (legacy + /// behavior). virtual StoreRef invalidateRegions( Store store, ArrayRef<SVal> Values, ConstCFGElementRef Elem, unsigned Count, const StackFrame *SF, const CallEvent *Call, InvalidatedSymbols &IS, RegionAndSymbolInvalidationTraits &ITraits, - InvalidatedRegions *TopLevelRegions, InvalidatedRegions *Invalidated) = 0; + InvalidatedRegions *TopLevelRegions, InvalidatedRegions *Invalidated, + const InvalidationCause *Cause = nullptr) = 0; /// enterStackFrame - Let the StoreManager to do something when execution /// engine is about to execute into a callee. diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h index a5d49200a50cb..2313138bf9ef0 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h @@ -19,6 +19,7 @@ #include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Basic/LLVM.h" #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntPtr.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/InvalidationCause.h" #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h" @@ -132,6 +133,84 @@ class SymbolConjured : public SymbolData { static constexpr bool classof(Kind K) { return K == ClassKind; } }; +/// A symbol representing a value bound to a memory region as a side effect of +/// an invalidation event (escape into an opaque function, loop widening, +/// unmodeled atomic, etc.). Behaves like SymbolConjured but additionally +/// carries an InvalidationCause describing why the invalidation happened, and +/// (when known) the symbol that was bound to the region just before the +/// invalidation. The previous symbol lets bug-report visitors reason about +/// constraints attached to a value before it was invalidated. +class SymbolInvalidationArtifact : public SymbolData { + ConstCFGElementRef Elem; + QualType T; + unsigned Count; + const StackFrame *SF; + const void *SymbolTag; + const InvalidationCause *Cause; + SymbolRef PreviousSym; + + friend class SymExprAllocator; + SymbolInvalidationArtifact(SymbolID sym, ConstCFGElementRef elem, + const StackFrame *SF, QualType t, unsigned count, + const void *symbolTag, + const InvalidationCause *cause, + SymbolRef previousSym) + : SymbolData(ClassKind, sym), Elem(elem), T(t), Count(count), SF(SF), + SymbolTag(symbolTag), Cause(cause), PreviousSym(previousSym) { + assert(SF); + assert(cause); + assert(isValidTypeForSymbol(t)); + } + +public: + ConstCFGElementRef getCFGElementRef() const { return Elem; } + + unsigned getCount() const { return Count; } + + /// May be null. + const void *getTag() const { return SymbolTag; } + + LLVM_ATTRIBUTE_RETURNS_NONNULL + const InvalidationCause *getCause() const { return Cause; } + + LLVM_ATTRIBUTE_RETURNS_NONNULL + const StackFrame *getStackFrame() const { return SF; } + + /// The symbol that was bound to the invalidated region immediately before + /// the invalidation event, or null if the region had no symbolic binding + /// (e.g. a concrete value, or no prior binding at all). + SymbolRef getPreviousSymbol() const { return PreviousSym; } + + QualType getType() const override; + + StringRef getKindStr() const override; + + void dumpToStream(raw_ostream &os) const override; + + static void Profile(llvm::FoldingSetNodeID &profile, ConstCFGElementRef Elem, + const StackFrame *SF, QualType T, unsigned Count, + const void *SymbolTag, const InvalidationCause *Cause, + SymbolRef PreviousSym) { + profile.AddInteger((unsigned)ClassKind); + profile.Add(Elem); + profile.AddPointer(SF); + profile.Add(T); + profile.AddInteger(Count); + profile.AddPointer(SymbolTag); + profile.AddPointer(Cause); + profile.AddPointer(PreviousSym); + } + + void Profile(llvm::FoldingSetNodeID &profile) override { + Profile(profile, Elem, SF, T, Count, SymbolTag, Cause, PreviousSym); + } + + // Implement isa<T> support. + static constexpr Kind ClassKind = SymbolInvalidationArtifactKind; + static bool classof(const SymExpr *SE) { return classof(SE->getKind()); } + static constexpr bool classof(Kind K) { return K == ClassKind; } +}; + /// A symbol representing the value of a MemRegion whose parent region has /// symbolic value. class SymbolDerived : public SymbolData { @@ -501,16 +580,20 @@ class SymExprAllocator { return new (Alloc) SymT(nextID(), std::forward<ArgsT>(Args)...); } + llvm::BumpPtrAllocator &getAllocator() { return Alloc; } + private: SymbolID nextID() { retur... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/207155 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
