[clang] [analyzer] Introduce the invalidation artifact symbol (PR #207155)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 2 03:55:27 PDT 2026
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
More information about the cfe-commits
mailing list