[analyzer][NFC] Merge the class LocationContext into StackFrame (#198211)

This commit implements the final parts of the roadmap described in issue
#190973 by merging the class `LocationContext` into the class
`StackFrame` and replacing `LocationContext` with `StackFrame`
throughout the analyzer.
This commit is contained in:
Gábor Tóthvári 2026-05-28 16:26:53 +00:00 committed by GitHub
parent ac2c011dd3
commit 35a10827d0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
122 changed files with 2327 additions and 2652 deletions

View file

@ -126,7 +126,7 @@ ExprEngine::inlineCall and ExprEngine::processCallExit.
If the conditions are right for inlining, a CallEnter node is created and added
to the analysis work list. The CallEnter node marks the change to a new
LocationContext representing the called function, and its state includes the
StackFrame representing the called function, and its state includes the
contents of the new stack frame. When the CallEnter node is actually processed,
its single successor will be an edge to the first CFG block in the function.
@ -145,7 +145,7 @@ reasonable steps:
bindings.
4. A CallExitEnd node is generated, which marks the transition back to the
caller's LocationContext.
caller's StackFrame.
5. Custom post-call checks are processed and the final nodes are pushed back
onto the work list, so that evaluation of the caller can continue.
@ -179,7 +179,7 @@ some cases, however, where the analyzer chooses not to inline:
cannot be computed. These are prerequisites for analyzing a function body,
with or without inlining.
- If the LocationContext chain for a given ExplodedNode reaches a maximum cutoff
- If the StackFrame chain for a given ExplodedNode reaches a maximum cutoff
depth. This prevents unbounded analysis due to infinite recursion, but also
serves as a useful cutoff for performance reasons.
@ -377,7 +377,7 @@ CallEvent
A CallEvent represents a specific call to a function, method, or other body of
code. It is path-sensitive, containing both the current state (ProgramStateRef)
and stack space (LocationContext), and provides uniform access to the argument
and stack space (StackFrame), and provides uniform access to the argument
values and return type of a call, no matter how the call is written in the
source or what sort of code body is being invoked.

View file

@ -38,8 +38,7 @@ class ASTContext;
class BlockDecl;
class CFGReverseBlockReachabilityAnalysis;
class ImplicitParamDecl;
class LocationContext;
class LocationContextManager;
class StackFrameManager;
class ParentMap;
class StackFrame;
class Stmt;
@ -176,11 +175,10 @@ public:
/// AnalysisDeclContext wraps an ObjCMethodDecl or nullptr otherwise.
const ImplicitParamDecl *getSelfDecl() const;
/// \copydoc LocationContextManager::getStackFrame()
const StackFrame *getStackFrame(LocationContext const *ParentLC,
const void *Data, const Expr *E,
const CFGBlock *Blk, unsigned BlockCount,
unsigned Index);
/// \copydoc StackFrameManager::getStackFrame()
const StackFrame *getStackFrame(const StackFrame *ParentSF, const void *Data,
const Expr *E, const CFGBlock *Blk,
unsigned BlockCount, unsigned Index);
/// \returns The specified analysis object, lazily running the analysis if
/// necessary or nullptr if the analysis could not run.
@ -200,96 +198,21 @@ public:
private:
std::unique_ptr<ManagedAnalysis> &getAnalysisImpl(const void *tag);
LocationContextManager &getLocationContextManager();
StackFrameManager &getStackFrameManager();
};
class LocationContext : public llvm::FoldingSetNode {
public:
enum ContextKind { StackFrameKind };
private:
ContextKind Kind;
/// It represents a stack frame of the call stack
class StackFrame final : public llvm::FoldingSetNode {
friend class StackFrameManager;
// AnalysisDeclContext can't be const since some methods may modify its
// member.
AnalysisDeclContext *Ctx;
const LocationContext *Parent;
const StackFrame *Parent;
int64_t ID;
protected:
LocationContext(ContextKind k, AnalysisDeclContext *ctx,
const LocationContext *parent, int64_t ID)
: Kind(k), Ctx(ctx), Parent(parent), ID(ID) {
assert(ctx);
}
public:
virtual ~LocationContext();
ContextKind getKind() const { return Kind; }
int64_t getID() const { return ID; }
LLVM_ATTRIBUTE_RETURNS_NONNULL
AnalysisDeclContext *getAnalysisDeclContext() const { return Ctx; }
/// It might return null.
const LocationContext *getParent() const { return Parent; }
bool isParentOf(const LocationContext *LC) const;
const Decl *getDecl() const { return Ctx->getDecl(); }
CFG *getCFG() const { return Ctx->getCFG(); }
template <typename T> T *getAnalysis() const { return Ctx->getAnalysis<T>(); }
const ParentMap &getParentMap() const { return Ctx->getParentMap(); }
/// \copydoc AnalysisDeclContext::getSelfDecl()
const ImplicitParamDecl *getSelfDecl() const { return Ctx->getSelfDecl(); }
const StackFrame *getStackFrame() const;
/// \returns Whether the current LocationContext has no caller context.
virtual bool inTopFrame() const;
virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
/// Prints out the call stack.
///
/// \param Out The out stream.
LLVM_DUMP_METHOD void dumpStack(raw_ostream &Out) const;
/// Prints out the call stack in \c json format.
///
/// \param Out The out stream.
/// \param NL The newline.
/// \param Space The space count for indentation.
/// \param IsDot Whether the output format is \c dot.
/// \param printMoreInfoPerContext
/// A callback to print more information for each context, for example:
/// \code
/// [&](const LocationContext *LC) { LC->dump(); }
/// \endcode
void printJson(
raw_ostream &Out, const char *NL = "\n", unsigned int Space = 0,
bool IsDot = false,
std::function<void(const LocationContext *)> printMoreInfoPerContext =
[](const LocationContext *) {}) const;
LLVM_DUMP_METHOD void dump() const;
static void ProfileCommon(llvm::FoldingSetNodeID &ID, ContextKind ck,
AnalysisDeclContext *ctx,
const LocationContext *parent, const void *data);
};
/// It represents a stack frame of the call stack (based on CallEvent).
class StackFrame : public LocationContext {
friend class LocationContextManager;
// Extra data for BlockInvocations
const void *Data;
@ -307,14 +230,37 @@ class StackFrame : public LocationContext {
// The index of the call site in the CFGBlock.
const unsigned Index;
StackFrame(AnalysisDeclContext *ADC, const LocationContext *ParentLC,
public:
StackFrame(AnalysisDeclContext *ADC, const StackFrame *Parent,
const void *Data, const Expr *E, const CFGBlock *Block,
unsigned BlockCount, unsigned Index, int64_t ID)
: LocationContext(StackFrameKind, ADC, ParentLC, ID), Data(Data),
CallSite(E), Block(Block), BlockCount(BlockCount), Index(Index) {}
: Ctx(ADC), Parent(Parent), ID(ID), Data(Data), CallSite(E), Block(Block),
BlockCount(BlockCount), Index(Index) {
assert(ADC);
}
public:
~StackFrame() override = default;
~StackFrame() = default;
LLVM_ATTRIBUTE_RETURNS_NONNULL
AnalysisDeclContext *getAnalysisDeclContext() const { return Ctx; }
/// It might return null.
const StackFrame *getParent() const { return Parent; }
int64_t getID() const { return ID; }
bool isParentOf(const StackFrame *SF) const;
const Decl *getDecl() const { return Ctx->getDecl(); }
CFG *getCFG() const { return Ctx->getCFG(); }
template <typename T> T *getAnalysis() const { return Ctx->getAnalysis<T>(); }
const ParentMap &getParentMap() const { return Ctx->getParentMap(); }
/// \copydoc AnalysisDeclContext::getSelfDecl()
const ImplicitParamDecl *getSelfDecl() const { return Ctx->getSelfDecl(); }
const void *getData() const { return Data; }
@ -322,43 +268,66 @@ public:
const CFGBlock *getCallSiteBlock() const { return Block; }
bool inTopFrame() const override { return getParent() == nullptr; }
/// \returns Whether the current StackFrame has no caller context.
bool inTopFrame() const { return getParent() == nullptr; }
unsigned getIndex() const { return Index; }
CFGElement getCallSiteCFGElement() const { return (*Block)[Index]; }
void Profile(llvm::FoldingSetNodeID &ID) override;
/// Prints out the call stack in \c json format.
///
/// \param Out The out stream.
/// \param NL The newline.
/// \param Space The space count for indentation.
/// \param IsDot Whether the output format is \c dot.
/// \param printMoreInfoPerStackFrame
/// A callback to print more information for each stack frame, for example:
/// \code
/// [&](const StackFrame *SF) { SF->dump(); }
/// \endcode
void printJson(
raw_ostream &Out, const char *NL = "\n", unsigned int Space = 0,
bool IsDot = false,
std::function<void(const StackFrame *)> printMoreInfoPerStackFrame =
[](const StackFrame *) {}) const;
/// Prints out the call stack.
///
/// \param Out The out stream.
LLVM_DUMP_METHOD void dumpStack(raw_ostream &Out) const;
LLVM_DUMP_METHOD void dump() const;
void Profile(llvm::FoldingSetNodeID &ID);
static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ADC,
const LocationContext *ParentLC, const void *Data,
const Expr *E, const CFGBlock *Block, unsigned BlockCount,
const StackFrame *SF, const void *Data, const Expr *E,
const CFGBlock *Block, unsigned BlockCount,
unsigned Index) {
ProfileCommon(ID, StackFrameKind, ADC, ParentLC, E);
ID.AddPointer(ADC);
ID.AddPointer(SF);
ID.AddPointer(E);
ID.AddPointer(Data);
ID.AddPointer(Block);
ID.AddInteger(BlockCount);
ID.AddInteger(Index);
}
static bool classof(const LocationContext *LC) {
return LC->getKind() == StackFrameKind;
}
};
class LocationContextManager {
llvm::FoldingSet<LocationContext> Contexts;
class StackFrameManager {
llvm::FoldingSet<StackFrame> Frames;
// ID used for generating a new location context.
// ID used for generating a new stack frame.
int64_t NewID = 0;
public:
~LocationContextManager();
~StackFrameManager();
/// Obtain a context of the call stack using its parent context.
///
/// \param ADC The AnalysisDeclContext.
/// \param ParentLC The parent context of this newly created
/// \param ParentSF The parent context of this newly created
/// context.
/// \param Data Extra data in case this StackFrame is
/// created for a BlockInvocation.
@ -369,12 +338,11 @@ public:
/// statements of the CFGBlock \p Block.
/// \returns The stack frame context corresponding to the call.
const StackFrame *getStackFrame(AnalysisDeclContext *ADC,
const LocationContext *ParentLC,
const void *Data, const Expr *E,
const CFGBlock *Block, unsigned BlockCount,
unsigned StmtIdx);
const StackFrame *ParentSF, const void *Data,
const Expr *E, const CFGBlock *Block,
unsigned BlockCount, unsigned StmtIdx);
/// Discard all previously created LocationContext objects.
/// Discard all previously created StackFrame objects.
void clear();
};
@ -383,7 +351,7 @@ class AnalysisDeclContextManager {
llvm::DenseMap<const Decl *, std::unique_ptr<AnalysisDeclContext>>;
ContextMap Contexts;
LocationContextManager LocCtxMgr;
StackFrameManager SFMgr;
CFG::BuildOptions cfgBuildOptions;
// Pointer to an interface that can provide function bodies for
@ -423,9 +391,9 @@ public:
/// Obtain the beginning context of the analysis.
///
/// \returns The top level stack frame for \p D.
const StackFrame *getStackFrame(const Decl *D) {
return LocCtxMgr.getStackFrame(getContext(D), nullptr, nullptr, nullptr,
nullptr, 0, 0);
const StackFrame *getTopStackFrame(const Decl *D) {
return SFMgr.getStackFrame(getContext(D), nullptr, nullptr, nullptr,
nullptr, 0, 0);
}
BodyFarm &getBodyFarm();
@ -436,7 +404,7 @@ public:
private:
friend class AnalysisDeclContext;
LocationContextManager &getLocationContextManager() { return LocCtxMgr; }
StackFrameManager &getStackFrameManager() { return SFMgr; }
};
} // namespace clang

View file

@ -43,7 +43,6 @@ class CallEnter;
class CallExitEnd;
class ConditionalOperator;
class Decl;
class LocationContext;
class MemberExpr;
class ProgramPoint;
class SourceManager;
@ -189,8 +188,8 @@ public:
PathDiagnosticRange() = default;
};
using LocationOrAnalysisDeclContext =
llvm::PointerUnion<const LocationContext *, AnalysisDeclContext *>;
using StackFrameOrAnalysisDeclContext =
llvm::PointerUnion<const StackFrame *, AnalysisDeclContext *>;
class PathDiagnosticLocation {
private:
@ -205,12 +204,12 @@ private:
PathDiagnosticLocation(SourceLocation L, const SourceManager &sm, Kind kind)
: K(kind), SM(&sm), Loc(genLocation(L)), Range(genRange()) {}
FullSourceLoc genLocation(
SourceLocation L = SourceLocation(),
LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext *)nullptr) const;
FullSourceLoc genLocation(SourceLocation L = SourceLocation(),
StackFrameOrAnalysisDeclContext SFAC =
(AnalysisDeclContext *)nullptr) const;
PathDiagnosticRange genRange(
LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext *)nullptr) const;
PathDiagnosticRange genRange(StackFrameOrAnalysisDeclContext SFAC =
(AnalysisDeclContext *)nullptr) const;
public:
/// Create an invalid location.
@ -218,10 +217,10 @@ public:
/// Create a location corresponding to the given statement.
PathDiagnosticLocation(const Stmt *s, const SourceManager &sm,
LocationOrAnalysisDeclContext lac)
StackFrameOrAnalysisDeclContext SFAC)
: K(s->getBeginLoc().isValid() ? StmtK : SingleLocK),
S(K == StmtK ? s : nullptr), SM(&sm),
Loc(genLocation(SourceLocation(), lac)), Range(genRange(lac)) {
Loc(genLocation(SourceLocation(), SFAC)), Range(genRange(SFAC)) {
assert(K == SingleLocK || S);
assert(K == SingleLocK || Loc.isValid());
assert(K == SingleLocK || Range.isValid());
@ -259,22 +258,22 @@ public:
/// of statements and declarations.
static PathDiagnosticLocation
createBegin(const Decl *D, const SourceManager &SM,
const LocationOrAnalysisDeclContext LAC) {
const StackFrameOrAnalysisDeclContext SFAC) {
return createBegin(D, SM);
}
/// Create a location for the beginning of the statement.
static PathDiagnosticLocation createBegin(const Stmt *S,
const SourceManager &SM,
const LocationOrAnalysisDeclContext LAC);
static PathDiagnosticLocation
createBegin(const Stmt *S, const SourceManager &SM,
const StackFrameOrAnalysisDeclContext SFAC);
/// Create a location for the end of the statement.
///
/// If the statement is a CompoundStatement, the location will point to the
/// closing brace instead of following it.
static PathDiagnosticLocation createEnd(const Stmt *S,
const SourceManager &SM,
const LocationOrAnalysisDeclContext LAC);
static PathDiagnosticLocation
createEnd(const Stmt *S, const SourceManager &SM,
const StackFrameOrAnalysisDeclContext SFAC);
/// Create the location for the operator of the binary expression.
/// Assumes the statement has a valid location.
@ -301,13 +300,13 @@ public:
/// Create a location for the beginning of the enclosing declaration body.
/// Defaults to the beginning of the first statement in the declaration body.
static PathDiagnosticLocation createDeclBegin(const LocationContext *LC,
static PathDiagnosticLocation createDeclBegin(const StackFrame *SF,
const SourceManager &SM);
/// Constructs a location for the end of the enclosing declaration body.
/// Defaults to the end of brace.
static PathDiagnosticLocation createDeclEnd(const LocationContext *LC,
const SourceManager &SM);
static PathDiagnosticLocation createDeclEnd(const StackFrame *SF,
const SourceManager &SM);
/// Create a location corresponding to the given valid ProgramPoint.
static PathDiagnosticLocation create(const ProgramPoint &P,
@ -321,7 +320,7 @@ public:
/// or the end of the given statement, or a nearby valid source location
/// if the statement does not have a valid source location of its own.
static SourceLocation
getValidSourceLocation(const Stmt *S, LocationOrAnalysisDeclContext LAC,
getValidSourceLocation(const Stmt *S, StackFrameOrAnalysisDeclContext SFAC,
bool UseEndOfStatement = false);
bool operator==(const PathDiagnosticLocation &X) const {

View file

@ -30,7 +30,6 @@
namespace clang {
class AnalysisDeclContext;
class LocationContext;
/// ProgramPoints can be "tagged" as representing points specific to a given
/// analysis entity. Tags are abstract annotations, with an associated
@ -95,9 +94,9 @@ private:
const void *Data1;
llvm::PointerIntPair<const void *, 2, unsigned> Data2;
// The LocationContext could be NULL to allow ProgramPoint to be used in
// The StackFrame could be NULL to allow ProgramPoint to be used in
// context insensitive analysis.
llvm::PointerIntPair<const LocationContext *, 2, unsigned> L;
llvm::PointerIntPair<const StackFrame *, 2, unsigned> S;
llvm::PointerIntPair<const ProgramPointTag *, 2, unsigned> Tag;
@ -105,22 +104,22 @@ private:
protected:
ProgramPoint() = default;
ProgramPoint(const void *P, Kind k, const LocationContext *l,
ProgramPoint(const void *P, Kind k, const StackFrame *SF,
const ProgramPointTag *tag = nullptr,
CFGBlock::ConstCFGElementRef ElemRef = {nullptr, 0})
: Data1(P), Data2(nullptr, (((unsigned)k) >> 0) & 0x3),
L(l, (((unsigned)k) >> 2) & 0x3), Tag(tag, (((unsigned)k) >> 4) & 0x3),
S(SF, (((unsigned)k) >> 2) & 0x3), Tag(tag, (((unsigned)k) >> 4) & 0x3),
ElemRef(ElemRef) {
assert(getKind() == k);
assert(getLocationContext() == l);
assert(getStackFrame() == SF);
assert(getData1() == P);
}
ProgramPoint(const void *P1, const void *P2, Kind k, const LocationContext *l,
ProgramPoint(const void *P1, const void *P2, Kind k, const StackFrame *SF,
const ProgramPointTag *tag = nullptr,
CFGBlock::ConstCFGElementRef ElemRef = {nullptr, 0})
: Data1(P1), Data2(P2, (((unsigned)k) >> 0) & 0x3),
L(l, (((unsigned)k) >> 2) & 0x3), Tag(tag, (((unsigned)k) >> 4) & 0x3),
S(SF, (((unsigned)k) >> 2) & 0x3), Tag(tag, (((unsigned)k) >> 4) & 0x3),
ElemRef(ElemRef) {}
protected:
@ -133,8 +132,8 @@ public:
/// Create a new ProgramPoint object that is the same as the original
/// except for using the specified tag value.
ProgramPoint withTag(const ProgramPointTag *tag) const {
return ProgramPoint(getData1(), getData2(), getKind(),
getLocationContext(), tag);
return ProgramPoint(getData1(), getData2(), getKind(), getStackFrame(),
tag);
}
/// Convert to the specified ProgramPoint type, asserting that this
@ -162,7 +161,7 @@ public:
Kind getKind() const {
unsigned x = Tag.getInt();
x <<= 2;
x |= L.getInt();
x |= S.getInt();
x <<= 2;
x |= Data2.getInt();
return (Kind) x;
@ -178,13 +177,7 @@ public:
const ProgramPointTag *getTag() const { return Tag.getPointer(); }
const LocationContext *getLocationContext() const {
return L.getPointer();
}
const StackFrame *getStackFrame() const {
return getLocationContext()->getStackFrame();
}
const StackFrame *getStackFrame() const { return S.getPointer(); }
// For use with DenseMap. This hash is probably slow.
unsigned getHashValue() const {
@ -194,12 +187,12 @@ public:
}
bool operator==(const ProgramPoint & RHS) const {
return Data1 == RHS.Data1 && Data2 == RHS.Data2 && L == RHS.L &&
return Data1 == RHS.Data1 && Data2 == RHS.Data2 && S == RHS.S &&
Tag == RHS.Tag && ElemRef == RHS.ElemRef;
}
bool operator!=(const ProgramPoint &RHS) const {
return Data1 != RHS.Data1 || Data2 != RHS.Data2 || L != RHS.L ||
return Data1 != RHS.Data1 || Data2 != RHS.Data2 || S != RHS.S ||
Tag != RHS.Tag || ElemRef != RHS.ElemRef;
}
@ -207,7 +200,7 @@ public:
ID.AddInteger((unsigned) getKind());
ID.AddPointer(getData1());
ID.AddPointer(getData2());
ID.AddPointer(getLocationContext());
ID.AddPointer(getStackFrame());
ID.AddPointer(getTag());
ID.AddPointer(ElemRef.getParent());
ID.AddInteger(ElemRef.getIndexInBlock());
@ -218,15 +211,15 @@ public:
LLVM_DUMP_METHOD void dump() const;
static ProgramPoint getProgramPoint(const Stmt *S, ProgramPoint::Kind K,
const LocationContext *LC,
const StackFrame *SF,
const ProgramPointTag *tag);
};
class BlockEntrance : public ProgramPoint {
public:
BlockEntrance(const CFGBlock *PrevBlock, const CFGBlock *CurrBlock,
const LocationContext *L, const ProgramPointTag *Tag = nullptr)
: ProgramPoint(CurrBlock, PrevBlock, BlockEntranceKind, L, Tag) {
const StackFrame *SF, const ProgramPointTag *Tag = nullptr)
: ProgramPoint(CurrBlock, PrevBlock, BlockEntranceKind, SF, Tag) {
assert(CurrBlock && "BlockEntrance requires non-null block");
}
@ -253,8 +246,8 @@ private:
class BlockExit : public ProgramPoint {
public:
BlockExit(const CFGBlock *B, const LocationContext *L)
: ProgramPoint(B, BlockExitKind, L) {}
BlockExit(const CFGBlock *B, const StackFrame *SF)
: ProgramPoint(B, BlockExitKind, SF) {}
const CFGBlock *getBlock() const {
return reinterpret_cast<const CFGBlock*>(getData1());
@ -275,9 +268,9 @@ private:
// FIXME: Eventually we want to take a CFGElementRef as parameter here too.
class StmtPoint : public ProgramPoint {
public:
StmtPoint(const Stmt *S, const void *p2, Kind k, const LocationContext *L,
StmtPoint(const Stmt *S, const void *p2, Kind k, const StackFrame *SF,
const ProgramPointTag *tag)
: ProgramPoint(S, p2, k, L, tag) {
: ProgramPoint(S, p2, k, SF, tag) {
assert(S);
}
@ -299,9 +292,9 @@ private:
class PreStmt : public StmtPoint {
public:
PreStmt(const Stmt *S, const LocationContext *L, const ProgramPointTag *tag,
PreStmt(const Stmt *S, const StackFrame *SF, const ProgramPointTag *tag,
const Stmt *SubStmt = nullptr)
: StmtPoint(S, SubStmt, PreStmtKind, L, tag) {}
: StmtPoint(S, SubStmt, PreStmtKind, SF, tag) {}
const Stmt *getSubStmt() const { return (const Stmt*) getData2(); }
@ -316,18 +309,18 @@ private:
class PostStmt : public StmtPoint {
protected:
PostStmt() = default;
PostStmt(const Stmt *S, const void *data, Kind k, const LocationContext *L,
PostStmt(const Stmt *S, const void *data, Kind k, const StackFrame *SF,
const ProgramPointTag *tag = nullptr)
: StmtPoint(S, data, k, L, tag) {}
: StmtPoint(S, data, k, SF, tag) {}
public:
explicit PostStmt(const Stmt *S, Kind k, const LocationContext *L,
explicit PostStmt(const Stmt *S, Kind k, const StackFrame *SF,
const ProgramPointTag *tag = nullptr)
: StmtPoint(S, nullptr, k, L, tag) {}
: StmtPoint(S, nullptr, k, SF, tag) {}
explicit PostStmt(const Stmt *S, const LocationContext *L,
explicit PostStmt(const Stmt *S, const StackFrame *SF,
const ProgramPointTag *tag = nullptr)
: StmtPoint(S, nullptr, PostStmtKind, L, tag) {}
: StmtPoint(S, nullptr, PostStmtKind, SF, tag) {}
private:
friend class ProgramPoint;
@ -339,13 +332,12 @@ private:
class FunctionExitPoint : public ProgramPoint {
public:
explicit FunctionExitPoint(const ReturnStmt *S,
const LocationContext *LC,
explicit FunctionExitPoint(const ReturnStmt *S, const StackFrame *SF,
const ProgramPointTag *tag = nullptr)
: ProgramPoint(S, FunctionExitKind, LC, tag) {}
: ProgramPoint(S, FunctionExitKind, SF, tag) {}
const CFGBlock *getBlock() const {
return &getLocationContext()->getCFG()->getExit();
return &getStackFrame()->getCFG()->getExit();
}
const ReturnStmt *getStmt() const {
@ -363,9 +355,9 @@ private:
// PostCondition represents the post program point of a branch condition.
class PostCondition : public PostStmt {
public:
PostCondition(const Stmt *S, const LocationContext *L,
PostCondition(const Stmt *S, const StackFrame *SF,
const ProgramPointTag *tag = nullptr)
: PostStmt(S, PostConditionKind, L, tag) {}
: PostStmt(S, PostConditionKind, SF, tag) {}
private:
friend class ProgramPoint;
@ -378,9 +370,9 @@ private:
class LocationCheck : public StmtPoint {
protected:
LocationCheck() = default;
LocationCheck(const Stmt *S, const LocationContext *L,
ProgramPoint::Kind K, const ProgramPointTag *tag)
: StmtPoint(S, nullptr, K, L, tag) {}
LocationCheck(const Stmt *S, const StackFrame *SF, ProgramPoint::Kind K,
const ProgramPointTag *tag)
: StmtPoint(S, nullptr, K, SF, tag) {}
private:
friend class ProgramPoint;
@ -392,9 +384,9 @@ private:
class PreLoad : public LocationCheck {
public:
PreLoad(const Stmt *S, const LocationContext *L,
PreLoad(const Stmt *S, const StackFrame *SF,
const ProgramPointTag *tag = nullptr)
: LocationCheck(S, L, PreLoadKind, tag) {}
: LocationCheck(S, SF, PreLoadKind, tag) {}
private:
friend class ProgramPoint;
@ -406,9 +398,9 @@ private:
class PreStore : public LocationCheck {
public:
PreStore(const Stmt *S, const LocationContext *L,
PreStore(const Stmt *S, const StackFrame *SF,
const ProgramPointTag *tag = nullptr)
: LocationCheck(S, L, PreStoreKind, tag) {}
: LocationCheck(S, SF, PreStoreKind, tag) {}
private:
friend class ProgramPoint;
@ -420,9 +412,9 @@ private:
class PostLoad : public PostStmt {
public:
PostLoad(const Stmt *S, const LocationContext *L,
PostLoad(const Stmt *S, const StackFrame *SF,
const ProgramPointTag *tag = nullptr)
: PostStmt(S, PostLoadKind, L, tag) {}
: PostStmt(S, PostLoadKind, SF, tag) {}
private:
friend class ProgramPoint;
@ -438,9 +430,9 @@ public:
/// Construct the post store point.
/// \param Loc can be used to store the information about the location
/// used in the form it was uttered in the code.
PostStore(const Stmt *S, const LocationContext *L, const void *Loc,
PostStore(const Stmt *S, const StackFrame *SF, const void *Loc,
const ProgramPointTag *tag = nullptr)
: PostStmt(S, PostStoreKind, L, tag) {
: PostStmt(S, PostStoreKind, SF, tag) {
assert(getData2() == nullptr);
setData2(Loc);
}
@ -461,9 +453,9 @@ private:
class PostLValue : public PostStmt {
public:
PostLValue(const Stmt *S, const LocationContext *L,
PostLValue(const Stmt *S, const StackFrame *SF,
const ProgramPointTag *tag = nullptr)
: PostStmt(S, PostLValueKind, L, tag) {}
: PostStmt(S, PostLValueKind, SF, tag) {}
private:
friend class ProgramPoint;
@ -477,9 +469,9 @@ private:
/// processing the given statement.
class PreStmtPurgeDeadSymbols : public StmtPoint {
public:
PreStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
const ProgramPointTag *tag = nullptr)
: StmtPoint(S, nullptr, PreStmtPurgeDeadSymbolsKind, L, tag) { }
PreStmtPurgeDeadSymbols(const Stmt *S, const StackFrame *SF,
const ProgramPointTag *tag = nullptr)
: StmtPoint(S, nullptr, PreStmtPurgeDeadSymbolsKind, SF, tag) {}
private:
friend class ProgramPoint;
@ -493,9 +485,9 @@ private:
/// processing the given statement.
class PostStmtPurgeDeadSymbols : public StmtPoint {
public:
PostStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
const ProgramPointTag *tag = nullptr)
: StmtPoint(S, nullptr, PostStmtPurgeDeadSymbolsKind, L, tag) { }
PostStmtPurgeDeadSymbols(const Stmt *S, const StackFrame *SF,
const ProgramPointTag *tag = nullptr)
: StmtPoint(S, nullptr, PostStmtPurgeDeadSymbolsKind, SF, tag) {}
private:
friend class ProgramPoint;
@ -507,8 +499,8 @@ private:
class BlockEdge : public ProgramPoint {
public:
BlockEdge(const CFGBlock *B1, const CFGBlock *B2, const LocationContext *L)
: ProgramPoint(B1, B2, BlockEdgeKind, L) {
BlockEdge(const CFGBlock *B1, const CFGBlock *B2, const StackFrame *SF)
: ProgramPoint(B1, B2, BlockEdgeKind, SF) {
assert(B1 && "BlockEdge: source block must be non-null");
assert(B2 && "BlockEdge: destination block must be non-null");
}
@ -536,10 +528,9 @@ public:
///
/// \param I The initializer.
/// \param Loc The location of the field being initialized.
PostInitializer(const CXXCtorInitializer *I,
const void *Loc,
const LocationContext *L)
: ProgramPoint(I, Loc, PostInitializerKind, L) {}
PostInitializer(const CXXCtorInitializer *I, const void *Loc,
const StackFrame *SF)
: ProgramPoint(I, Loc, PostInitializerKind, SF) {}
const CXXCtorInitializer *getInitializer() const {
return static_cast<const CXXCtorInitializer *>(getData1());
@ -564,9 +555,9 @@ private:
class ImplicitCallPoint : public ProgramPoint {
public:
ImplicitCallPoint(const Decl *D, SourceLocation Loc, Kind K,
const LocationContext *L, const ProgramPointTag *Tag,
const StackFrame *SF, const ProgramPointTag *Tag,
CFGBlock::ConstCFGElementRef ElemRef)
: ProgramPoint(Loc.getPtrEncoding(), D, K, L, Tag, ElemRef) {}
: ProgramPoint(Loc.getPtrEncoding(), D, K, SF, Tag, ElemRef) {}
const Decl *getDecl() const { return static_cast<const Decl *>(getData2()); }
SourceLocation getLocation() const {
@ -588,10 +579,10 @@ private:
/// Explicit calls will appear as PreStmt program points.
class PreImplicitCall : public ImplicitCallPoint {
public:
PreImplicitCall(const Decl *D, SourceLocation Loc, const LocationContext *L,
PreImplicitCall(const Decl *D, SourceLocation Loc, const StackFrame *SF,
CFGBlock::ConstCFGElementRef ElemRef,
const ProgramPointTag *Tag = nullptr)
: ImplicitCallPoint(D, Loc, PreImplicitCallKind, L, Tag, ElemRef) {}
: ImplicitCallPoint(D, Loc, PreImplicitCallKind, SF, Tag, ElemRef) {}
private:
friend class ProgramPoint;
@ -606,10 +597,10 @@ private:
/// Explicit calls will appear as PostStmt program points.
class PostImplicitCall : public ImplicitCallPoint {
public:
PostImplicitCall(const Decl *D, SourceLocation Loc, const LocationContext *L,
PostImplicitCall(const Decl *D, SourceLocation Loc, const StackFrame *SF,
CFGBlock::ConstCFGElementRef ElemRef,
const ProgramPointTag *Tag = nullptr)
: ImplicitCallPoint(D, Loc, PostImplicitCallKind, L, Tag, ElemRef) {}
: ImplicitCallPoint(D, Loc, PostImplicitCallKind, SF, Tag, ElemRef) {}
private:
friend class ProgramPoint;
@ -621,9 +612,9 @@ private:
class PostAllocatorCall : public StmtPoint {
public:
PostAllocatorCall(const Stmt *S, const LocationContext *L,
PostAllocatorCall(const Stmt *S, const StackFrame *SF,
const ProgramPointTag *Tag = nullptr)
: StmtPoint(S, nullptr, PostAllocatorCallKind, L, Tag) {}
: StmtPoint(S, nullptr, PostAllocatorCallKind, SF, Tag) {}
private:
friend class ProgramPoint;
@ -634,24 +625,24 @@ private:
};
/// Represents a point when we begin processing an inlined call.
/// CallEnter uses the caller's location context.
/// CallEnter uses the caller's stack frame.
class CallEnter : public ProgramPoint {
public:
CallEnter(const Stmt *stmt, const StackFrame *CalleeSF,
const LocationContext *callerCtx)
: ProgramPoint(stmt, CalleeSF, CallEnterKind, callerCtx, nullptr) {}
const StackFrame *CallerSF)
: ProgramPoint(stmt, CalleeSF, CallEnterKind, CallerSF, nullptr) {}
const Stmt *getCallExpr() const {
return static_cast<const Stmt *>(getData1());
}
const StackFrame *getCalleeContext() const {
const StackFrame *getCalleeStackFrame() const {
return static_cast<const StackFrame *>(getData2());
}
/// Returns the entry block in the CFG for the entered function.
const CFGBlock *getEntry() const {
const StackFrame *CalleeSF = getCalleeContext();
const StackFrame *CalleeSF = getCalleeStackFrame();
const CFG *CalleeCFG = CalleeSF->getCFG();
return &(CalleeCFG->getEntry());
}
@ -675,7 +666,7 @@ private:
/// - CallExitEnd
class CallExitBegin : public ProgramPoint {
public:
// CallExitBegin uses the callee's location context.
// CallExitBegin uses the callee's stack frame.
CallExitBegin(const StackFrame *SF, const ReturnStmt *RS)
: ProgramPoint(RS, CallExitBeginKind, SF, nullptr) {}
@ -695,11 +686,11 @@ private:
/// \sa CallExitBegin
class CallExitEnd : public ProgramPoint {
public:
// CallExitEnd uses the caller's location context.
CallExitEnd(const StackFrame *CalleeSF, const LocationContext *CallerCtx)
: ProgramPoint(CalleeSF, CallExitEndKind, CallerCtx, nullptr) {}
// CallExitEnd uses the caller's stack frame.
CallExitEnd(const StackFrame *CalleeSF, const StackFrame *CallerSF)
: ProgramPoint(CalleeSF, CallExitEndKind, CallerSF, nullptr) {}
const StackFrame *getCalleeContext() const {
const StackFrame *getCalleeStackFrame() const {
return static_cast<const StackFrame *>(getData1());
}
@ -719,12 +710,12 @@ private:
/// result in a LoopExit program point.
class LoopExit : public ProgramPoint {
public:
LoopExit(const Stmt *LoopStmt, const LocationContext *LC)
: ProgramPoint(LoopStmt, nullptr, LoopExitKind, LC) {}
LoopExit(const Stmt *LoopStmt, const StackFrame *SF)
: ProgramPoint(LoopStmt, nullptr, LoopExitKind, SF) {}
const Stmt *getLoopStmt() const {
return static_cast<const Stmt *>(getData1());
}
const Stmt *getLoopStmt() const {
return static_cast<const Stmt *>(getData1());
}
private:
friend class ProgramPoint;
@ -738,10 +729,10 @@ private:
/// reasoning etc.
class EpsilonPoint : public ProgramPoint {
public:
EpsilonPoint(const LocationContext *L, const void *Data1,
EpsilonPoint(const StackFrame *SF, const void *Data1,
const void *Data2 = nullptr,
const ProgramPointTag *tag = nullptr)
: ProgramPoint(Data1, Data2, EpsilonKind, L, tag) {}
: ProgramPoint(Data1, Data2, EpsilonKind, SF, tag) {}
const void *getData() const { return getData1(); }

View file

@ -29,7 +29,7 @@ static constexpr TaintTagType TaintTagGeneric = 0;
/// Create a new state in which the value of the expression is marked as
/// tainted.
[[nodiscard]] ProgramStateRef addTaint(ProgramStateRef State, const Expr *E,
const LocationContext *LCtx,
const StackFrame *SF,
TaintTagType Kind = TaintTagGeneric);
/// Create a new state in which the value is marked as tainted.
@ -63,8 +63,7 @@ addPartialTaint(ProgramStateRef State, SymbolRef ParentSym,
TaintTagType Kind = TaintTagGeneric);
/// Check if the expression has a tainted value in the given state.
bool isTainted(ProgramStateRef State, const Expr *E,
const LocationContext *LCtx,
bool isTainted(ProgramStateRef State, const Expr *E, const StackFrame *SF,
TaintTagType Kind = TaintTagGeneric);
/// Check if the value is tainted in the given state.
@ -82,7 +81,7 @@ bool isTainted(ProgramStateRef State, const MemRegion *Reg,
/// Returns the tainted Symbols for a given expression and state.
std::vector<SymbolRef> getTaintedSymbols(ProgramStateRef State, const Expr *E,
const LocationContext *LCtx,
const StackFrame *SF,
TaintTagType Kind = TaintTagGeneric);
/// Returns the tainted Symbols for a given SVal and state.
@ -101,7 +100,7 @@ std::vector<SymbolRef> getTaintedSymbols(ProgramStateRef State,
std::vector<SymbolRef> getTaintedSymbolsImpl(ProgramStateRef State,
const Expr *E,
const LocationContext *LCtx,
const StackFrame *SF,
TaintTagType Kind,
bool returnFirstOnly);

View file

@ -48,7 +48,6 @@ namespace clang {
class AnalyzerOptions;
class ASTContext;
class Decl;
class LocationContext;
class SourceManager;
class Stmt;
@ -322,9 +321,9 @@ protected:
llvm::DenseMap<const MemRegion *, bugreporter::TrackingKind>
InterestingRegions;
/// A set of location contexts that correspoind to call sites which should be
/// A set of stack frames that correspond to call sites which should be
/// considered "interesting".
llvm::SmallPtrSet<const LocationContext *, 2> InterestingLocationContexts;
llvm::SmallPtrSet<const StackFrame *, 2> InterestingStackFrames;
/// A set of custom visitors which generate "event" diagnostics at
/// interesting points in the path.
@ -450,12 +449,12 @@ public:
/// condition, will append "will be used as a condition" to the message).
void markInteresting(SVal V, bugreporter::TrackingKind TKind =
bugreporter::TrackingKind::Thorough);
void markInteresting(const LocationContext *LC);
void markInteresting(const StackFrame *SF);
bool isInteresting(SymbolRef sym) const;
bool isInteresting(const MemRegion *R) const;
bool isInteresting(SVal V) const;
bool isInteresting(const LocationContext *LC) const;
bool isInteresting(const StackFrame *SF) const;
std::optional<bugreporter::TrackingKind>
getInterestingnessKind(SymbolRef sym) const;

View file

@ -346,16 +346,13 @@ public:
class RegionChanges {
template <typename CHECKER>
static ProgramStateRef
_checkRegionChanges(void *checker,
ProgramStateRef state,
_checkRegionChanges(void *checker, ProgramStateRef state,
const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> Explicits,
ArrayRef<const MemRegion *> Regions,
const LocationContext *LCtx,
ArrayRef<const MemRegion *> Regions, const StackFrame *SF,
const CallEvent *Call) {
return ((const CHECKER *) checker)->checkRegionChanges(state, invalidated,
Explicits, Regions,
LCtx, Call);
return ((const CHECKER *)checker)
->checkRegionChanges(state, invalidated, Explicits, Regions, SF, Call);
}
public:

View file

@ -29,7 +29,6 @@ namespace clang {
class AnalyzerOptions;
class CallExpr;
class Decl;
class LocationContext;
class Stmt;
class TranslationUnitDecl;
@ -411,8 +410,7 @@ public:
const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const LocationContext *LCtx,
const CallEvent *Call);
const StackFrame *SF, const CallEvent *Call);
/// Run checkers when pointers escape.
///
@ -523,13 +521,11 @@ public:
using CheckLiveSymbolsFunc = CheckerFn<void (ProgramStateRef,SymbolReaper &)>;
using CheckRegionChangesFunc =
CheckerFn<ProgramStateRef (ProgramStateRef,
const InvalidatedSymbols *symbols,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const LocationContext *LCtx,
const CallEvent *Call)>;
using CheckRegionChangesFunc = CheckerFn<ProgramStateRef(
ProgramStateRef, const InvalidatedSymbols *symbols,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions, const StackFrame *SF,
const CallEvent *Call)>;
using CheckPointerEscapeFunc =
CheckerFn<ProgramStateRef (ProgramStateRef,

View file

@ -50,7 +50,6 @@
namespace clang {
class LocationContext;
class ProgramPoint;
class ProgramPointTag;
class StackFrame;
@ -156,7 +155,7 @@ public:
private:
ProgramStateRef State;
const LocationContext *LCtx;
const StackFrame *SF;
llvm::PointerUnion<const Expr *, const Decl *> Origin;
CFGBlock::ConstCFGElementRef ElemRef = {nullptr, 0};
mutable std::optional<bool> Foreign; // Set by CTU analysis.
@ -181,17 +180,17 @@ private:
protected:
friend class CallEventManager;
CallEvent(const Expr *E, ProgramStateRef state, const LocationContext *lctx,
CallEvent(const Expr *E, ProgramStateRef state, const StackFrame *SF,
CFGBlock::ConstCFGElementRef ElemRef)
: State(std::move(state)), LCtx(lctx), Origin(E), ElemRef(ElemRef) {}
: State(std::move(state)), SF(SF), Origin(E), ElemRef(ElemRef) {}
CallEvent(const Decl *D, ProgramStateRef state, const LocationContext *lctx,
CallEvent(const Decl *D, ProgramStateRef state, const StackFrame *SF,
CFGBlock::ConstCFGElementRef ElemRef)
: State(std::move(state)), LCtx(lctx), Origin(D), ElemRef(ElemRef) {}
: State(std::move(state)), SF(SF), Origin(D), ElemRef(ElemRef) {}
// DO NOT MAKE PUBLIC
CallEvent(const CallEvent &Original)
: State(Original.State), LCtx(Original.LCtx), Origin(Original.Origin),
: State(Original.State), SF(Original.SF), Origin(Original.Origin),
ElemRef(Original.ElemRef), Data(Original.Data),
Location(Original.Location) {}
@ -200,7 +199,7 @@ protected:
/// Get the value of arbitrary expressions at this point in the path.
SVal getSVal(const Expr *E) const {
return getState()->getSVal(E, getLocationContext());
return getState()->getSVal(E, getStackFrame());
}
using ValueList = SmallVectorImpl<SVal>;
@ -247,8 +246,8 @@ public:
return getState()->getStateManager().getContext();
}
/// The context in which the call is being evaluated.
const LocationContext *getLocationContext() const { return LCtx; }
/// The stack frame in which the call is being evaluated.
const StackFrame *getStackFrame() const { return SF; }
const CFGBlock::ConstCFGElementRef &getCFGElementRef() const {
return ElemRef;
@ -433,7 +432,7 @@ public:
bool isArgumentConstructedDirectly(unsigned Index) const {
// This assumes that the object was not yet removed from the state.
return ExprEngine::getObjectUnderConstruction(
getState(), {getOriginExpr(), Index}, getLocationContext())
getState(), {getOriginExpr(), Index}, getStackFrame())
.has_value();
}
@ -509,14 +508,12 @@ public:
/// FunctionDecl.
class AnyFunctionCall : public CallEvent {
protected:
AnyFunctionCall(const Expr *E, ProgramStateRef St,
const LocationContext *LCtx,
AnyFunctionCall(const Expr *E, ProgramStateRef St, const StackFrame *SF,
CFGBlock::ConstCFGElementRef ElemRef)
: CallEvent(E, St, LCtx, ElemRef) {}
AnyFunctionCall(const Decl *D, ProgramStateRef St,
const LocationContext *LCtx,
: CallEvent(E, St, SF, ElemRef) {}
AnyFunctionCall(const Decl *D, ProgramStateRef St, const StackFrame *SF,
CFGBlock::ConstCFGElementRef ElemRef)
: CallEvent(D, St, LCtx, ElemRef) {}
: CallEvent(D, St, SF, ElemRef) {}
AnyFunctionCall(const AnyFunctionCall &Other) = default;
public:
@ -549,9 +546,8 @@ class SimpleFunctionCall : public AnyFunctionCall {
protected:
SimpleFunctionCall(const CallExpr *CE, ProgramStateRef St,
const LocationContext *LCtx,
CFGBlock::ConstCFGElementRef ElemRef)
: AnyFunctionCall(CE, St, LCtx, ElemRef) {}
const StackFrame *SF, CFGBlock::ConstCFGElementRef ElemRef)
: AnyFunctionCall(CE, St, SF, ElemRef) {}
SimpleFunctionCall(const SimpleFunctionCall &Other) = default;
void cloneTo(void *Dest) const override {
@ -588,9 +584,9 @@ class BlockCall : public CallEvent {
friend class CallEventManager;
protected:
BlockCall(const CallExpr *CE, ProgramStateRef St, const LocationContext *LCtx,
BlockCall(const CallExpr *CE, ProgramStateRef St, const StackFrame *SF,
CFGBlock::ConstCFGElementRef ElemRef)
: CallEvent(CE, St, LCtx, ElemRef) {}
: CallEvent(CE, St, SF, ElemRef) {}
BlockCall(const BlockCall &Other) = default;
void cloneTo(void *Dest) const override { new (Dest) BlockCall(*this); }
@ -689,14 +685,12 @@ public:
/// it is written.
class CXXInstanceCall : public AnyFunctionCall {
protected:
CXXInstanceCall(const CallExpr *CE, ProgramStateRef St,
const LocationContext *LCtx,
CXXInstanceCall(const CallExpr *CE, ProgramStateRef St, const StackFrame *SF,
CFGBlock::ConstCFGElementRef ElemRef)
: AnyFunctionCall(CE, St, LCtx, ElemRef) {}
: AnyFunctionCall(CE, St, SF, ElemRef) {}
CXXInstanceCall(const FunctionDecl *D, ProgramStateRef St,
const LocationContext *LCtx,
CFGBlock::ConstCFGElementRef ElemRef)
: AnyFunctionCall(D, St, LCtx, ElemRef) {}
const StackFrame *SF, CFGBlock::ConstCFGElementRef ElemRef)
: AnyFunctionCall(D, St, SF, ElemRef) {}
CXXInstanceCall(const CXXInstanceCall &Other) = default;
void getExtraInvalidatedValues(
@ -749,9 +743,9 @@ class CXXStaticOperatorCall : public SimpleFunctionCall {
protected:
CXXStaticOperatorCall(const CXXOperatorCallExpr *CE, ProgramStateRef St,
const LocationContext *LCtx,
const StackFrame *SF,
CFGBlock::ConstCFGElementRef ElemRef)
: SimpleFunctionCall(CE, St, LCtx, ElemRef) {}
: SimpleFunctionCall(CE, St, SF, ElemRef) {}
CXXStaticOperatorCall(const CXXStaticOperatorCall &Other) = default;
void cloneTo(void *Dest) const override {
@ -807,9 +801,8 @@ class CXXMemberCall : public CXXInstanceCall {
protected:
CXXMemberCall(const CXXMemberCallExpr *CE, ProgramStateRef St,
const LocationContext *LCtx,
CFGBlock::ConstCFGElementRef ElemRef)
: CXXInstanceCall(CE, St, LCtx, ElemRef) {}
const StackFrame *SF, CFGBlock::ConstCFGElementRef ElemRef)
: CXXInstanceCall(CE, St, SF, ElemRef) {}
CXXMemberCall(const CXXMemberCall &Other) = default;
void cloneTo(void *Dest) const override { new (Dest) CXXMemberCall(*this); }
@ -850,9 +843,9 @@ class CXXMemberOperatorCall : public CXXInstanceCall {
protected:
CXXMemberOperatorCall(const CXXOperatorCallExpr *CE, ProgramStateRef St,
const LocationContext *LCtx,
const StackFrame *SF,
CFGBlock::ConstCFGElementRef ElemRef)
: CXXInstanceCall(CE, St, LCtx, ElemRef) {}
: CXXInstanceCall(CE, St, SF, ElemRef) {}
CXXMemberOperatorCall(const CXXMemberOperatorCall &Other) = default;
void cloneTo(void *Dest) const override {
@ -917,7 +910,7 @@ protected:
/// \param Trigger The statement whose completion causes this destructor call.
/// \param Target The object region to be destructed.
/// \param St The path-sensitive state at this point in the program.
/// \param LCtx The location context at this point in the program.
/// \param SF The stack frame at this point in the program.
/// \param ElemRef The reference to this destructor in the CFG.
///
/// FIXME: Eventually we want to drop \param Target and deduce it from
@ -926,9 +919,9 @@ protected:
/// independent from ExprEngine.
CXXDestructorCall(const CXXDestructorDecl *DD, const Stmt *Trigger,
const MemRegion *Target, bool IsBaseDestructor,
ProgramStateRef St, const LocationContext *LCtx,
ProgramStateRef St, const StackFrame *SF,
CFGBlock::ConstCFGElementRef ElemRef)
: CXXInstanceCall(DD, St, LCtx, ElemRef) {
: CXXInstanceCall(DD, St, SF, ElemRef) {
Data = DtorDataTy(Target, IsBaseDestructor).getOpaqueValue();
Location = Trigger->getEndLoc();
}
@ -966,9 +959,9 @@ public:
class AnyCXXConstructorCall : public AnyFunctionCall {
protected:
AnyCXXConstructorCall(const Expr *E, const MemRegion *Target,
ProgramStateRef St, const LocationContext *LCtx,
ProgramStateRef St, const StackFrame *SF,
CFGBlock::ConstCFGElementRef ElemRef)
: AnyFunctionCall(E, St, LCtx, ElemRef) {
: AnyFunctionCall(E, St, SF, ElemRef) {
assert(E && (isa<CXXConstructExpr>(E) || isa<CXXInheritedCtorInitExpr>(E)));
// Target may be null when the region is unknown.
Data = Target;
@ -1004,15 +997,15 @@ protected:
/// \param Target The region where the object should be constructed. If NULL,
/// a new symbolic region will be used.
/// \param St The path-sensitive state at this point in the program.
/// \param LCtx The location context at this point in the program.
/// \param SF The stack frame at this point in the program.
/// \param ElemRef The reference to this constructor in the CFG.
///
/// FIXME: Eventually we want to drop \param Target and deduce it from
/// \param ElemRef.
CXXConstructorCall(const CXXConstructExpr *CE, const MemRegion *Target,
ProgramStateRef St, const LocationContext *LCtx,
ProgramStateRef St, const StackFrame *SF,
CFGBlock::ConstCFGElementRef ElemRef)
: AnyCXXConstructorCall(CE, Target, St, LCtx, ElemRef) {}
: AnyCXXConstructorCall(CE, Target, St, SF, ElemRef) {}
CXXConstructorCall(const CXXConstructorCall &Other) = default;
@ -1069,9 +1062,9 @@ class CXXInheritedConstructorCall : public AnyCXXConstructorCall {
protected:
CXXInheritedConstructorCall(const CXXInheritedCtorInitExpr *CE,
const MemRegion *Target, ProgramStateRef St,
const LocationContext *LCtx,
const StackFrame *SF,
CFGBlock::ConstCFGElementRef ElemRef)
: AnyCXXConstructorCall(CE, Target, St, LCtx, ElemRef) {}
: AnyCXXConstructorCall(CE, Target, St, SF, ElemRef) {}
CXXInheritedConstructorCall(const CXXInheritedConstructorCall &Other) =
default;
@ -1109,9 +1102,8 @@ public:
}
SVal getArgSVal(unsigned Index) const override {
return getState()->getSVal(
getArgExpr(Index),
getInheritingStackFrame()->getParent()->getStackFrame());
return getState()->getSVal(getArgExpr(Index),
getInheritingStackFrame()->getParent());
}
Kind getKind() const override { return CE_CXXInheritedConstructor; }
@ -1132,9 +1124,8 @@ class CXXAllocatorCall : public AnyFunctionCall {
protected:
CXXAllocatorCall(const CXXNewExpr *E, ProgramStateRef St,
const LocationContext *LCtx,
CFGBlock::ConstCFGElementRef ElemRef)
: AnyFunctionCall(E, St, LCtx, ElemRef) {}
const StackFrame *SF, CFGBlock::ConstCFGElementRef ElemRef)
: AnyFunctionCall(E, St, SF, ElemRef) {}
CXXAllocatorCall(const CXXAllocatorCall &Other) = default;
void cloneTo(void *Dest) const override {
@ -1152,7 +1143,7 @@ public:
SVal getObjectUnderConstruction() const {
return *ExprEngine::getObjectUnderConstruction(getState(), getOriginExpr(),
getLocationContext());
getStackFrame());
}
/// Number of non-placement arguments to the call. It is equal to 2 for
@ -1175,7 +1166,7 @@ public:
SVal getArraySizeVal() const {
assert(isArray() && "The allocator call doesn't allocate and array!");
return getState()->getSVal(*getArraySizeExpr(), getLocationContext());
return getState()->getSVal(*getArraySizeExpr(), getStackFrame());
}
const Expr *getArgExpr(unsigned Index) const override {
@ -1216,9 +1207,8 @@ class CXXDeallocatorCall : public AnyFunctionCall {
protected:
CXXDeallocatorCall(const CXXDeleteExpr *E, ProgramStateRef St,
const LocationContext *LCtx,
CFGBlock::ConstCFGElementRef ElemRef)
: AnyFunctionCall(E, St, LCtx, ElemRef) {}
const StackFrame *SF, CFGBlock::ConstCFGElementRef ElemRef)
: AnyFunctionCall(E, St, SF, ElemRef) {}
CXXDeallocatorCall(const CXXDeallocatorCall &Other) = default;
void cloneTo(void *Dest) const override {
@ -1265,9 +1255,8 @@ class ObjCMethodCall : public CallEvent {
protected:
ObjCMethodCall(const ObjCMessageExpr *Msg, ProgramStateRef St,
const LocationContext *LCtx,
CFGBlock::ConstCFGElementRef ElemRef)
: CallEvent(Msg, St, LCtx, ElemRef) {
const StackFrame *SF, CFGBlock::ConstCFGElementRef ElemRef)
: CallEvent(Msg, St, SF, ElemRef) {
Data = nullptr;
}
@ -1392,36 +1381,36 @@ class CallEventManager {
}
template <typename T, typename Arg>
T *create(Arg A, ProgramStateRef St, const LocationContext *LCtx,
T *create(Arg A, ProgramStateRef St, const StackFrame *SF,
CFGBlock::ConstCFGElementRef ElemRef) {
static_assert(sizeof(T) == sizeof(CallEventTemplateTy),
"CallEvent subclasses are not all the same size");
return new (allocate()) T(A, St, LCtx, ElemRef);
return new (allocate()) T(A, St, SF, ElemRef);
}
template <typename T, typename Arg1, typename Arg2>
T *create(Arg1 A1, Arg2 A2, ProgramStateRef St, const LocationContext *LCtx,
T *create(Arg1 A1, Arg2 A2, ProgramStateRef St, const StackFrame *SF,
CFGBlock::ConstCFGElementRef ElemRef) {
static_assert(sizeof(T) == sizeof(CallEventTemplateTy),
"CallEvent subclasses are not all the same size");
return new (allocate()) T(A1, A2, St, LCtx, ElemRef);
return new (allocate()) T(A1, A2, St, SF, ElemRef);
}
template <typename T, typename Arg1, typename Arg2, typename Arg3>
T *create(Arg1 A1, Arg2 A2, Arg3 A3, ProgramStateRef St,
const LocationContext *LCtx, CFGBlock::ConstCFGElementRef ElemRef) {
T *create(Arg1 A1, Arg2 A2, Arg3 A3, ProgramStateRef St, const StackFrame *SF,
CFGBlock::ConstCFGElementRef ElemRef) {
static_assert(sizeof(T) == sizeof(CallEventTemplateTy),
"CallEvent subclasses are not all the same size");
return new (allocate()) T(A1, A2, A3, St, LCtx, ElemRef);
return new (allocate()) T(A1, A2, A3, St, SF, ElemRef);
}
template <typename T, typename Arg1, typename Arg2, typename Arg3,
typename Arg4>
T *create(Arg1 A1, Arg2 A2, Arg3 A3, Arg4 A4, ProgramStateRef St,
const LocationContext *LCtx, CFGBlock::ConstCFGElementRef ElemRef) {
const StackFrame *SF, CFGBlock::ConstCFGElementRef ElemRef) {
static_assert(sizeof(T) == sizeof(CallEventTemplateTy),
"CallEvent subclasses are not all the same size");
return new (allocate()) T(A1, A2, A3, A4, St, LCtx, ElemRef);
return new (allocate()) T(A1, A2, A3, A4, St, SF, ElemRef);
}
public:
@ -1433,56 +1422,56 @@ public:
/// Gets a call event for a function call, Objective-C method call,
/// a 'new', or a 'delete' call.
CallEventRef<> getCall(const Stmt *S, ProgramStateRef State,
const LocationContext *LC,
const StackFrame *SF,
CFGBlock::ConstCFGElementRef ElemRef);
CallEventRef<> getSimpleCall(const CallExpr *E, ProgramStateRef State,
const LocationContext *LCtx,
const StackFrame *SF,
CFGBlock::ConstCFGElementRef ElemRef);
CallEventRef<ObjCMethodCall>
getObjCMethodCall(const ObjCMessageExpr *E, ProgramStateRef State,
const LocationContext *LCtx,
const StackFrame *SF,
CFGBlock::ConstCFGElementRef ElemRef) {
return create<ObjCMethodCall>(E, State, LCtx, ElemRef);
return create<ObjCMethodCall>(E, State, SF, ElemRef);
}
CallEventRef<CXXConstructorCall>
getCXXConstructorCall(const CXXConstructExpr *E, const MemRegion *Target,
ProgramStateRef State, const LocationContext *LCtx,
ProgramStateRef State, const StackFrame *SF,
CFGBlock::ConstCFGElementRef ElemRef) {
return create<CXXConstructorCall>(E, Target, State, LCtx, ElemRef);
return create<CXXConstructorCall>(E, Target, State, SF, ElemRef);
}
CallEventRef<CXXInheritedConstructorCall>
getCXXInheritedConstructorCall(const CXXInheritedCtorInitExpr *E,
const MemRegion *Target, ProgramStateRef State,
const LocationContext *LCtx,
const StackFrame *SF,
CFGBlock::ConstCFGElementRef ElemRef) {
return create<CXXInheritedConstructorCall>(E, Target, State, LCtx, ElemRef);
return create<CXXInheritedConstructorCall>(E, Target, State, SF, ElemRef);
}
CallEventRef<CXXDestructorCall>
getCXXDestructorCall(const CXXDestructorDecl *DD, const Stmt *Trigger,
const MemRegion *Target, bool IsBase,
ProgramStateRef State, const LocationContext *LCtx,
ProgramStateRef State, const StackFrame *SF,
CFGBlock::ConstCFGElementRef ElemRef) {
return create<CXXDestructorCall>(DD, Trigger, Target, IsBase, State, LCtx,
return create<CXXDestructorCall>(DD, Trigger, Target, IsBase, State, SF,
ElemRef);
}
CallEventRef<CXXAllocatorCall>
getCXXAllocatorCall(const CXXNewExpr *E, ProgramStateRef State,
const LocationContext *LCtx,
const StackFrame *SF,
CFGBlock::ConstCFGElementRef ElemRef) {
return create<CXXAllocatorCall>(E, State, LCtx, ElemRef);
return create<CXXAllocatorCall>(E, State, SF, ElemRef);
}
CallEventRef<CXXDeallocatorCall>
getCXXDeallocatorCall(const CXXDeleteExpr *E, ProgramStateRef State,
const LocationContext *LCtx,
const StackFrame *SF,
CFGBlock::ConstCFGElementRef ElemRef) {
return create<CXXDeallocatorCall>(E, State, LCtx, ElemRef);
return create<CXXDeallocatorCall>(E, State, SF, ElemRef);
}
};

View file

@ -101,14 +101,10 @@ public:
return Eng.getContext().getLangOpts();
}
const LocationContext *getLocationContext() const {
return Pred->getLocationContext();
}
const StackFrame *getStackFrame() const { return Pred->getStackFrame(); }
/// Return true if the current LocationContext has no caller context.
bool inTopFrame() const { return getLocationContext()->inTopFrame(); }
/// Return true if the current StackFrame has no caller context.
bool inTopFrame() const { return getStackFrame()->inTopFrame(); }
BugReporter &getBugReporter() {
return Eng.getBugReporter();
@ -147,7 +143,7 @@ public:
}
AnalysisDeclContext *getCurrentAnalysisDeclContext() const {
return Pred->getLocationContext()->getAnalysisDeclContext();
return Pred->getStackFrame()->getAnalysisDeclContext();
}
/// Get the blockID.

View file

@ -137,7 +137,7 @@ public:
/// ExecuteWorkList - Run the worklist algorithm for a maximum number of
/// steps. Returns true if there is still simulation state on the worklist.
bool ExecuteWorkList(const LocationContext *L, unsigned Steps,
bool ExecuteWorkList(const StackFrame *SF, unsigned Steps,
ProgramStateRef InitState);
/// Dispatch the work list item based on the given location information.
@ -173,7 +173,7 @@ public:
ExplodedNode *makePostStmtNode(const Stmt *S, ProgramStateRef State,
ExplodedNode *Pred,
bool MarkAsSink = false) const {
PostStmt Loc(S, Pred->getLocationContext(), /*tag=*/nullptr);
PostStmt Loc(S, Pred->getStackFrame(), /*tag=*/nullptr);
return makeNode(Loc, State, Pred, MarkAsSink);
}
@ -181,9 +181,9 @@ public:
makeNodeWithBinding(ExplodedNode *Pred, const Expr *E, SVal V,
ProgramStateRef State,
ProgramPoint::Kind K = ProgramPoint::PostStmtKind) const {
const LocationContext *LC = Pred->getLocationContext();
State = State->BindExpr(E, LC, V);
const auto &L = ProgramPoint::getProgramPoint(E, K, LC, /*tag=*/nullptr);
const StackFrame *SF = Pred->getStackFrame();
State = State->BindExpr(E, SF, V);
const auto &L = ProgramPoint::getProgramPoint(E, K, SF, /*tag=*/nullptr);
return makeNode(L, State, Pred);
}
@ -214,17 +214,17 @@ public:
class NodeBuilderContext {
const CoreEngine &Eng;
const CFGBlock *Block;
const LocationContext *LC;
const StackFrame *SF;
public:
NodeBuilderContext(const CoreEngine &E, const CFGBlock *B,
const LocationContext *L)
: Eng(E), Block(B), LC(L) {
const StackFrame *S)
: Eng(E), Block(B), SF(S) {
assert(B);
}
NodeBuilderContext(const CoreEngine &E, const CFGBlock *B, ExplodedNode *N)
: NodeBuilderContext(E, B, N->getLocationContext()) {}
: NodeBuilderContext(E, B, N->getStackFrame()) {}
/// Return the CoreEngine associated with this builder.
const CoreEngine &getEngine() const { return Eng; }
@ -232,15 +232,13 @@ public:
/// Return the CFGBlock associated with this builder.
const CFGBlock *getBlock() const { return Block; }
/// Return the location context associated with this builder.
const LocationContext *getLocationContext() const { return LC; }
/// Return the stack frame associated with this builder.
const StackFrame *getStackFrame() const { return SF; }
/// Returns the number of times the current basic block has been
/// visited on the exploded graph path.
unsigned blockCount() const {
return Eng.WList->getBlockCounter().getNumVisited(
LC->getStackFrame(),
Block->getBlockID());
return Eng.WList->getBlockCounter().getNumVisited(SF, Block->getBlockID());
}
};
@ -310,8 +308,8 @@ public:
ProgramStateRef St,
const ProgramPointTag *tag = nullptr,
ProgramPoint::Kind K = ProgramPoint::PostStmtKind){
const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
Pred->getLocationContext(), tag);
const ProgramPoint &L =
ProgramPoint::getProgramPoint(S, K, Pred->getStackFrame(), tag);
return generateNode(L, St, Pred);
}
@ -320,8 +318,8 @@ public:
ProgramStateRef St,
const ProgramPointTag *tag = nullptr,
ProgramPoint::Kind K = ProgramPoint::PostStmtKind){
const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
Pred->getLocationContext(), tag);
const ProgramPoint &L =
ProgramPoint::getProgramPoint(S, K, Pred->getStackFrame(), tag);
return generateSink(L, St, Pred);
}

View file

@ -28,22 +28,22 @@ namespace ento {
class SValBuilder;
class SymbolReaper;
/// An entry in the environment consists of a Stmt and an LocationContext.
/// An entry in the environment consists of a Stmt and an StackFrame.
/// This allows the environment to manage context-sensitive bindings,
/// which is essentially for modeling recursive function analysis, among
/// other things.
class EnvironmentEntry : public std::pair<const Expr *, const StackFrame *> {
public:
EnvironmentEntry(const Expr *E, const LocationContext *L);
EnvironmentEntry(const Expr *E, const StackFrame *SF);
const Expr *getExpr() const { return first; }
const LocationContext *getLocationContext() const { return second; }
const StackFrame *getStackFrame() const { return second; }
/// Profile an EnvironmentEntry for inclusion in a FoldingSet.
static void Profile(llvm::FoldingSetNodeID &ID,
const EnvironmentEntry &E) {
ID.AddPointer(E.getExpr());
ID.AddPointer(E.getLocationContext());
ID.AddPointer(E.getStackFrame());
}
void Profile(llvm::FoldingSetNodeID &ID) const {
@ -91,7 +91,7 @@ public:
}
void printJson(raw_ostream &Out, const ASTContext &Ctx,
const LocationContext *LCtx = nullptr, const char *NL = "\n",
const StackFrame *SF = nullptr, const char *NL = "\n",
unsigned int Space = 0, bool IsDot = false) const;
};

View file

@ -140,26 +140,22 @@ public:
/// getLocation - Returns the edge associated with the given node.
ProgramPoint getLocation() const { return Location; }
const LocationContext *getLocationContext() const {
return getLocation().getLocationContext();
}
const StackFrame *getStackFrame() const {
return getLocation().getStackFrame();
}
const Decl &getCodeDecl() const { return *getLocationContext()->getDecl(); }
const Decl &getCodeDecl() const { return *getStackFrame()->getDecl(); }
CFG &getCFG() const { return *getLocationContext()->getCFG(); }
CFG &getCFG() const { return *getStackFrame()->getCFG(); }
const CFGBlock *getCFGBlock() const;
const ParentMap &getParentMap() const {
return getLocationContext()->getParentMap();
return getStackFrame()->getParentMap();
}
template <typename T> T &getAnalysis() const {
return *getLocationContext()->getAnalysis<T>();
return *getStackFrame()->getAnalysis<T>();
}
const ProgramStateRef &getState() const { return State; }
@ -170,7 +166,7 @@ public:
/// Get the value of an arbitrary expression at this node.
SVal getSVal(const Expr *E) const {
return getState()->getSVal(E, getLocationContext());
return getState()->getSVal(E, getStackFrame());
}
static void Profile(llvm::FoldingSetNodeID &ID,

View file

@ -57,7 +57,6 @@ class Decl;
class DeclStmt;
class GCCAsmStmt;
class LambdaExpr;
class LocationContext;
class MaterializeTemporaryExpr;
class MSAsmStmt;
class NamedDecl;
@ -162,22 +161,22 @@ private:
/// which has three independent roles:
/// - It holds a pointer to the CFGBlock that is currently under analysis.
/// (This is the primary way to get the current block.)
/// - It holds a pointer to the current LocationContext. (This is rarely
/// used, the location context is usually queried from a recent
/// - It holds a pointer to the current StackFrame. (This is rarely
/// used, the stack frame is usually queried from a recent
/// ExplodedNode. Unfortunately it seems that these two sources of truth
/// are not always consistent.)
/// - It can be used for constructing `NodeBuilder`s. Practically all
/// `NodeBuilder` objects are useless complications in the code, so I
/// intend to replace them with direct use of `CoreEngine::makeNode`.
/// TODO: Eventually `currBldrCtx` should be replaced by two separate fields:
/// `const CFGBlock *CurrBlock` & `const LocationContext *CurrLocationContext`
/// `const CFGBlock *CurrBlock` & `const StackFrame *CurrStackFrame`
/// that are kept up-to-date and are almost always non-null during the
/// analysis. I will switch to this more natural representation when
/// `NodeBuilder`s are eliminated from the code.
const NodeBuilderContext *currBldrCtx = nullptr;
/// Historically `currBldrCtx` pointed to a local variable in some stack
/// frame. This field is introduced as a temporary measure to allow a gradual
/// transition. Only use this in {re,}setLocationContextAndBlock!
/// transition. Only use this in {re,}setCurrStackFrameAndBlock!
/// TODO: Remove this temporary hack.
std::optional<NodeBuilderContext> OwnedCurrBldrCtx;
@ -205,10 +204,10 @@ public:
virtual ~ExprEngine() = default;
/// Returns true if there is still simulation state on the worklist.
bool ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) {
assert(L->inTopFrame());
BR.setAnalysisEntryPoint(L->getDecl());
return Engine.ExecuteWorkList(L, Steps, nullptr);
bool ExecuteWorkList(const StackFrame *SF, unsigned Steps = 150000) {
assert(SF->inTopFrame());
BR.setAnalysisEntryPoint(SF->getDecl());
return Engine.ExecuteWorkList(SF, Steps, nullptr);
}
/// getContext - Return the ASTContext associated with this analysis.
@ -237,27 +236,26 @@ public:
}
// FIXME: Ideally the body of this method should look like
// CurrLocationContext = LC;
// CurrStackFrame = SF;
// CurrBlock = B;
// where CurrLocationContext and CurrBlock are new member variables that
// where CurrStackFrame and CurrBlock are new member variables that
// fulfill the roles of `currBldrCtx` in a more natural way.
// This implementation is a temporary measure to allow a gradual transition.
void setCurrLocationContextAndBlock(const LocationContext *LC,
const CFGBlock *B) {
// The current LocationContext and Block is reset at the beginning of
void setCurrStackFrameAndBlock(const StackFrame *SF, const CFGBlock *B) {
// The current StackFrame and Block is reset at the beginning of
// dispatchWorkItem. Ideally, this method should be called only once per
// dispatchWorkItem call (= elementary analysis step); so the following
// assertion is there to catch accidental repeated calls. If the current
// LocationContext and Block needs to change in the middle of a single step
// StackFrame and Block needs to change in the middle of a single step
// (which currently happens only once, in processCallExit), use an explicit
// call to resetCurrLocationContextAndBlock.
// call to resetCurrStackFrameAndBlock.
assert(!currBldrCtx && !OwnedCurrBldrCtx &&
"The current LocationContext and Block is already set");
OwnedCurrBldrCtx.emplace(Engine, B, LC);
"The current StackFrame and Block is already set");
OwnedCurrBldrCtx.emplace(Engine, B, SF);
currBldrCtx = &*OwnedCurrBldrCtx;
}
void resetCurrLocationContextAndBlock() {
void resetCurrStackFrameAndBlock() {
currBldrCtx = nullptr;
OwnedCurrBldrCtx = std::nullopt;
}
@ -267,20 +265,20 @@ public:
return *currBldrCtx;
}
const LocationContext *getRootLocationContext() const {
const StackFrame *getRootStackFrame() const {
assert(G.getRoot());
return G.getRoot()->getLocation().getLocationContext();
return G.getRoot()->getLocation().getStackFrame();
}
/// Get the 'current' location context corresponding to the current work item
/// Get the 'current' stack frame corresponding to the current work item
/// (elementary analysis step handled by `dispatchWorkItem`).
/// FIXME: This sometimes (e.g. in some `BeginFunction` callbacks) differs
/// from the `LocationContext` that can be obtained from different sources
/// (e.g. a recent `ExplodedNode`). Traditionally this location context is
/// from the `StackFrame` that can be obtained from different sources
/// (e.g. a recent `ExplodedNode`). Traditionally this stack frame is
/// only used for block count calculations (`getNumVisited`); it is probably
/// wise to follow this tradition until the discrepancies are resolved.
const LocationContext *getCurrLocationContext() const {
return currBldrCtx ? currBldrCtx->getLocationContext() : nullptr;
const StackFrame *getCurrStackFrame() const {
return currBldrCtx ? currBldrCtx->getStackFrame() : nullptr;
}
/// Get the 'current' CFGBlock corresponding to the current work item
@ -293,14 +291,13 @@ public:
return {getCurrBlock(), currStmtIdx};
}
unsigned getNumVisited(const LocationContext *LC,
const CFGBlock *Block) const {
return Engine.WList->getBlockCounter().getNumVisited(LC->getStackFrame(),
unsigned getNumVisited(const StackFrame *SF, const CFGBlock *Block) const {
return Engine.WList->getBlockCounter().getNumVisited(SF,
Block->getBlockID());
}
unsigned getNumVisitedCurrent() const {
return getNumVisited(getCurrLocationContext(), getCurrBlock());
return getNumVisited(getCurrStackFrame(), getCurrBlock());
}
/// Dump graph to the specified filename.
@ -323,7 +320,7 @@ public:
/// getInitialState - Return the initial state used for the root vertex
/// in the ExplodedGraph.
ProgramStateRef getInitialState(const LocationContext *InitLoc);
ProgramStateRef getInitialState(const StackFrame *InitSF);
ExplodedGraph &getGraph() { return G; }
const ExplodedGraph &getGraph() const { return G; }
@ -339,24 +336,25 @@ public:
/// \param Out The returned set of output nodes.
/// \param ReferenceStmt The statement which is about to be processed.
/// Everything needed for this statement should be considered live.
/// A null statement means that everything in child LocationContexts
/// A null statement means that everything in child StackFrames
/// is dead.
/// \param LC The location context of the \p ReferenceStmt. A null location
/// context means that we have reached the end of analysis and that
/// \param SF The stack frame of the \p ReferenceStmt. A null stack frame
/// means that we have reached the end of analysis and that
/// all statements and local variables should be considered dead.
/// \param DiagnosticStmt Used as a location for any warnings that should
/// occur while removing the dead (e.g. leaks). By default, the
/// \p ReferenceStmt is used.
/// \param K Denotes whether this is a pre- or post-statement purge. This
/// must only be ProgramPoint::PostStmtPurgeDeadSymbolsKind if an
/// entire location context is being cleared, in which case the
/// entire stack frame is being cleared, in which case the
/// \p ReferenceStmt must either be a ReturnStmt or \c NULL. Otherwise,
/// it must be ProgramPoint::PreStmtPurgeDeadSymbolsKind (the default)
/// and \p ReferenceStmt must be valid (non-null).
void removeDead(ExplodedNode *Node, ExplodedNodeSet &Out,
const Stmt *ReferenceStmt, const LocationContext *LC,
const Stmt *DiagnosticStmt = nullptr,
ProgramPoint::Kind K = ProgramPoint::PreStmtPurgeDeadSymbolsKind);
void
removeDead(ExplodedNode *Node, ExplodedNodeSet &Out,
const Stmt *ReferenceStmt, const StackFrame *SF,
const Stmt *DiagnosticStmt = nullptr,
ProgramPoint::Kind K = ProgramPoint::PreStmtPurgeDeadSymbolsKind);
/// A tag to track convenience transitions, which can be removed at cleanup.
/// This tag applies to a node created after removeDead.
@ -462,20 +460,17 @@ public:
const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const LocationContext *LCtx,
const CallEvent *Call);
const StackFrame *SF, const CallEvent *Call);
inline ProgramStateRef
processRegionChange(ProgramStateRef state,
const MemRegion* MR,
const LocationContext *LCtx) {
return processRegionChanges(state, nullptr, MR, MR, LCtx, nullptr);
inline ProgramStateRef processRegionChange(ProgramStateRef state,
const MemRegion *MR,
const StackFrame *SF) {
return processRegionChanges(state, nullptr, MR, MR, SF, nullptr);
}
/// printJson - Called by ProgramStateManager to print checker-specific data.
void printJson(raw_ostream &Out, ProgramStateRef State,
const LocationContext *LCtx, const char *NL,
unsigned int Space, bool IsDot) const;
void printJson(raw_ostream &Out, ProgramStateRef State, const StackFrame *SF,
const char *NL, unsigned int Space, bool IsDot) const;
ProgramStateManager &getStateManager() { return StateMgr; }
const ProgramStateManager &getStateManager() const { return StateMgr; }
@ -673,7 +668,7 @@ public:
getEagerlyAssumeBifurcationTags();
ProgramStateRef handleLValueBitCast(ProgramStateRef state, const Expr *Ex,
const LocationContext *LCtx, QualType T,
const StackFrame *SF, QualType T,
QualType ExTy, const CastExpr *CastE,
NodeBuilder &Bldr, ExplodedNode *Pred);
@ -689,17 +684,16 @@ public:
/// Retrieves which element is being constructed in a non-POD type array.
static std::optional<unsigned>
getIndexOfElementToConstruct(ProgramStateRef State, const CXXConstructExpr *E,
const LocationContext *LCtx);
const StackFrame *SF);
/// Retrieves which element is being destructed in a non-POD type array.
static std::optional<unsigned>
getPendingArrayDestruction(ProgramStateRef State,
const LocationContext *LCtx);
getPendingArrayDestruction(ProgramStateRef State, const StackFrame *SF);
/// Retrieves the size of the array in the pending ArrayInitLoopExpr.
static std::optional<unsigned>
getPendingInitLoop(ProgramStateRef State, const CXXConstructExpr *E,
const LocationContext *LCtx);
static std::optional<unsigned> getPendingInitLoop(ProgramStateRef State,
const CXXConstructExpr *E,
const StackFrame *SF);
/// By looking at a certain item that may be potentially part of an object's
/// ConstructionContext, retrieve such object's location. A particular
@ -707,13 +701,12 @@ public:
static std::optional<SVal>
getObjectUnderConstruction(ProgramStateRef State,
const ConstructionContextItem &Item,
const LocationContext *LC);
const StackFrame *SF);
/// Call PointerEscape callback when a value escapes as a result of bind.
ProgramStateRef processPointerEscapedOnBind(
ProgramStateRef State, ArrayRef<std::pair<SVal, SVal>> LocAndVals,
const LocationContext *LCtx, PointerEscapeKind Kind,
const CallEvent *Call);
const StackFrame *SF, PointerEscapeKind Kind, const CallEvent *Call);
/// Call PointerEscape callback when a value escapes as a result of
/// region invalidation.
@ -732,10 +725,8 @@ private:
SVal location, SVal Val, bool AtDeclInit = false,
const ProgramPoint *PP = nullptr);
ProgramStateRef
processPointerEscapedOnBind(ProgramStateRef State,
SVal Loc, SVal Val,
const LocationContext *LCtx);
ProgramStateRef processPointerEscapedOnBind(ProgramStateRef State, SVal Loc,
SVal Val, const StackFrame *SF);
public:
/// A simple wrapper when you only need to notify checkers of pointer-escape
@ -744,7 +735,7 @@ public:
PointerEscapeKind K,
const CallEvent *Call = nullptr) const;
// FIXME: 'tag' should be removed, and a LocationContext should be used
// FIXME: 'tag' should be removed, and a StackFrame should be used
// instead.
// FIXME: Comment on the meaning of the arguments, when 'St' may not
// be the same as Pred->state, and when 'location' may not be the
@ -759,7 +750,7 @@ public:
const ProgramPointTag *tag = nullptr,
QualType LoadTy = QualType());
// FIXME: 'tag' should be removed, and a LocationContext should be used
// FIXME: 'tag' should be removed, and a StackFrame should be used
// instead.
void evalStore(ExplodedNodeSet &Dst, const Expr *AssignE, const Expr *StoreE,
ExplodedNode *Pred, ProgramStateRef St, SVal TargetLV, SVal Val,
@ -771,8 +762,7 @@ public:
/// Create a new state in which the call return value is binded to the
/// call origin expression.
ProgramStateRef bindReturnValue(const CallEvent &Call,
const LocationContext *LCtx,
ProgramStateRef bindReturnValue(const CallEvent &Call, const StackFrame *SF,
ProgramStateRef State);
/// Evaluate a call, running pre- and post-call checkers and allowing checkers
@ -800,7 +790,7 @@ public:
/// row major order, so for arr[0][0] Idx is 0 and for arr[3][3] Idx is 8.
SVal computeObjectUnderConstruction(const Expr *E, ProgramStateRef State,
unsigned NumVisitedCaller,
const LocationContext *LCtx,
const StackFrame *SF,
const ConstructionContext *CC,
EvalCallOptions &CallOpts,
unsigned Idx = 0);
@ -809,21 +799,22 @@ public:
/// that's necessary to perform construction of an object with a given
/// syntactic construction context. V and CallOpts have to be obtained from
/// computeObjectUnderConstruction() invoked with the same set of
/// the remaining arguments (E, State, LCtx, CC).
/// the remaining arguments (E, State, SF, CC).
ProgramStateRef updateObjectsUnderConstruction(
SVal V, const Expr *E, ProgramStateRef State, const LocationContext *LCtx,
SVal V, const Expr *E, ProgramStateRef State, const StackFrame *SF,
const ConstructionContext *CC, const EvalCallOptions &CallOpts);
/// A convenient wrapper around computeObjectUnderConstruction
/// and updateObjectsUnderConstruction.
std::pair<ProgramStateRef, SVal> handleConstructionContext(
const Expr *E, ProgramStateRef State, const NodeBuilderContext *BldrCtx,
const LocationContext *LCtx, const ConstructionContext *CC,
EvalCallOptions &CallOpts, unsigned Idx = 0) {
std::pair<ProgramStateRef, SVal>
handleConstructionContext(const Expr *E, ProgramStateRef State,
const NodeBuilderContext *BldrCtx,
const StackFrame *SF, const ConstructionContext *CC,
EvalCallOptions &CallOpts, unsigned Idx = 0) {
SVal V = computeObjectUnderConstruction(E, State, BldrCtx->blockCount(),
LCtx, CC, CallOpts, Idx);
State = updateObjectsUnderConstruction(V, E, State, LCtx, CC, CallOpts);
SVal V = computeObjectUnderConstruction(E, State, BldrCtx->blockCount(), SF,
CC, CallOpts, Idx);
State = updateObjectsUnderConstruction(V, E, State, SF, CC, CallOpts);
return std::make_pair(State, V);
}
@ -843,7 +834,7 @@ private:
bool isLoad);
/// Count the stack depth and determine if the call is recursive.
void examineStackFrames(const Decl *D, const LocationContext *LCtx,
void examineStackFrames(const Decl *D, const StackFrame *SF,
bool &IsRecursive, unsigned &StackDepth);
enum CallInlinePolicy {
@ -887,7 +878,7 @@ private:
/// construction.
bool shouldInlineArrayConstruction(const ProgramStateRef State,
const CXXConstructExpr *CE,
const LocationContext *LCtx);
const StackFrame *SF);
/// Checks whether our policies allow us to inline a non-POD type array
/// destruction.
@ -901,19 +892,19 @@ private:
/// original state along with an index of 0. The actual element count of the
/// array can be accessed by the optional 'ElementCountVal' parameter. \param
/// State The program state. \param Region The memory region where the array
/// is stored. \param ElementTy The type an element in the array. \param LCty
/// The location context. \param ElementCountVal A pointer to an optional
/// SVal. If specified, the size of the array will be returned in it. It can
/// is stored. \param ElementTy The type an element in the array. \param SF
/// The stack frame. \param ElementCountVal A pointer to an optional SVal.
/// If specified, the size of the array will be returned in it. It can
/// be Unknown.
std::pair<ProgramStateRef, uint64_t> prepareStateForArrayDestruction(
const ProgramStateRef State, const MemRegion *Region,
const QualType &ElementTy, const LocationContext *LCtx,
const QualType &ElementTy, const StackFrame *SF,
SVal *ElementCountVal = nullptr);
/// Checks whether we construct an array of non-POD type, and decides if the
/// constructor should be invoked once again.
bool shouldRepeatCtorCall(ProgramStateRef State, const CXXConstructExpr *E,
const LocationContext *LCtx);
const StackFrame *SF);
void inlineCall(WorkList *WList, const CallEvent &Call, const Decl *D,
NodeBuilder &Bldr, ExplodedNode *Pred, ProgramStateRef State);
@ -935,7 +926,7 @@ private:
const CallEvent &Call, const Decl *D, NodeBuilder &Bldr,
ExplodedNode *Pred);
bool replayWithoutInlining(ExplodedNode *P, const LocationContext *CalleeLC);
bool replayWithoutInlining(ExplodedNode *P, const StackFrame *CalleeSF);
/// Models a trivial copy or move constructor or trivial assignment operator
/// call with a simple bind.
@ -953,7 +944,7 @@ private:
/// OutRegionWithAdjustments out-parameter if a new region was indeed needed,
/// otherwise sets it to nullptr.
ProgramStateRef createTemporaryRegionIfNeeded(
ProgramStateRef State, const LocationContext *LC,
ProgramStateRef State, const StackFrame *SF,
const Expr *InitWithAdjustments, const Expr *Result = nullptr,
const SubRegion **OutRegionWithAdjustments = nullptr);
@ -980,52 +971,47 @@ public:
[[nodiscard]] static ProgramStateRef
setWhetherHasMoreIteration(ProgramStateRef State,
const ObjCForCollectionStmt *O,
const LocationContext *LC, bool HasMoreIteraton);
const StackFrame *SF, bool HasMoreIteraton);
[[nodiscard]] static ProgramStateRef
removeIterationState(ProgramStateRef State, const ObjCForCollectionStmt *O,
const LocationContext *LC);
const StackFrame *SF);
[[nodiscard]] static bool hasMoreIteration(ProgramStateRef State,
const ObjCForCollectionStmt *O,
const LocationContext *LC);
const StackFrame *SF);
private:
/// Assuming we construct an array of non-POD types, this method allows us
/// to store which element is to be constructed next.
static ProgramStateRef
setIndexOfElementToConstruct(ProgramStateRef State, const CXXConstructExpr *E,
const LocationContext *LCtx, unsigned Idx);
static ProgramStateRef setIndexOfElementToConstruct(ProgramStateRef State,
const CXXConstructExpr *E,
const StackFrame *SF,
unsigned Idx);
static ProgramStateRef
removeIndexOfElementToConstruct(ProgramStateRef State,
const CXXConstructExpr *E,
const LocationContext *LCtx);
static ProgramStateRef removeIndexOfElementToConstruct(
ProgramStateRef State, const CXXConstructExpr *E, const StackFrame *SF);
/// Assuming we destruct an array of non-POD types, this method allows us
/// to store which element is to be destructed next.
static ProgramStateRef setPendingArrayDestruction(ProgramStateRef State,
const LocationContext *LCtx,
const StackFrame *SF,
unsigned Idx);
static ProgramStateRef
removePendingArrayDestruction(ProgramStateRef State,
const LocationContext *LCtx);
static ProgramStateRef removePendingArrayDestruction(ProgramStateRef State,
const StackFrame *SF);
/// Sets the size of the array in a pending ArrayInitLoopExpr.
static ProgramStateRef setPendingInitLoop(ProgramStateRef State,
const CXXConstructExpr *E,
const LocationContext *LCtx,
unsigned Idx);
const StackFrame *SF, unsigned Idx);
static ProgramStateRef removePendingInitLoop(ProgramStateRef State,
const CXXConstructExpr *E,
const LocationContext *LCtx);
const StackFrame *SF);
static ProgramStateRef
removeStateTraitsUsedForArrayEvaluation(ProgramStateRef State,
const CXXConstructExpr *E,
const LocationContext *LCtx);
static ProgramStateRef removeStateTraitsUsedForArrayEvaluation(
ProgramStateRef State, const CXXConstructExpr *E, const StackFrame *SF);
/// Store the location of a C++ object corresponding to a statement
/// until the statement is actually encountered. For example, if a DeclStmt
@ -1037,42 +1023,42 @@ private:
static ProgramStateRef
addObjectUnderConstruction(ProgramStateRef State,
const ConstructionContextItem &Item,
const LocationContext *LC, SVal V);
const StackFrame *SF, SVal V);
/// Mark the object as fully constructed, cleaning up the state trait
/// that tracks objects under construction.
static ProgramStateRef
finishObjectConstruction(ProgramStateRef State,
const ConstructionContextItem &Item,
const LocationContext *LC);
const StackFrame *SF);
/// If the given expression corresponds to a temporary that was used for
/// passing into an elidable copy/move constructor and that constructor
/// was actually elided, track that we also need to elide the destructor.
static ProgramStateRef elideDestructor(ProgramStateRef State,
const CXXBindTemporaryExpr *BTE,
const LocationContext *LC);
const StackFrame *SF);
/// Stop tracking the destructor that corresponds to an elided constructor.
static ProgramStateRef
cleanupElidedDestructor(ProgramStateRef State,
const CXXBindTemporaryExpr *BTE,
const LocationContext *LC);
const StackFrame *SF);
/// Returns true if the given expression corresponds to a temporary that
/// was constructed for passing into an elidable copy/move constructor
/// and that constructor was actually elided.
static bool isDestructorElided(ProgramStateRef State,
const CXXBindTemporaryExpr *BTE,
const LocationContext *LC);
const StackFrame *SF);
/// Check if all objects under construction have been fully constructed
/// for the given context range (including FromLC, not including ToLC).
/// for the given context range (including FromSF, not including ToSF).
/// This is useful for assertions. Also checks if elided destructors
/// were cleaned up.
static bool areAllObjectsFullyConstructed(ProgramStateRef State,
const LocationContext *FromLC,
const LocationContext *ToLC);
const StackFrame *FromSF,
const StackFrame *ToSF);
};
/// Traits for storing the call processing policy inside GDM.

View file

@ -26,8 +26,7 @@ namespace ento {
/// Widen the loop by invalidating anything that might be modified
/// by the loop body in any iteration.
ProgramStateRef getWidenedLoopState(ProgramStateRef PrevState,
const LocationContext *LCtx,
unsigned BlockCount,
const StackFrame *SF, unsigned BlockCount,
ConstCFGElementRef Elem);
} // end namespace ento

View file

@ -48,7 +48,6 @@ namespace clang {
class AnalysisDeclContext;
class CXXRecordDecl;
class Decl;
class LocationContext;
class StackFrame;
namespace ento {
@ -707,26 +706,25 @@ class BlockDataRegion : public TypedRegion {
friend class MemRegionManager;
const BlockCodeRegion *BC;
const LocationContext *LC; // Can be null
const StackFrame *SF;
unsigned BlockCount;
void *ReferencedVars = nullptr;
void *OriginalVars = nullptr;
BlockDataRegion(const BlockCodeRegion *bc, const LocationContext *lc,
BlockDataRegion(const BlockCodeRegion *bc, const StackFrame *SF,
unsigned count, const MemSpaceRegion *sreg)
: TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc),
: TypedRegion(sreg, BlockDataRegionKind), BC(bc), SF(SF),
BlockCount(count) {
assert(bc);
assert(bc->getDecl());
assert(lc);
assert(SF);
assert(isa<GlobalImmutableSpaceRegion>(sreg) ||
isa<StackLocalsSpaceRegion>(sreg) ||
isa<UnknownSpaceRegion>(sreg));
}
static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockCodeRegion *,
const LocationContext *, unsigned,
const MemRegion *);
static void ProfileRegion(llvm::FoldingSetNodeID &, const BlockCodeRegion *,
const StackFrame *, unsigned, const MemRegion *);
public:
LLVM_ATTRIBUTE_RETURNS_NONNULL
@ -1496,18 +1494,17 @@ public:
/// getAllocaRegion - Retrieve a region associated with a call to alloca().
const AllocaRegion *getAllocaRegion(const Expr *Ex, unsigned Cnt,
const LocationContext *LC);
const StackFrame *SF);
/// getCompoundLiteralRegion - Retrieve the region associated with a
/// given CompoundLiteral.
const CompoundLiteralRegion*
getCompoundLiteralRegion(const CompoundLiteralExpr *CL,
const LocationContext *LC);
const CompoundLiteralRegion *
getCompoundLiteralRegion(const CompoundLiteralExpr *CL, const StackFrame *SF);
/// getCXXThisRegion - Retrieve the [artificial] region associated with the
/// parameter 'this'.
const CXXThisRegion *getCXXThisRegion(QualType thisPointerTy,
const LocationContext *LC);
const StackFrame *SF);
/// Retrieve or create a "symbolic" memory region.
/// If no memory space is specified, `UnknownSpaceRegion` will be used.
@ -1522,19 +1519,18 @@ public:
const ObjCStringRegion *getObjCStringRegion(const ObjCStringLiteral *Str);
/// getVarRegion - Retrieve or create the memory region associated with
/// a specified VarDecl and LocationContext.
const VarRegion *getVarRegion(const VarDecl *VD, const LocationContext *LC);
/// a specified VarDecl and StackFrame.
const VarRegion *getVarRegion(const VarDecl *VD, const StackFrame *SF);
/// getVarRegion - Retrieve or create the memory region associated with
/// a specified VarDecl and LocationContext.
/// a specified VarDecl and StackFrame.
const NonParamVarRegion *getNonParamVarRegion(const VarDecl *VD,
const MemRegion *superR);
/// getParamVarRegion - Retrieve or create the memory region
/// associated with a specified CallExpr, Index and LocationContext.
/// associated with a specified CallExpr, Index and StackFrame.
const ParamVarRegion *getParamVarRegion(const Expr *OriginExpr,
unsigned Index,
const LocationContext *LC);
unsigned Index, const StackFrame *SF);
/// getElementRegion - Retrieve the memory region associated with the
/// associated element type, index, and super region.
@ -1568,18 +1564,18 @@ public:
const SubRegion* superRegion);
const CXXTempObjectRegion *getCXXTempObjectRegion(Expr const *Ex,
LocationContext const *LC);
StackFrame const *SF);
/// Create a CXXLifetimeExtendedObjectRegion for temporaries which are
/// lifetime-extended by local references.
const CXXLifetimeExtendedObjectRegion *
getCXXLifetimeExtendedObjectRegion(Expr const *Ex, ValueDecl const *VD,
LocationContext const *LC);
StackFrame const *SF);
/// Create a CXXLifetimeExtendedObjectRegion for temporaries which are
/// lifetime-extended by *static* references.
/// This differs from \ref getCXXLifetimeExtendedObjectRegion(Expr const *,
/// ValueDecl const *, LocationContext const *) in the super-region used.
/// ValueDecl const *, StackFrame const *) in the super-region used.
const CXXLifetimeExtendedObjectRegion *
getCXXStaticLifetimeExtendedObjectRegion(const Expr *Ex, ValueDecl const *VD);
@ -1614,11 +1610,10 @@ public:
AnalysisDeclContext *AC);
/// getBlockDataRegion - Get the memory region associated with an instance
/// of a block. Unlike many other MemRegions, the LocationContext*
/// argument is allowed to be NULL for cases where we have no known
/// context.
/// of a block. Unlike many other MemRegions, the StackFrame * argument
/// is allowed to be NULL for cases where we have no known stack frame.
const BlockDataRegion *getBlockDataRegion(const BlockCodeRegion *bc,
const LocationContext *lc,
const StackFrame *SF,
unsigned blockCount);
private:

View file

@ -272,7 +272,7 @@ public:
/// Utility method for getting regions.
LLVM_ATTRIBUTE_RETURNS_NONNULL
const VarRegion* getRegion(const VarDecl *D, const LocationContext *LC) const;
const VarRegion *getRegion(const VarDecl *D, const StackFrame *SF) const;
//==---------------------------------------------------------------------==//
// Binding and retrieving values to/from the environment and symbolic store.
@ -280,16 +280,15 @@ public:
/// Create a new state by binding the value \p V to the expression \p E in
/// the state's environment.
[[nodiscard]] ProgramStateRef BindExpr(const Expr *E,
const LocationContext *LCtx, SVal V,
bool Invalidate = true) const;
[[nodiscard]] ProgramStateRef BindExpr(const Expr *E, const StackFrame *SF,
SVal V, bool Invalidate = true) const;
[[nodiscard]] ProgramStateRef bindLoc(Loc location, SVal V,
const LocationContext *LCtx,
const StackFrame *SF,
bool notifyChanges = true) const;
[[nodiscard]] ProgramStateRef bindLoc(SVal location, SVal V,
const LocationContext *LCtx) const;
const StackFrame *SF) const;
/// Initializes the region of memory represented by \p loc with an initial
/// value. Once initialized, all values loaded from any sub-regions of that
@ -297,13 +296,13 @@ public:
/// This method should not be used on regions that are already initialized.
/// If you need to indicate that memory contents have suddenly become unknown
/// within a certain region of memory, consider invalidateRegions().
[[nodiscard]] ProgramStateRef
bindDefaultInitial(SVal loc, SVal V, const LocationContext *LCtx) const;
[[nodiscard]] ProgramStateRef bindDefaultInitial(SVal loc, SVal V,
const StackFrame *SF) const;
/// Performs C++ zero-initialization procedure on the region of memory
/// represented by \p loc.
[[nodiscard]] ProgramStateRef
bindDefaultZero(SVal loc, const LocationContext *LCtx) const;
[[nodiscard]] ProgramStateRef bindDefaultZero(SVal loc,
const StackFrame *SF) const;
[[nodiscard]] ProgramStateRef killBinding(Loc LV) const;
@ -328,17 +327,15 @@ public:
/// the call and should be considered directly invalidated.
/// \param ITraits information about special handling for particular regions
/// or symbols.
[[nodiscard]] ProgramStateRef
invalidateRegions(ArrayRef<const MemRegion *> Regions,
ConstCFGElementRef Elem, unsigned BlockCount,
const LocationContext *LCtx, bool CausesPointerEscape,
InvalidatedSymbols *IS = nullptr,
const CallEvent *Call = nullptr,
RegionAndSymbolInvalidationTraits *ITraits = nullptr) const;
[[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;
[[nodiscard]] ProgramStateRef
invalidateRegions(ArrayRef<SVal> Values, ConstCFGElementRef Elem,
unsigned BlockCount, const LocationContext *LCtx,
unsigned BlockCount, const StackFrame *SF,
bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr,
const CallEvent *Call = nullptr,
RegionAndSymbolInvalidationTraits *ITraits = nullptr) const;
@ -349,7 +346,7 @@ public:
enterStackFrame(const CallEvent &Call, const StackFrame *CalleeSF) const;
/// Return the value of 'self' if available in the given context.
SVal getSelfSVal(const LocationContext *LC) const;
SVal getSelfSVal(const StackFrame *SF) const;
/// Get the lvalue for a base class object reference.
Loc getLValue(const CXXBaseSpecifier &BaseSpec, const SubRegion *Super) const;
@ -359,10 +356,9 @@ public:
bool IsVirtual) const;
/// Get the lvalue for a variable reference.
Loc getLValue(const VarDecl *D, const LocationContext *LC) const;
Loc getLValue(const VarDecl *D, const StackFrame *SF) const;
Loc getLValue(const CompoundLiteralExpr *literal,
const LocationContext *LC) const;
Loc getLValue(const CompoundLiteralExpr *literal, const StackFrame *SF) const;
/// Get the lvalue for an ivar reference.
SVal getLValue(const ObjCIvarDecl *decl, SVal base) const;
@ -377,9 +373,9 @@ public:
SVal getLValue(QualType ElementType, SVal Idx, SVal Base) const;
/// Returns the SVal bound to the expression \p E in the state's environment.
SVal getSVal(const Expr *E, const LocationContext *LCtx) const;
SVal getSVal(const Expr *E, const StackFrame *SF) const;
SVal getSValAsScalarOrLoc(const Expr *E, const LocationContext *LCtx) const;
SVal getSValAsScalarOrLoc(const Expr *E, const StackFrame *SF) const;
/// Return the value bound to the specified location.
/// Returns UnknownVal() if none found.
@ -477,11 +473,11 @@ public:
}
// Pretty-printing.
void printJson(raw_ostream &Out, const LocationContext *LCtx = nullptr,
void printJson(raw_ostream &Out, const StackFrame *SF = nullptr,
const char *NL = "\n", unsigned int Space = 0,
bool IsDot = false) const;
void printDOT(raw_ostream &Out, const LocationContext *LCtx = nullptr,
void printDOT(raw_ostream &Out, const StackFrame *SF = nullptr,
unsigned int Space = 0) const;
void dump() const;
@ -540,7 +536,7 @@ public:
~ProgramStateManager();
ProgramStateRef getInitialState(const LocationContext *InitLoc);
ProgramStateRef getInitialState(const StackFrame *InitSF);
ASTContext &getContext() { return svalBuilder->getContext(); }
const ASTContext &getContext() const { return svalBuilder->getContext(); }
@ -698,10 +694,9 @@ inline ConstraintManager &ProgramState::getConstraintManager() const {
return stateMgr->getConstraintManager();
}
inline const VarRegion* ProgramState::getRegion(const VarDecl *D,
const LocationContext *LC) const
{
return getStateManager().getRegionManager().getVarRegion(D, LC);
inline const VarRegion *ProgramState::getRegion(const VarDecl *D,
const StackFrame *SF) const {
return getStateManager().getRegionManager().getVarRegion(D, SF);
}
inline ProgramStateRef ProgramState::assume(DefinedOrUnknownSVal Cond,
@ -747,9 +742,10 @@ ProgramState::assumeInclusiveRange(DefinedOrUnknownSVal Val,
this, Val.castAs<NonLoc>(), From, To);
}
inline ProgramStateRef ProgramState::bindLoc(SVal LV, SVal V, const LocationContext *LCtx) const {
inline ProgramStateRef ProgramState::bindLoc(SVal LV, SVal V,
const StackFrame *SF) const {
if (std::optional<Loc> L = LV.getAs<Loc>())
return bindLoc(*L, V, LCtx);
return bindLoc(*L, V, SF);
return this;
}
@ -770,13 +766,13 @@ inline Loc ProgramState::getLValue(const CXXRecordDecl *BaseClass,
}
inline Loc ProgramState::getLValue(const VarDecl *VD,
const LocationContext *LC) const {
return getStateManager().StoreMgr->getLValueVar(VD, LC);
const StackFrame *SF) const {
return getStateManager().StoreMgr->getLValueVar(VD, SF);
}
inline Loc ProgramState::getLValue(const CompoundLiteralExpr *literal,
const LocationContext *LC) const {
return getStateManager().StoreMgr->getLValueCompoundLiteral(literal, LC);
const StackFrame *SF) const {
return getStateManager().StoreMgr->getLValueCompoundLiteral(literal, SF);
}
inline SVal ProgramState::getLValue(const ObjCIvarDecl *D, SVal Base) const {
@ -789,17 +785,15 @@ inline SVal ProgramState::getLValue(QualType ElementType, SVal Idx, SVal Base) c
return UnknownVal();
}
inline SVal ProgramState::getSVal(const Expr *E,
const LocationContext *LCtx) const {
return Env.getSVal(EnvironmentEntry(E, LCtx), *getStateManager().svalBuilder);
inline SVal ProgramState::getSVal(const Expr *E, const StackFrame *SF) const {
return Env.getSVal(EnvironmentEntry(E, SF), *getStateManager().svalBuilder);
}
inline SVal
ProgramState::getSValAsScalarOrLoc(const Expr *E,
const LocationContext *LCtx) const {
inline SVal ProgramState::getSValAsScalarOrLoc(const Expr *E,
const StackFrame *SF) const {
QualType T = E->getType();
if (E->isGLValue() || Loc::isLocType(T) || T->isIntegralOrEnumerationType())
return getSVal(E, LCtx);
return getSVal(E, SF);
return UnknownVal();
}

View file

@ -41,7 +41,6 @@ class CXXMethodDecl;
class CXXRecordDecl;
class DeclaratorDecl;
class FunctionDecl;
class LocationContext;
class StackFrame;
class Stmt;
@ -173,10 +172,10 @@ public:
// Forwarding methods to SymbolManager.
const SymbolConjured *conjureSymbol(ConstCFGElementRef Elem,
const LocationContext *LCtx,
QualType type, unsigned visitCount,
const StackFrame *SF, QualType type,
unsigned visitCount,
const void *symbolTag = nullptr) {
return SymMgr.conjureSymbol(Elem, LCtx, type, visitCount, symbolTag);
return SymMgr.conjureSymbol(Elem, SF, type, visitCount, symbolTag);
}
/// Construct an SVal representing '0' for the specified type.
@ -193,15 +192,14 @@ public:
/// conjured symbols should be used sparingly.
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag,
ConstCFGElementRef elem,
const LocationContext *LCtx,
unsigned count);
const StackFrame *SF, unsigned count);
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag,
ConstCFGElementRef elem,
const LocationContext *LCtx,
QualType type, unsigned count);
const StackFrame *SF, QualType type,
unsigned count);
DefinedOrUnknownSVal conjureSymbolVal(ConstCFGElementRef elem,
const LocationContext *LCtx,
QualType type, unsigned visitCount);
const StackFrame *SF, QualType type,
unsigned visitCount);
DefinedOrUnknownSVal conjureSymbolVal(const CallEvent &call, QualType type,
unsigned visitCount,
const void *symbolTag = nullptr);
@ -211,25 +209,23 @@ public:
/// Conjure a symbol representing heap allocated memory region.
DefinedSVal getConjuredHeapSymbolVal(ConstCFGElementRef elem,
const LocationContext *LCtx,
QualType type, unsigned Count);
const StackFrame *SF, QualType type,
unsigned Count);
/// Create an SVal representing the result of an alloca()-like call, that is,
/// an AllocaRegion on the stack.
///
/// After calling this function, it's a good idea to set the extent of the
/// returned AllocaRegion.
loc::MemRegionVal getAllocaRegionVal(const Expr *E,
const LocationContext *LCtx,
loc::MemRegionVal getAllocaRegionVal(const Expr *E, const StackFrame *SF,
unsigned Count);
DefinedOrUnknownSVal getDerivedRegionValueSymbolVal(
SymbolRef parentSymbol, const TypedValueRegion *region);
DefinedSVal getMetadataSymbolVal(const void *symbolTag,
const MemRegion *region,
const Expr *expr, QualType type,
const LocationContext *LCtx,
const MemRegion *region, const Expr *expr,
QualType type, const StackFrame *SF,
unsigned count);
DefinedSVal getMemberPointer(const NamedDecl *ND);
@ -237,8 +233,7 @@ public:
DefinedSVal getFunctionPointer(const FunctionDecl *func);
DefinedSVal getBlockPointer(const BlockDecl *block, CanQualType locTy,
const LocationContext *locContext,
unsigned blockCount);
const StackFrame *SF, unsigned blockCount);
/// Returns the value of \p E, if it can be determined in a non-path-sensitive
/// manner.

View file

@ -37,7 +37,6 @@ class CompoundLiteralExpr;
class CXXBasePath;
class Decl;
class Expr;
class LocationContext;
class ObjCIvarDecl;
class StackFrame;
@ -132,7 +131,7 @@ public:
/// getInitialStore - Returns the initial "empty" store representing the
/// value bindings upon entry to an analyzed function.
virtual StoreRef getInitialStore(const LocationContext *InitLoc) = 0;
virtual StoreRef getInitialStore(const StackFrame *InitSF) = 0;
/// getRegionManager - Returns the internal RegionManager object that is
/// used to query and manipulate MemRegion objects.
@ -140,13 +139,13 @@ public:
SValBuilder& getSValBuilder() { return svalBuilder; }
virtual Loc getLValueVar(const VarDecl *VD, const LocationContext *LC) {
return svalBuilder.makeLoc(MRMgr.getVarRegion(VD, LC));
virtual Loc getLValueVar(const VarDecl *VD, const StackFrame *SF) {
return svalBuilder.makeLoc(MRMgr.getVarRegion(VD, SF));
}
Loc getLValueCompoundLiteral(const CompoundLiteralExpr *CL,
const LocationContext *LC) {
return loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL, LC));
const StackFrame *SF) {
return loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL, SF));
}
virtual SVal getLValueIvar(const ObjCIvarDecl *decl, SVal base);
@ -242,7 +241,7 @@ public:
/// information will not be used.
virtual StoreRef invalidateRegions(
Store store, ArrayRef<SVal> Values, ConstCFGElementRef Elem,
unsigned Count, const LocationContext *LCtx, const CallEvent *Call,
unsigned Count, const StackFrame *SF, const CallEvent *Call,
InvalidatedSymbols &IS, RegionAndSymbolInvalidationTraits &ITraits,
InvalidatedRegions *TopLevelRegions, InvalidatedRegions *Invalidated) = 0;

View file

@ -83,16 +83,15 @@ class SymbolConjured : public SymbolData {
ConstCFGElementRef Elem;
QualType T;
unsigned Count;
const LocationContext *LCtx;
const StackFrame *SF;
const void *SymbolTag;
friend class SymExprAllocator;
SymbolConjured(SymbolID sym, ConstCFGElementRef elem,
const LocationContext *lctx, QualType t, unsigned count,
const void *symbolTag)
: SymbolData(ClassKind, sym), Elem(elem), T(t), Count(count), LCtx(lctx),
SymbolConjured(SymbolID sym, ConstCFGElementRef elem, const StackFrame *SF,
QualType t, unsigned count, const void *symbolTag)
: SymbolData(ClassKind, sym), Elem(elem), T(t), Count(count), SF(SF),
SymbolTag(symbolTag) {
assert(lctx);
assert(SF);
assert(isValidTypeForSymbol(t));
}
@ -113,18 +112,18 @@ public:
void dumpToStream(raw_ostream &os) const override;
static void Profile(llvm::FoldingSetNodeID &profile, ConstCFGElementRef Elem,
const LocationContext *LCtx, QualType T, unsigned Count,
const StackFrame *SF, QualType T, unsigned Count,
const void *SymbolTag) {
profile.AddInteger((unsigned)ClassKind);
profile.Add(Elem);
profile.AddPointer(LCtx);
profile.AddPointer(SF);
profile.Add(T);
profile.AddInteger(Count);
profile.AddPointer(SymbolTag);
}
void Profile(llvm::FoldingSetNodeID& profile) override {
Profile(profile, Elem, LCtx, T, Count, SymbolTag);
Profile(profile, Elem, SF, T, Count, SymbolTag);
}
// Implement isa<T> support.
@ -222,7 +221,7 @@ class SymbolMetadata : public SymbolData {
const MemRegion* R;
const Stmt *S;
QualType T;
const LocationContext *LCtx;
const StackFrame *SF;
/// Count can be used to differentiate regions corresponding to
/// different loop iterations, thus, making the symbol path-dependent.
unsigned Count;
@ -230,13 +229,13 @@ class SymbolMetadata : public SymbolData {
friend class SymExprAllocator;
SymbolMetadata(SymbolID sym, const MemRegion *r, const Stmt *s, QualType t,
const LocationContext *LCtx, unsigned count, const void *tag)
: SymbolData(ClassKind, sym), R(r), S(s), T(t), LCtx(LCtx), Count(count),
const StackFrame *SF, unsigned count, const void *tag)
: SymbolData(ClassKind, sym), R(r), S(s), T(t), SF(SF), Count(count),
Tag(tag) {
assert(r);
assert(s);
assert(isValidTypeForSymbol(t));
assert(LCtx);
assert(SF);
assert(tag);
}
@ -248,7 +247,7 @@ class SymbolMetadata : public SymbolData {
const Stmt *getStmt() const { return S; }
LLVM_ATTRIBUTE_RETURNS_NONNULL
const LocationContext *getLocationContext() const { return LCtx; }
const StackFrame *getStackFrame() const { return SF; }
unsigned getCount() const { return Count; }
@ -262,19 +261,19 @@ class SymbolMetadata : public SymbolData {
void dumpToStream(raw_ostream &os) const override;
static void Profile(llvm::FoldingSetNodeID &profile, const MemRegion *R,
const Stmt *S, QualType T, const LocationContext *LCtx,
const Stmt *S, QualType T, const StackFrame *SF,
unsigned Count, const void *Tag) {
profile.AddInteger((unsigned)ClassKind);
profile.AddPointer(R);
profile.AddPointer(S);
profile.Add(T);
profile.AddPointer(LCtx);
profile.AddPointer(SF);
profile.AddInteger(Count);
profile.AddPointer(Tag);
}
void Profile(llvm::FoldingSetNodeID& profile) override {
Profile(profile, R, S, T, LCtx, Count, Tag);
Profile(profile, R, S, T, SF, Count, Tag);
}
// Implement isa<T> support.
@ -535,11 +534,11 @@ public:
const SymExprT *acquire(Args &&...args);
const SymbolConjured *conjureSymbol(ConstCFGElementRef Elem,
const LocationContext *LCtx, QualType T,
const StackFrame *SF, QualType T,
unsigned VisitCount,
const void *SymbolTag = nullptr) {
return acquire<SymbolConjured>(Elem, LCtx, T, VisitCount, SymbolTag);
return acquire<SymbolConjured>(Elem, SF, T, VisitCount, SymbolTag);
}
QualType getType(const SymExpr *SE) const {
@ -586,22 +585,21 @@ class SymbolReaper {
public:
/// Construct a reaper object, which removes everything which is not
/// live before we execute statement s in the given location context.
/// live before we execute statements in the given stack frame.
///
/// If the statement is NULL, everything is this and parent contexts is
/// If the statement is NULL, everything in this and parent stack frames are
/// considered live.
/// If the stack frame context is NULL, everything on stack is considered
/// dead.
/// If the stack frame is NULL, everything on stack is considered dead.
SymbolReaper(const StackFrame *SF, const Stmt *s, SymbolManager &symmgr,
StoreManager &storeMgr)
: SF(SF), Loc(s), SymMgr(symmgr), reapedStore(nullptr, storeMgr) {}
/// It might return null.
const LocationContext *getLocationContext() const { return SF; }
const StackFrame *getStackFrame() const { return SF; }
bool isLive(SymbolRef sym);
bool isLiveRegion(const MemRegion *region);
bool isLive(const Expr *ExprVal, const LocationContext *LCtx) const;
bool isLive(const Expr *ExprVal, const StackFrame *SF) const;
bool isLive(const VarRegion *VR, bool includeStoreBindings = false) const;
/// Unconditionally marks a symbol as live.

View file

@ -310,11 +310,12 @@ AnalysisDeclContext *AnalysisDeclContextManager::getContext(const Decl *D) {
BodyFarm &AnalysisDeclContextManager::getBodyFarm() { return FunctionBodyFarm; }
const StackFrame *AnalysisDeclContext::getStackFrame(
const LocationContext *ParentLC, const void *Data, const Expr *E,
const CFGBlock *Blk, unsigned BlockCount, unsigned Index) {
return getLocationContextManager().getStackFrame(this, ParentLC, Data, E, Blk,
BlockCount, Index);
const StackFrame *
AnalysisDeclContext::getStackFrame(const StackFrame *ParentSF, const void *Data,
const Expr *E, const CFGBlock *Blk,
unsigned BlockCount, unsigned Index) {
return getStackFrameManager().getStackFrame(this, ParentSF, Data, E, Blk,
BlockCount, Index);
}
bool AnalysisDeclContext::isInStdNamespace(const Decl *D) {
@ -385,78 +386,51 @@ std::string AnalysisDeclContext::getFunctionName(const Decl *D) {
return Str;
}
LocationContextManager &AnalysisDeclContext::getLocationContextManager() {
assert(
ADCMgr &&
"Cannot create LocationContexts without an AnalysisDeclContextManager!");
return ADCMgr->getLocationContextManager();
StackFrameManager &AnalysisDeclContext::getStackFrameManager() {
assert(ADCMgr &&
"Cannot create StackFrames without an AnalysisDeclContextManager!");
return ADCMgr->getStackFrameManager();
}
//===----------------------------------------------------------------------===//
// FoldingSet profiling.
//===----------------------------------------------------------------------===//
void LocationContext::ProfileCommon(llvm::FoldingSetNodeID &ID,
ContextKind ck,
AnalysisDeclContext *ctx,
const LocationContext *parent,
const void *data) {
ID.AddInteger(ck);
ID.AddPointer(ctx);
ID.AddPointer(parent);
ID.AddPointer(data);
}
void StackFrame::Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getAnalysisDeclContext(), getParent(), Data, CallSite, Block,
BlockCount, Index);
}
//===----------------------------------------------------------------------===//
// LocationContext creation.
// StackFrame creation.
//===----------------------------------------------------------------------===//
const StackFrame *LocationContextManager::getStackFrame(
AnalysisDeclContext *Ctx, const LocationContext *Parent, const void *Data,
const Expr *E, const CFGBlock *Blk, unsigned BlockCount, unsigned StmtIdx) {
const StackFrame *StackFrameManager::getStackFrame(
AnalysisDeclContext *Ctx, const StackFrame *Parent, const void *Data,
const Expr *E, const CFGBlock *B, unsigned BlockCount, unsigned StmtIdx) {
llvm::FoldingSetNodeID ID;
StackFrame::Profile(ID, Ctx, Parent, Data, E, Blk, BlockCount, StmtIdx);
StackFrame::Profile(ID, Ctx, Parent, Data, E, B, BlockCount, StmtIdx);
void *InsertPos;
auto *L =
cast_or_null<StackFrame>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
if (!L) {
L = new StackFrame(Ctx, Parent, Data, E, Blk, BlockCount, StmtIdx, ++NewID);
Contexts.InsertNode(L, InsertPos);
StackFrame *SF = Frames.FindNodeOrInsertPos(ID, InsertPos);
if (!SF) {
SF = new StackFrame(Ctx, Parent, Data, E, B, BlockCount, StmtIdx, ++NewID);
Frames.InsertNode(SF, InsertPos);
}
return L;
return SF;
}
//===----------------------------------------------------------------------===//
// LocationContext methods.
// StackFrame methods.
//===----------------------------------------------------------------------===//
const StackFrame *LocationContext::getStackFrame() const {
const LocationContext *LC = this;
while (LC) {
if (const auto *SF = dyn_cast<StackFrame>(LC))
return SF;
LC = LC->getParent();
}
return nullptr;
}
bool LocationContext::inTopFrame() const {
return getStackFrame()->inTopFrame();
}
bool LocationContext::isParentOf(const LocationContext *LC) const {
bool StackFrame::isParentOf(const StackFrame *SF) const {
do {
const LocationContext *Parent = LC->getParent();
const StackFrame *Parent = SF->getParent();
if (Parent == this)
return true;
else
LC = Parent;
} while (LC);
SF = Parent;
} while (SF);
return false;
}
@ -469,7 +443,7 @@ static void printLocation(raw_ostream &Out, const SourceManager &SM,
Loc.print(Out, SM);
}
void LocationContext::dumpStack(raw_ostream &Out) const {
void StackFrame::dumpStack(raw_ostream &Out) const {
ASTContext &Ctx = getAnalysisDeclContext()->getASTContext();
PrintingPolicy PP(Ctx.getLangOpts());
PP.TerseOutput = 1;
@ -478,29 +452,24 @@ void LocationContext::dumpStack(raw_ostream &Out) const {
getAnalysisDeclContext()->getASTContext().getSourceManager();
unsigned Frame = 0;
for (const LocationContext *LCtx = this; LCtx; LCtx = LCtx->getParent()) {
switch (LCtx->getKind()) {
case StackFrameKind:
Out << "\t#" << Frame << ' ';
++Frame;
if (const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl()))
Out << "Calling " << AnalysisDeclContext::getFunctionName(D);
else
Out << "Calling anonymous code";
if (const Expr *E = cast<StackFrame>(LCtx)->getCallSite()) {
Out << " at line ";
printLocation(Out, SM, E->getBeginLoc());
}
break;
for (const StackFrame *SF = this; SF; SF = SF->getParent()) {
Out << "\t#" << Frame << ' ';
++Frame;
if (const auto *D = dyn_cast<NamedDecl>(SF->getDecl()))
Out << "Calling " << AnalysisDeclContext::getFunctionName(D);
else
Out << "Calling anonymous code";
if (const Expr *E = SF->getCallSite()) {
Out << " at line ";
printLocation(Out, SM, E->getBeginLoc());
}
Out << '\n';
}
}
void LocationContext::printJson(raw_ostream &Out, const char *NL,
unsigned int Space, bool IsDot,
std::function<void(const LocationContext *)>
printMoreInfoPerContext) const {
void StackFrame::printJson(
raw_ostream &Out, const char *NL, unsigned int Space, bool IsDot,
std::function<void(const StackFrame *)> printMoreInfoPerStackFrame) const {
ASTContext &Ctx = getAnalysisDeclContext()->getASTContext();
PrintingPolicy PP(Ctx.getLangOpts());
PP.TerseOutput = 1;
@ -509,39 +478,35 @@ void LocationContext::printJson(raw_ostream &Out, const char *NL,
getAnalysisDeclContext()->getASTContext().getSourceManager();
unsigned Frame = 0;
for (const LocationContext *LCtx = this; LCtx; LCtx = LCtx->getParent()) {
for (const StackFrame *SF = this; SF; SF = SF->getParent()) {
Indent(Out, Space, IsDot)
<< "{ \"lctx_id\": " << LCtx->getID() << ", \"location_context\": \"";
switch (LCtx->getKind()) {
case StackFrameKind:
Out << '#' << Frame << " Call\", \"calling\": \"";
++Frame;
if (const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl()))
Out << D->getQualifiedNameAsString();
else
Out << "anonymous code";
<< "{ \"lctx_id\": " << SF->getID() << ", \"location_context\": \"";
Out << '#' << Frame << " Call\", \"calling\": \"";
++Frame;
if (const auto *D = dyn_cast<NamedDecl>(SF->getDecl()))
Out << D->getQualifiedNameAsString();
else
Out << "anonymous code";
Out << "\", \"location\": ";
if (const Expr *E = cast<StackFrame>(LCtx)->getCallSite()) {
printSourceLocationAsJson(Out, E->getBeginLoc(), SM);
} else {
Out << "null";
}
Out << ", \"items\": ";
break;
Out << "\", \"location\": ";
if (const Expr *E = SF->getCallSite()) {
printSourceLocationAsJson(Out, E->getBeginLoc(), SM);
} else {
Out << "null";
}
printMoreInfoPerContext(LCtx);
Out << ", \"items\": ";
printMoreInfoPerStackFrame(SF);
Out << '}';
if (LCtx->getParent())
if (SF->getParent())
Out << ',';
Out << NL;
}
}
LLVM_DUMP_METHOD void LocationContext::dump() const { printJson(llvm::errs()); }
LLVM_DUMP_METHOD void StackFrame::dump() const { printJson(llvm::errs()); }
//===----------------------------------------------------------------------===//
// Lazily generated map to query the external variables referenced by a Block.
@ -649,18 +614,15 @@ AnalysisDeclContext::~AnalysisDeclContext() {
delete (ManagedAnalysisMap*) ManagedAnalyses;
}
LocationContext::~LocationContext() = default;
StackFrameManager::~StackFrameManager() { clear(); }
LocationContextManager::~LocationContextManager() {
clear();
}
void LocationContextManager::clear() {
for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(),
E = Contexts.end(); I != E; ) {
LocationContext *LC = &*I;
void StackFrameManager::clear() {
for (llvm::FoldingSet<StackFrame>::iterator I = Frames.begin(),
E = Frames.end();
I != E;) {
StackFrame *SF = &*I;
++I;
delete LC;
delete SF;
}
Contexts.clear();
Frames.clear();
}

View file

@ -470,20 +470,21 @@ PathDiagnosticConsumer::FilesMade::getFiles(const PathDiagnostic &PD) {
//===----------------------------------------------------------------------===//
SourceLocation PathDiagnosticLocation::getValidSourceLocation(
const Stmt *S, LocationOrAnalysisDeclContext LAC, bool UseEndOfStatement) {
const Stmt *S, StackFrameOrAnalysisDeclContext SFAC,
bool UseEndOfStatement) {
SourceLocation L = UseEndOfStatement ? S->getEndLoc() : S->getBeginLoc();
assert(!LAC.isNull() &&
"A valid LocationContext or AnalysisDeclContext should be passed to "
assert(!SFAC.isNull() &&
"A valid StackFrame or AnalysisDeclContext should be passed to "
"PathDiagnosticLocation upon creation.");
// S might be a temporary statement that does not have a location in the
// source code, so find an enclosing statement and use its location.
if (!L.isValid()) {
AnalysisDeclContext *ADC;
if (auto *LC = dyn_cast<const LocationContext *>(LAC))
ADC = LC->getAnalysisDeclContext();
if (auto *SF = dyn_cast<const StackFrame *>(SFAC))
ADC = SF->getAnalysisDeclContext();
else
ADC = cast<AnalysisDeclContext *>(LAC);
ADC = cast<AnalysisDeclContext *>(SFAC);
ParentMap &PM = ADC->getParentMap();
@ -513,9 +514,9 @@ SourceLocation PathDiagnosticLocation::getValidSourceLocation(
return L;
}
static PathDiagnosticLocation
getLocationForCaller(const StackFrame *SF, const LocationContext *CallerCtx,
const SourceManager &SM) {
static PathDiagnosticLocation getLocationForCaller(const StackFrame *SF,
const StackFrame *CallerSF,
const SourceManager &SM) {
const CFGBlock &Block = *SF->getCallSiteBlock();
CFGElement Source = Block[SF->getIndex()];
@ -523,32 +524,32 @@ getLocationForCaller(const StackFrame *SF, const LocationContext *CallerCtx,
case CFGElement::Statement:
case CFGElement::Constructor:
case CFGElement::CXXRecordTypedCall:
return PathDiagnosticLocation(Source.castAs<CFGStmt>().getStmt(),
SM, CallerCtx);
return PathDiagnosticLocation(Source.castAs<CFGStmt>().getStmt(), SM,
CallerSF);
case CFGElement::Initializer: {
const CFGInitializer &Init = Source.castAs<CFGInitializer>();
return PathDiagnosticLocation(Init.getInitializer()->getInit(),
SM, CallerCtx);
return PathDiagnosticLocation(Init.getInitializer()->getInit(), SM,
CallerSF);
}
case CFGElement::AutomaticObjectDtor: {
const CFGAutomaticObjDtor &Dtor = Source.castAs<CFGAutomaticObjDtor>();
return PathDiagnosticLocation::createEnd(Dtor.getTriggerStmt(),
SM, CallerCtx);
return PathDiagnosticLocation::createEnd(Dtor.getTriggerStmt(), SM,
CallerSF);
}
case CFGElement::DeleteDtor: {
const CFGDeleteDtor &Dtor = Source.castAs<CFGDeleteDtor>();
return PathDiagnosticLocation(Dtor.getDeleteExpr(), SM, CallerCtx);
return PathDiagnosticLocation(Dtor.getDeleteExpr(), SM, CallerSF);
}
case CFGElement::BaseDtor:
case CFGElement::MemberDtor: {
const AnalysisDeclContext *CallerInfo = CallerCtx->getAnalysisDeclContext();
const AnalysisDeclContext *CallerInfo = CallerSF->getAnalysisDeclContext();
if (const Stmt *CallerBody = CallerInfo->getBody())
return PathDiagnosticLocation::createEnd(CallerBody, SM, CallerCtx);
return PathDiagnosticLocation::createEnd(CallerBody, SM, CallerSF);
return PathDiagnosticLocation::create(CallerInfo->getDecl(), SM);
}
case CFGElement::NewAllocator: {
const CFGNewAllocator &Alloc = Source.castAs<CFGNewAllocator>();
return PathDiagnosticLocation(Alloc.getAllocatorExpr(), SM, CallerCtx);
return PathDiagnosticLocation(Alloc.getAllocatorExpr(), SM, CallerSF);
}
case CFGElement::TemporaryDtor: {
// Temporary destructors are for temporaries. They die immediately at around
@ -556,7 +557,7 @@ getLocationForCaller(const StackFrame *SF, const LocationContext *CallerCtx,
// they'd be dealt with via an AutomaticObjectDtor instead.
const auto &Dtor = Source.castAs<CFGTemporaryDtor>();
return PathDiagnosticLocation::createEnd(Dtor.getBindTemporaryExpr(), SM,
CallerCtx);
CallerSF);
}
case CFGElement::ScopeBegin:
case CFGElement::ScopeEnd:
@ -578,21 +579,19 @@ PathDiagnosticLocation::createBegin(const Decl *D,
}
PathDiagnosticLocation
PathDiagnosticLocation::createBegin(const Stmt *S,
const SourceManager &SM,
LocationOrAnalysisDeclContext LAC) {
PathDiagnosticLocation::createBegin(const Stmt *S, const SourceManager &SM,
StackFrameOrAnalysisDeclContext SFAC) {
assert(S && "Statement cannot be null");
return PathDiagnosticLocation(getValidSourceLocation(S, LAC),
SM, SingleLocK);
return PathDiagnosticLocation(getValidSourceLocation(S, SFAC), SM,
SingleLocK);
}
PathDiagnosticLocation
PathDiagnosticLocation::createEnd(const Stmt *S,
const SourceManager &SM,
LocationOrAnalysisDeclContext LAC) {
PathDiagnosticLocation::createEnd(const Stmt *S, const SourceManager &SM,
StackFrameOrAnalysisDeclContext SFAC) {
if (const auto *CS = dyn_cast<CompoundStmt>(S))
return createEndBrace(CS, SM);
return PathDiagnosticLocation(getValidSourceLocation(S, LAC, /*End=*/true),
return PathDiagnosticLocation(getValidSourceLocation(S, SFAC, /*End=*/true),
SM, SingleLocK);
}
@ -638,10 +637,10 @@ PathDiagnosticLocation::createEndBrace(const CompoundStmt *CS,
}
PathDiagnosticLocation
PathDiagnosticLocation::createDeclBegin(const LocationContext *LC,
PathDiagnosticLocation::createDeclBegin(const StackFrame *SF,
const SourceManager &SM) {
// FIXME: Should handle CXXTryStmt if analyser starts supporting C++.
if (const auto *CS = dyn_cast_or_null<CompoundStmt>(LC->getDecl()->getBody()))
if (const auto *CS = dyn_cast_or_null<CompoundStmt>(SF->getDecl()->getBody()))
if (!CS->body_empty()) {
SourceLocation Loc = (*CS->body_begin())->getBeginLoc();
return PathDiagnosticLocation(Loc, SM, SingleLocK);
@ -651,9 +650,9 @@ PathDiagnosticLocation::createDeclBegin(const LocationContext *LC,
}
PathDiagnosticLocation
PathDiagnosticLocation::createDeclEnd(const LocationContext *LC,
PathDiagnosticLocation::createDeclEnd(const StackFrame *SF,
const SourceManager &SM) {
SourceLocation L = LC->getDecl()->getBodyRBrace();
SourceLocation L = SF->getDecl()->getBodyRBrace();
return PathDiagnosticLocation(L, SM, SingleLocK);
}
@ -666,8 +665,8 @@ PathDiagnosticLocation::create(const ProgramPoint& P,
if (BSrc->getTerminator().isVirtualBaseBranch()) {
// TODO: VirtualBaseBranches should also appear for destructors.
// In this case we should put the diagnostic at the end of decl.
return PathDiagnosticLocation::createBegin(
P.getLocationContext()->getDecl(), SMng);
return PathDiagnosticLocation::createBegin(P.getStackFrame()->getDecl(),
SMng);
} else {
S = BSrc->getTerminatorCondition();
@ -677,14 +676,14 @@ PathDiagnosticLocation::create(const ProgramPoint& P,
// the beginning of a function), use the function's declaration instead.
assert(BSrc == &BSrc->getParent()->getEntry() && "CFGBlock has no "
"TerminatorCondition and is not the enrty block of the CFG");
return PathDiagnosticLocation::createBegin(
P.getLocationContext()->getDecl(), SMng);
return PathDiagnosticLocation::createBegin(P.getStackFrame()->getDecl(),
SMng);
}
}
} else if (std::optional<StmtPoint> SP = P.getAs<StmtPoint>()) {
S = SP->getStmt();
if (P.getAs<PostStmtPurgeDeadSymbols>())
return PathDiagnosticLocation::createEnd(S, SMng, P.getLocationContext());
return PathDiagnosticLocation::createEnd(S, SMng, P.getStackFrame());
} else if (std::optional<PostInitializer> PIP = P.getAs<PostInitializer>()) {
return PathDiagnosticLocation(PIP->getInitializer()->getSourceLocation(),
SMng);
@ -694,19 +693,17 @@ PathDiagnosticLocation::create(const ProgramPoint& P,
P.getAs<PostImplicitCall>()) {
return PathDiagnosticLocation(PIE->getLocation(), SMng);
} else if (std::optional<CallEnter> CE = P.getAs<CallEnter>()) {
return getLocationForCaller(CE->getCalleeContext(),
CE->getLocationContext(),
return getLocationForCaller(CE->getCalleeStackFrame(), CE->getStackFrame(),
SMng);
} else if (std::optional<CallExitEnd> CEE = P.getAs<CallExitEnd>()) {
return getLocationForCaller(CEE->getCalleeContext(),
CEE->getLocationContext(),
SMng);
return getLocationForCaller(CEE->getCalleeStackFrame(),
CEE->getStackFrame(), SMng);
} else if (auto CEB = P.getAs<CallExitBegin>()) {
if (const ReturnStmt *RS = CEB->getReturnStmt())
return PathDiagnosticLocation::createBegin(RS, SMng,
CEB->getLocationContext());
CEB->getStackFrame());
return PathDiagnosticLocation(
CEB->getLocationContext()->getDecl()->getSourceRange().getEnd(), SMng);
CEB->getStackFrame()->getDecl()->getSourceRange().getEnd(), SMng);
} else if (std::optional<BlockEntrance> BE = P.getAs<BlockEntrance>()) {
if (std::optional<CFGElement> BlockFront = BE->getFirstElement()) {
if (auto StmtElt = BlockFront->getAs<CFGStmt>()) {
@ -722,13 +719,12 @@ PathDiagnosticLocation::create(const ProgramPoint& P,
BE->getBlock()->getTerminatorStmt()->getBeginLoc(), SMng);
} else if (std::optional<FunctionExitPoint> FE =
P.getAs<FunctionExitPoint>()) {
return PathDiagnosticLocation(FE->getStmt(), SMng,
FE->getLocationContext());
return PathDiagnosticLocation(FE->getStmt(), SMng, FE->getStackFrame());
} else {
llvm_unreachable("Unexpected ProgramPoint");
}
return PathDiagnosticLocation(S, SMng, P.getLocationContext());
return PathDiagnosticLocation(S, SMng, P.getStackFrame());
}
PathDiagnosticLocation PathDiagnosticLocation::createSingleLocation(
@ -737,9 +733,8 @@ PathDiagnosticLocation PathDiagnosticLocation::createSingleLocation(
return PathDiagnosticLocation(L, L.getManager(), SingleLocK);
}
FullSourceLoc
PathDiagnosticLocation::genLocation(SourceLocation L,
LocationOrAnalysisDeclContext LAC) const {
FullSourceLoc PathDiagnosticLocation::genLocation(
SourceLocation L, StackFrameOrAnalysisDeclContext SFAC) const {
assert(isValid());
// Note that we want a 'switch' here so that the compiler can warn us in
// case we add more cases.
@ -751,8 +746,8 @@ FullSourceLoc
// Defensive checking.
if (!S)
break;
return FullSourceLoc(getValidSourceLocation(S, LAC),
const_cast<SourceManager&>(*SM));
return FullSourceLoc(getValidSourceLocation(S, SFAC),
const_cast<SourceManager &>(*SM));
case DeclK:
// Defensive checking.
if (!D)
@ -764,7 +759,7 @@ FullSourceLoc
}
PathDiagnosticRange
PathDiagnosticLocation::genRange(LocationOrAnalysisDeclContext LAC) const {
PathDiagnosticLocation::genRange(StackFrameOrAnalysisDeclContext SFAC) const {
assert(isValid());
// Note that we want a 'switch' here so that the compiler can warn us in
// case we add more cases.
@ -799,7 +794,7 @@ PathDiagnosticRange
case Stmt::BinaryConditionalOperatorClass:
case Stmt::ConditionalOperatorClass:
case Stmt::ObjCForCollectionStmtClass: {
SourceLocation L = getValidSourceLocation(S, LAC);
SourceLocation L = getValidSourceLocation(S, SFAC);
return SourceRange(L, L);
}
}
@ -844,10 +839,9 @@ void PathDiagnosticLocation::flatten() {
std::shared_ptr<PathDiagnosticCallPiece>
PathDiagnosticCallPiece::construct(const CallExitEnd &CE,
const SourceManager &SM) {
const Decl *caller = CE.getLocationContext()->getDecl();
PathDiagnosticLocation pos = getLocationForCaller(CE.getCalleeContext(),
CE.getLocationContext(),
SM);
const Decl *caller = CE.getStackFrame()->getDecl();
PathDiagnosticLocation pos =
getLocationForCaller(CE.getCalleeStackFrame(), CE.getStackFrame(), SM);
return std::shared_ptr<PathDiagnosticCallPiece>(
new PathDiagnosticCallPiece(caller, pos));
}
@ -865,11 +859,11 @@ PathDiagnosticCallPiece::construct(PathPieces &path,
void PathDiagnosticCallPiece::setCallee(const CallEnter &CE,
const SourceManager &SM) {
const StackFrame *CalleeSF = CE.getCalleeContext();
const StackFrame *CalleeSF = CE.getCalleeStackFrame();
Callee = CalleeSF->getDecl();
callEnterWithin = PathDiagnosticLocation::createBegin(Callee, SM);
callEnter = getLocationForCaller(CalleeSF, CE.getLocationContext(), SM);
callEnter = getLocationForCaller(CalleeSF, CE.getStackFrame(), SM);
// Autosynthesized property accessors are special because we'd never
// pop back up to non-autosynthesized code until we leave them.

View file

@ -21,27 +21,27 @@ using namespace clang;
ProgramPointTag::~ProgramPointTag() {}
ProgramPoint ProgramPoint::getProgramPoint(const Stmt *S, ProgramPoint::Kind K,
const LocationContext *LC,
const ProgramPointTag *tag){
const StackFrame *SF,
const ProgramPointTag *tag) {
switch (K) {
default:
llvm_unreachable("Unhandled ProgramPoint kind");
case ProgramPoint::PreStmtKind:
return PreStmt(S, LC, tag);
return PreStmt(S, SF, tag);
case ProgramPoint::PostStmtKind:
return PostStmt(S, LC, tag);
return PostStmt(S, SF, tag);
case ProgramPoint::PreLoadKind:
return PreLoad(S, LC, tag);
return PreLoad(S, SF, tag);
case ProgramPoint::PostLoadKind:
return PostLoad(S, LC, tag);
return PostLoad(S, SF, tag);
case ProgramPoint::PreStoreKind:
return PreStore(S, LC, tag);
return PreStore(S, SF, tag);
case ProgramPoint::PostLValueKind:
return PostLValue(S, LC, tag);
return PostLValue(S, SF, tag);
case ProgramPoint::PostStmtPurgeDeadSymbolsKind:
return PostStmtPurgeDeadSymbols(S, LC, tag);
return PostStmtPurgeDeadSymbols(S, SF, tag);
case ProgramPoint::PreStmtPurgeDeadSymbolsKind:
return PreStmtPurgeDeadSymbols(S, LC, tag);
return PreStmtPurgeDeadSymbols(S, SF, tag);
}
}
@ -166,7 +166,7 @@ std::optional<SourceLocation> ProgramPoint::getSourceLocation() const {
void ProgramPoint::printJson(llvm::raw_ostream &Out, const char *NL) const {
const ASTContext &Context =
getLocationContext()->getAnalysisDeclContext()->getASTContext();
getStackFrame()->getAnalysisDeclContext()->getASTContext();
const SourceManager &SM = Context.getSourceManager();
const PrintingPolicy &PP = Context.getPrintingPolicy();
const bool AddQuotes = true;
@ -199,7 +199,7 @@ void ProgramPoint::printJson(llvm::raw_ostream &Out, const char *NL) const {
case ProgramPoint::CallEnterKind:
Out << "CallEnter\", \"callee_decl\": \"";
Out << AnalysisDeclContext::getFunctionName(
castAs<CallEnter>().getCalleeContext()->getDecl())
castAs<CallEnter>().getCalleeStackFrame()->getDecl())
<< '\"';
break;
case ProgramPoint::CallExitBeginKind:

View file

@ -200,8 +200,8 @@ public:
checkRegionChanges(ProgramStateRef State,
const InvalidatedSymbols *Invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const LocationContext *LCtx, const CallEvent *Call) const {
ArrayRef<const MemRegion *> Regions, const StackFrame *SF,
const CallEvent *Call) const {
if (isCallbackEnabled(State, "RegionChanges"))
llvm::errs() << "RegionChanges\n";
return State;

View file

@ -44,16 +44,16 @@ void AnalyzerStatsChecker::checkEndAnalysis(ExplodedGraph &G,
const SourceManager &SM = B.getSourceManager();
llvm::SmallPtrSet<const CFGBlock*, 32> reachable;
const LocationContext *LC = Eng.getRootLocationContext();
const StackFrame *RootSF = Eng.getRootStackFrame();
const Decl *D = LC->getDecl();
const Decl *D = RootSF->getDecl();
// Iterate over the exploded graph.
for (const ExplodedNode &N : G.nodes()) {
const ProgramPoint &P = N.getLocation();
// Only check the coverage in the top level function (optimization).
if (D != P.getLocationContext()->getDecl())
if (D != P.getStackFrame()->getDecl())
continue;
if (std::optional<BlockEntrance> BE = P.getAs<BlockEntrance>()) {
@ -63,7 +63,7 @@ void AnalyzerStatsChecker::checkEndAnalysis(ExplodedGraph &G,
}
// Get the CFG and the Decl of this block.
C = LC->getCFG();
C = RootSF->getCFG();
unsigned total = 0, unreachable = 0;
@ -124,7 +124,7 @@ void AnalyzerStatsChecker::checkEndAnalysis(ExplodedGraph &G,
": The analyzer generated a sink at this point";
B.EmitBasicReport(
D, this, "Sink Point", "Internal Statistics", outputI.str(),
PathDiagnosticLocation::createBegin(CS->getStmt(), SM, LC));
PathDiagnosticLocation::createBegin(CS->getStmt(), SM, RootSF));
}
}
}

View file

@ -705,7 +705,7 @@ void ArrayBoundChecker::performCheck(const Expr *E, CheckerContext &C) const {
// nicer to say "tainted index".
const char *OffsetName = "offset";
if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(E))
if (isTainted(State, ASE->getIdx(), C.getLocationContext()))
if (isTainted(State, ASE->getIdx(), C.getStackFrame()))
OffsetName = "index";
Messages Msgs =

View file

@ -876,7 +876,7 @@ static ProgramStateRef checkElementNonNil(CheckerContext &C,
if (!isKnownNonNilCollectionType(FCS->getCollection()->getType()))
return State;
const LocationContext *LCtx = C.getLocationContext();
const StackFrame *SF = C.getStackFrame();
const Stmt *Element = FCS->getElement();
// FIXME: Copied from ExprEngineObjC.
@ -884,9 +884,9 @@ static ProgramStateRef checkElementNonNil(CheckerContext &C,
if (const DeclStmt *DS = dyn_cast<DeclStmt>(Element)) {
const VarDecl *ElemDecl = cast<VarDecl>(DS->getSingleDecl());
assert(ElemDecl->getInit() == nullptr);
ElementLoc = State->getLValue(ElemDecl, LCtx);
ElementLoc = State->getLValue(ElemDecl, SF);
} else if (const auto *E = dyn_cast<Expr>(Element)) {
ElementLoc = State->getSVal(E, LCtx).getAs<Loc>();
ElementLoc = State->getSVal(E, SF).getAs<Loc>();
}
if (!ElementLoc)
@ -966,7 +966,7 @@ void ObjCLoopChecker::checkPostStmt(const ObjCForCollectionStmt *FCS,
ProgramStateRef State = C.getState();
// Check if this is the branch for the end of the loop.
if (!ExprEngine::hasMoreIteration(State, FCS, C.getLocationContext())) {
if (!ExprEngine::hasMoreIteration(State, FCS, C.getStackFrame())) {
if (!alreadyExecutedAtLeastOneLoopIteration(C.getPredecessor(), FCS))
State = assumeCollectionNonEmpty(C, State, FCS, /*Assumption*/false);

View file

@ -180,11 +180,11 @@ ProgramStateRef BuiltinFunctionChecker::initStateAftetBuiltinOverflow(
auto BoolTy = C.getASTContext().BoolTy;
ProgramStateRef NewState =
State->BindExpr(Call.getOriginExpr(), C.getLocationContext(),
State->BindExpr(Call.getOriginExpr(), C.getStackFrame(),
SVB.makeTruthVal(IsOverflow, BoolTy));
if (auto L = Call.getArgSVal(2).getAs<Loc>()) {
NewState = NewState->bindLoc(*L, RetVal, C.getLocationContext());
NewState = NewState->bindLoc(*L, RetVal, C.getStackFrame());
// Propagate taint if any of the arguments were tainted
if (isTainted(State, Arg1) || isTainted(State, Arg2))
@ -255,11 +255,11 @@ bool BuiltinFunctionChecker::evalCall(const CallEvent &Call,
if (!FD)
return false;
const LocationContext *LCtx = C.getLocationContext();
const StackFrame *SF = C.getStackFrame();
const Expr *CE = Call.getOriginExpr();
if (isBuiltinLikeFunction(Call)) {
C.addTransition(state->BindExpr(CE, LCtx, Call.getArgSVal(0)));
C.addTransition(state->BindExpr(CE, SF, Call.getArgSVal(0)));
return true;
}
@ -311,7 +311,7 @@ bool BuiltinFunctionChecker::evalCall(const CallEvent &Call,
// are represented the same way in the analyzer.
assert (Call.getNumArgs() > 0);
SVal Arg = Call.getArgSVal(0);
C.addTransition(state->BindExpr(CE, LCtx, Arg));
C.addTransition(state->BindExpr(CE, SF, Arg));
return true;
}
@ -339,7 +339,7 @@ bool BuiltinFunctionChecker::evalCall(const CallEvent &Call,
V = SVB.makeIntVal(0, CE->getType());
}
C.addTransition(state->BindExpr(CE, LCtx, V));
C.addTransition(state->BindExpr(CE, SF, V));
return true;
}
}

View file

@ -107,12 +107,10 @@ public:
void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
ProgramStateRef
checkRegionChanges(ProgramStateRef state,
const InvalidatedSymbols *,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const LocationContext *LCtx,
const CallEvent *Call) const;
checkRegionChanges(ProgramStateRef state, const InvalidatedSymbols *,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions, const StackFrame *SF,
const CallEvent *Call) const;
using FnCheck = std::function<void(const CStringChecker *, CheckerContext &,
const CallEvent &)>;
@ -687,9 +685,9 @@ ProgramStateRef CStringChecker::CheckOverlap(CheckerContext &C,
return state;
// Get the buffer values and make sure they're known locations.
const LocationContext *LCtx = C.getLocationContext();
SVal firstVal = state->getSVal(First.Expression, LCtx);
SVal secondVal = state->getSVal(Second.Expression, LCtx);
const StackFrame *SF = C.getStackFrame();
SVal firstVal = state->getSVal(First.Expression, SF);
SVal secondVal = state->getSVal(Second.Expression, SF);
std::optional<Loc> firstLoc = firstVal.getAs<Loc>();
if (!firstLoc)
@ -753,7 +751,7 @@ ProgramStateRef CStringChecker::CheckOverlap(CheckerContext &C,
}
// Get the length, and make sure it too is known.
SVal LengthVal = state->getSVal(Size.Expression, LCtx);
SVal LengthVal = state->getSVal(Size.Expression, SF);
std::optional<NonLoc> Length = LengthVal.getAs<NonLoc>();
if (!Length)
return state;
@ -997,10 +995,9 @@ SVal CStringChecker::getCStringLengthForRegion(CheckerContext &C,
// Otherwise, get a new symbol and update the state.
SValBuilder &svalBuilder = C.getSValBuilder();
QualType sizeTy = svalBuilder.getContext().getSizeType();
SVal strLength = svalBuilder.getMetadataSymbolVal(CStringChecker::getTag(),
MR, Ex, sizeTy,
C.getLocationContext(),
C.blockCount());
SVal strLength =
svalBuilder.getMetadataSymbolVal(CStringChecker::getTag(), MR, Ex, sizeTy,
C.getStackFrame(), C.blockCount());
if (!hypothetical) {
if (std::optional<NonLoc> strLn = strLength.getAs<NonLoc>()) {
@ -1299,11 +1296,11 @@ ProgramStateRef CStringChecker::invalidateBufferAux(
}
// Invalidate this region.
const LocationContext *LCtx = C.getPredecessor()->getLocationContext();
const StackFrame *SF = C.getPredecessor()->getStackFrame();
RegionAndSymbolInvalidationTraits ITraits;
bool CausesPointerEscape = InvalidationTraitOperations(ITraits, R);
return State->invalidateRegions(R, Elem, C.blockCount(), LCtx,
return State->invalidateRegions(R, Elem, C.blockCount(), SF,
CausesPointerEscape, nullptr, nullptr,
&ITraits);
}
@ -1403,8 +1400,8 @@ bool CStringChecker::memsetAux(const Expr *DstBuffer, ConstCFGElementRef Elem,
// FIXME: Since there is no perfect way to bind the non-zero character, we
// can only deal with zero value here. In the future, we need to deal with
// the binding of non-zero value in the case of whole region.
State = State->bindDefaultZero(svalBuilder.makeLoc(BR),
C.getLocationContext());
State =
State->bindDefaultZero(svalBuilder.makeLoc(BR), C.getStackFrame());
} else {
// If the destination buffer's extent is not equal to the value of
// third argument, just invalidate buffer.
@ -1420,7 +1417,7 @@ bool CStringChecker::memsetAux(const Expr *DstBuffer, ConstCFGElementRef Elem,
} else if (!StateNullChar && StateNonNullChar) {
SVal NewStrLen = svalBuilder.getMetadataSymbolVal(
CStringChecker::getTag(), MR, DstBuffer, Ctx.getSizeType(),
C.getLocationContext(), C.blockCount());
C.getStackFrame(), C.blockCount());
// If the value of second argument is not zero, then the string length
// is at least the size argument.
@ -1452,8 +1449,8 @@ void CStringChecker::evalCopyCommon(CheckerContext &C, const CallEvent &Call,
CurrentFunctionDescription = "memory copy function";
// See if the size argument is zero.
const LocationContext *LCtx = C.getLocationContext();
SVal sizeVal = state->getSVal(Size.Expression, LCtx);
const StackFrame *SF = C.getStackFrame();
SVal sizeVal = state->getSVal(Size.Expression, SF);
QualType sizeTy = Size.Expression->getType();
ProgramStateRef stateZeroSize, stateNonZeroSize;
@ -1461,13 +1458,12 @@ void CStringChecker::evalCopyCommon(CheckerContext &C, const CallEvent &Call,
assumeZero(C, state, sizeVal, sizeTy);
// Get the value of the Dest.
SVal destVal = state->getSVal(Dest.Expression, LCtx);
SVal destVal = state->getSVal(Dest.Expression, SF);
// If the size is zero, there won't be any actual memory access, so
// just bind the return value to the destination buffer and return.
if (stateZeroSize && !stateNonZeroSize) {
stateZeroSize =
stateZeroSize->BindExpr(Call.getOriginExpr(), LCtx, destVal);
stateZeroSize = stateZeroSize->BindExpr(Call.getOriginExpr(), SF, destVal);
C.addTransition(stateZeroSize);
return;
}
@ -1486,7 +1482,7 @@ void CStringChecker::evalCopyCommon(CheckerContext &C, const CallEvent &Call,
return;
// Get the value of the Src.
SVal srcVal = state->getSVal(Source.Expression, LCtx);
SVal srcVal = state->getSVal(Source.Expression, SF);
// Ensure the source is not null. If it is NULL there will be a
// NULL pointer dereference.
@ -1521,11 +1517,11 @@ void CStringChecker::evalCopyCommon(CheckerContext &C, const CallEvent &Call,
lastElement = C.getSValBuilder().conjureSymbolVal(Call, C.blockCount());
// The byte after the last byte copied is the return value.
state = state->BindExpr(Call.getOriginExpr(), LCtx, lastElement);
state = state->BindExpr(Call.getOriginExpr(), SF, lastElement);
} else {
// All other copies return the destination buffer.
// (Well, bcopy() has a void return type, but this won't hurt.)
state = state->BindExpr(Call.getOriginExpr(), LCtx, destVal);
state = state->BindExpr(Call.getOriginExpr(), SF, destVal);
}
// Invalidate the destination (regular invalidation without pointer-escaping
@ -1613,10 +1609,10 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallEvent &Call,
ProgramStateRef State = C.getState();
SValBuilder &Builder = C.getSValBuilder();
const LocationContext *LCtx = C.getLocationContext();
const StackFrame *SF = C.getStackFrame();
// See if the size argument is zero.
SVal sizeVal = State->getSVal(Size.Expression, LCtx);
SVal sizeVal = State->getSVal(Size.Expression, SF);
QualType sizeTy = Size.Expression->getType();
ProgramStateRef stateZeroSize, stateNonZeroSize;
@ -1627,7 +1623,7 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallEvent &Call,
// have to check either of the buffers.
if (stateZeroSize) {
State = stateZeroSize;
State = State->BindExpr(Call.getOriginExpr(), LCtx,
State = State->BindExpr(Call.getOriginExpr(), SF,
Builder.makeZeroVal(Call.getResultType()));
C.addTransition(State);
}
@ -1639,9 +1635,9 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallEvent &Call,
// First, get the two buffers' addresses. Another checker will have already
// made sure they're not undefined.
DefinedOrUnknownSVal LV =
State->getSVal(Left.Expression, LCtx).castAs<DefinedOrUnknownSVal>();
State->getSVal(Left.Expression, SF).castAs<DefinedOrUnknownSVal>();
DefinedOrUnknownSVal RV =
State->getSVal(Right.Expression, LCtx).castAs<DefinedOrUnknownSVal>();
State->getSVal(Right.Expression, SF).castAs<DefinedOrUnknownSVal>();
// See if they are the same.
ProgramStateRef SameBuffer, NotSameBuffer;
@ -1654,7 +1650,7 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallEvent &Call,
State = SameBuffer;
State = CheckBufferAccess(C, State, Left, Size, AccessKind::read);
if (State) {
State = SameBuffer->BindExpr(Call.getOriginExpr(), LCtx,
State = SameBuffer->BindExpr(Call.getOriginExpr(), SF,
Builder.makeZeroVal(Call.getResultType()));
C.addTransition(State);
}
@ -1669,7 +1665,7 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallEvent &Call,
if (State) {
// The return value is the comparison result, which we don't know.
SVal CmpV = Builder.conjureSymbolVal(Call, C.blockCount());
State = State->BindExpr(Call.getOriginExpr(), LCtx, CmpV);
State = State->BindExpr(Call.getOriginExpr(), SF, CmpV);
C.addTransition(State);
}
}
@ -1692,11 +1688,11 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C,
bool IsStrnlen) const {
CurrentFunctionDescription = "string length function";
ProgramStateRef state = C.getState();
const LocationContext *LCtx = C.getLocationContext();
const StackFrame *SF = C.getStackFrame();
if (IsStrnlen) {
const Expr *maxlenExpr = Call.getArgExpr(1);
SVal maxlenVal = state->getSVal(maxlenExpr, LCtx);
SVal maxlenVal = state->getSVal(maxlenExpr, SF);
ProgramStateRef stateZeroSize, stateNonZeroSize;
std::tie(stateZeroSize, stateNonZeroSize) =
@ -1706,7 +1702,7 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C,
// have to check the string itself.
if (stateZeroSize) {
SVal zero = C.getSValBuilder().makeZeroVal(Call.getResultType());
stateZeroSize = stateZeroSize->BindExpr(Call.getOriginExpr(), LCtx, zero);
stateZeroSize = stateZeroSize->BindExpr(Call.getOriginExpr(), SF, zero);
C.addTransition(stateZeroSize);
}
@ -1720,7 +1716,7 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C,
// Check that the string argument is non-null.
AnyArgExpr Arg = {Call.getArgExpr(0), 0};
SVal ArgVal = state->getSVal(Arg.Expression, LCtx);
SVal ArgVal = state->getSVal(Arg.Expression, SF);
state = checkNonNull(C, state, Arg, ArgVal);
if (!state)
@ -1743,7 +1739,7 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C,
// It's a little unfortunate to be getting this again,
// but it's not that expensive...
const Expr *maxlenExpr = Call.getArgExpr(1);
SVal maxlenVal = state->getSVal(maxlenExpr, LCtx);
SVal maxlenVal = state->getSVal(maxlenExpr, SF);
std::optional<NonLoc> strLengthNL = strLength.getAs<NonLoc>();
std::optional<NonLoc> maxlenValNL = maxlenVal.getAs<NonLoc>();
@ -1800,7 +1796,7 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C,
// Bind the return value.
assert(!result.isUnknown() && "Should have conjured a value by now");
state = state->BindExpr(Call.getOriginExpr(), LCtx, result);
state = state->BindExpr(Call.getOriginExpr(), SF, result);
C.addTransition(state);
}
@ -1881,18 +1877,18 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallEvent &Call,
CurrentFunctionDescription = "string concatenation function";
ProgramStateRef state = C.getState();
const LocationContext *LCtx = C.getLocationContext();
const StackFrame *SF = C.getStackFrame();
// Check that the destination is non-null.
DestinationArgExpr Dst = {{Call.getArgExpr(0), 0}};
SVal DstVal = state->getSVal(Dst.Expression, LCtx);
SVal DstVal = state->getSVal(Dst.Expression, SF);
state = checkNonNull(C, state, Dst, DstVal);
if (!state)
return;
// Check that the source is non-null.
SourceArgExpr srcExpr = {{Call.getArgExpr(1), 1}};
SVal srcVal = state->getSVal(srcExpr.Expression, LCtx);
SVal srcVal = state->getSVal(srcExpr.Expression, SF);
state = checkNonNull(C, state, srcExpr, srcVal);
if (!state)
return;
@ -1936,7 +1932,7 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallEvent &Call,
if (IsBounded) {
// Get the max number of characters to copy.
SizeArgExpr lenExpr = {{Call.getArgExpr(2), 2}};
SVal lenVal = state->getSVal(lenExpr.Expression, LCtx);
SVal lenVal = state->getSVal(lenExpr.Expression, SF);
// Protect against misdeclared strncpy().
lenVal =
@ -2050,18 +2046,18 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallEvent &Call,
if (StateZeroSize && !StateNonZeroSize) {
if (returnPtr) {
StateZeroSize =
StateZeroSize->BindExpr(Call.getOriginExpr(), LCtx, DstVal);
StateZeroSize->BindExpr(Call.getOriginExpr(), SF, DstVal);
} else {
if (appendK == ConcatFnKind::none) {
// strlcpy returns strlen(src)
StateZeroSize = StateZeroSize->BindExpr(Call.getOriginExpr(),
LCtx, strLength);
StateZeroSize =
StateZeroSize->BindExpr(Call.getOriginExpr(), SF, strLength);
} else {
// strlcat returns strlen(src) + strlen(dst)
SVal retSize = svalBuilder.evalBinOp(
state, BO_Add, strLength, dstStrLength, sizeTy);
StateZeroSize =
StateZeroSize->BindExpr(Call.getOriginExpr(), LCtx, retSize);
StateZeroSize->BindExpr(Call.getOriginExpr(), SF, retSize);
}
}
C.addTransition(StateZeroSize);
@ -2253,7 +2249,7 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallEvent &Call,
if (CouldAccessOutOfBound) {
// Get the max number of characters to copy.
const Expr *LenExpr = Call.getArgExpr(2);
SVal LenVal = state->getSVal(LenExpr, LCtx);
SVal LenVal = state->getSVal(LenExpr, SF);
// Protect against misdeclared strncpy().
LenVal = svalBuilder.evalCast(LenVal, sizeTy, LenExpr->getType());
@ -2307,7 +2303,7 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallEvent &Call,
}
}
// Set the return value.
state = state->BindExpr(Call.getOriginExpr(), LCtx, Result);
state = state->BindExpr(Call.getOriginExpr(), SF, Result);
C.addTransition(state);
}
@ -2317,7 +2313,7 @@ void CStringChecker::evalStrxfrm(CheckerContext &C,
CurrentFunctionDescription = "locale transformation function";
ProgramStateRef State = C.getState();
const LocationContext *LCtx = C.getLocationContext();
const StackFrame *SF = C.getStackFrame();
SValBuilder &SVB = C.getSValBuilder();
// Get arguments
@ -2326,7 +2322,7 @@ void CStringChecker::evalStrxfrm(CheckerContext &C,
SizeArgExpr Size = {{Call.getArgExpr(2), 2}};
// `src` can never be null
SVal SrcVal = State->getSVal(Source.Expression, LCtx);
SVal SrcVal = State->getSVal(Source.Expression, SF);
State = checkNonNull(C, State, Source, SrcVal);
if (!State)
return;
@ -2340,16 +2336,16 @@ void CStringChecker::evalStrxfrm(CheckerContext &C,
// transformation
SVal RetVal = SVB.conjureSymbolVal(Call, C.blockCount());
auto BindReturnAndTransition = [&RetVal, &Call, LCtx,
auto BindReturnAndTransition = [&RetVal, &Call, SF,
&C](ProgramStateRef State) {
if (State) {
State = State->BindExpr(Call.getOriginExpr(), LCtx, RetVal);
State = State->BindExpr(Call.getOriginExpr(), SF, RetVal);
C.addTransition(State);
}
};
// Check if size is zero
SVal SizeVal = State->getSVal(Size.Expression, LCtx);
SVal SizeVal = State->getSVal(Size.Expression, SF);
QualType SizeTy = Size.Expression->getType();
auto [StateZeroSize, StateSizeNonZero] =
@ -2364,7 +2360,7 @@ void CStringChecker::evalStrxfrm(CheckerContext &C,
return BindReturnAndTransition(StateZeroSize);
// If `n` is not 0, `dest` can not be null.
SVal DestVal = StateSizeNonZero->getSVal(Dest.Expression, LCtx);
SVal DestVal = StateSizeNonZero->getSVal(Dest.Expression, SF);
StateSizeNonZero = checkNonNull(C, StateSizeNonZero, Dest, DestVal);
if (!StateSizeNonZero)
return;
@ -2404,7 +2400,7 @@ void CStringChecker::evalStrxfrm(CheckerContext &C,
if (auto DestLoc = DestVal.getAs<loc::MemRegionVal>()) {
StateFailure = StateFailure->killBinding(*DestLoc);
StateFailure =
StateFailure->bindDefaultInitial(*DestLoc, UndefinedVal{}, LCtx);
StateFailure->bindDefaultInitial(*DestLoc, UndefinedVal{}, SF);
}
BindReturnAndTransition(StateFailure);
@ -2439,18 +2435,18 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallEvent &Call,
bool IsBounded, bool IgnoreCase) const {
CurrentFunctionDescription = "string comparison function";
ProgramStateRef state = C.getState();
const LocationContext *LCtx = C.getLocationContext();
const StackFrame *SF = C.getStackFrame();
// Check that the first string is non-null
AnyArgExpr Left = {Call.getArgExpr(0), 0};
SVal LeftVal = state->getSVal(Left.Expression, LCtx);
SVal LeftVal = state->getSVal(Left.Expression, SF);
state = checkNonNull(C, state, Left, LeftVal);
if (!state)
return;
// Check that the second string is non-null.
AnyArgExpr Right = {Call.getArgExpr(1), 1};
SVal RightVal = state->getSVal(Right.Expression, LCtx);
SVal RightVal = state->getSVal(Right.Expression, SF);
state = checkNonNull(C, state, Right, RightVal);
if (!state)
return;
@ -2481,7 +2477,7 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallEvent &Call,
// and we only need to check one size.
if (StSameBuf) {
StSameBuf =
StSameBuf->BindExpr(Call.getOriginExpr(), LCtx,
StSameBuf->BindExpr(Call.getOriginExpr(), SF,
svalBuilder.makeZeroVal(Call.getResultType()));
C.addTransition(StSameBuf);
@ -2511,7 +2507,7 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallEvent &Call,
if (IsBounded) {
// Get the max number of characters to compare.
const Expr *lenExpr = Call.getArgExpr(2);
SVal lenVal = state->getSVal(lenExpr, LCtx);
SVal lenVal = state->getSVal(lenExpr, SF);
// If the length is known, we can get the right substrings.
if (const llvm::APSInt *len = svalBuilder.getKnownValue(state, lenVal)) {
@ -2558,7 +2554,7 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallEvent &Call,
}
}
state = state->BindExpr(Call.getOriginExpr(), LCtx, resultVal);
state = state->BindExpr(Call.getOriginExpr(), SF, resultVal);
// Record this as a possible path.
C.addTransition(state);
@ -2577,18 +2573,18 @@ void CStringChecker::evalStrsep(CheckerContext &C,
CurrentFunctionDescription = "strsep()";
ProgramStateRef State = C.getState();
const LocationContext *LCtx = C.getLocationContext();
const StackFrame *SF = C.getStackFrame();
// Check that the search string pointer is non-null (though it may point to
// a null string).
SVal SearchStrVal = State->getSVal(SearchStrPtr.Expression, LCtx);
SVal SearchStrVal = State->getSVal(SearchStrPtr.Expression, SF);
State = checkNonNull(C, State, SearchStrPtr, SearchStrVal);
if (!State)
return;
// Check that the delimiter string is non-null.
AnyArgExpr DelimStr = {Call.getArgExpr(1), 1};
SVal DelimStrVal = State->getSVal(DelimStr.Expression, LCtx);
SVal DelimStrVal = State->getSVal(DelimStr.Expression, SF);
State = checkNonNull(C, State, DelimStr, DelimStrVal);
if (!State)
return;
@ -2609,7 +2605,7 @@ void CStringChecker::evalStrsep(CheckerContext &C,
// further along in the same string, or NULL if there are no more tokens.
State = State->bindLoc(*SearchStrLoc,
SVB.conjureSymbolVal(Call, C.blockCount(), getTag()),
LCtx);
SF);
} else {
assert(SearchStrVal.isUnknown());
// Conjure a symbolic value. It's the best we can do.
@ -2617,7 +2613,7 @@ void CStringChecker::evalStrsep(CheckerContext &C,
}
// Set the return value, and finish.
State = State->BindExpr(Call.getOriginExpr(), LCtx, Result);
State = State->BindExpr(Call.getOriginExpr(), SF, Result);
C.addTransition(State);
}
@ -2639,7 +2635,7 @@ void CStringChecker::evalStdCopyCommon(CheckerContext &C,
ProgramStateRef State = C.getState();
const LocationContext *LCtx = C.getLocationContext();
const StackFrame *SF = C.getStackFrame();
// template <class _InputIterator, class _OutputIterator>
// _OutputIterator
@ -2648,7 +2644,7 @@ void CStringChecker::evalStdCopyCommon(CheckerContext &C,
// Invalidate the destination buffer
const Expr *Dst = Call.getArgExpr(2);
SVal DstVal = State->getSVal(Dst, LCtx);
SVal DstVal = State->getSVal(Dst, SF);
// FIXME: As we do not know how many items are copied, we also invalidate the
// super region containing the target location.
State = invalidateDestinationBufferAlwaysEscapeSuperRegion(
@ -2657,7 +2653,7 @@ void CStringChecker::evalStdCopyCommon(CheckerContext &C,
SValBuilder &SVB = C.getSValBuilder();
SVal ResultVal = SVB.conjureSymbolVal(Call, C.blockCount());
State = State->BindExpr(Call.getOriginExpr(), LCtx, ResultVal);
State = State->BindExpr(Call.getOriginExpr(), SF, ResultVal);
C.addTransition(State);
}
@ -2674,7 +2670,7 @@ void CStringChecker::evalMemset(CheckerContext &C,
ProgramStateRef State = C.getState();
// See if the size argument is zero.
const LocationContext *LCtx = C.getLocationContext();
const StackFrame *SF = C.getStackFrame();
SVal SizeVal = C.getSVal(Size.Expression);
QualType SizeTy = Size.Expression->getType();
@ -2687,7 +2683,7 @@ void CStringChecker::evalMemset(CheckerContext &C,
// If the size is zero, there won't be any actual memory access, so
// just bind the return value to the buffer and return.
if (ZeroSize && !NonZeroSize) {
ZeroSize = ZeroSize->BindExpr(Call.getOriginExpr(), LCtx, BufferPtrVal);
ZeroSize = ZeroSize->BindExpr(Call.getOriginExpr(), SF, BufferPtrVal);
C.addTransition(ZeroSize);
return;
}
@ -2709,7 +2705,7 @@ void CStringChecker::evalMemset(CheckerContext &C,
C.getSVal(CharE.Expression), Size.Expression, C, State))
return;
State = State->BindExpr(Call.getOriginExpr(), LCtx, BufferPtrVal);
State = State->BindExpr(Call.getOriginExpr(), SF, BufferPtrVal);
C.addTransition(State);
}
@ -2882,7 +2878,7 @@ void CStringChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
if (!isa<StringLiteral>(Init))
continue;
Loc VarLoc = state->getLValue(D, C.getLocationContext());
Loc VarLoc = state->getLValue(D, C.getStackFrame());
const MemRegion *MR = VarLoc.getAsRegion();
if (!MR)
continue;
@ -2898,12 +2894,10 @@ void CStringChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
C.addTransition(state);
}
ProgramStateRef
CStringChecker::checkRegionChanges(ProgramStateRef state,
const InvalidatedSymbols *,
ProgramStateRef CStringChecker::checkRegionChanges(
ProgramStateRef state, const InvalidatedSymbols *,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const LocationContext *LCtx,
ArrayRef<const MemRegion *> Regions, const StackFrame *SF,
const CallEvent *Call) const {
CStringLengthTy Entries = state->get<CStringLength>();
if (Entries.isEmpty())

View file

@ -210,8 +210,7 @@ CXXDeleteChecker::PtrCastVisitor::VisitNode(const ExplodedNode *N,
OS << "Casting from '" << SourceType.getAsString() << "' to '"
<< TargetType.getAsString() << "' here";
PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
N->getLocationContext());
PathDiagnosticLocation Pos(S, BRC.getSourceManager(), N->getStackFrame());
return std::make_shared<PathDiagnosticEventPiece>(Pos, OS.str(),
/*addPosRange=*/true);
}

View file

@ -38,20 +38,19 @@ CXXSelfAssignmentChecker::CXXSelfAssignmentChecker() {}
void CXXSelfAssignmentChecker::checkBeginFunction(CheckerContext &C) const {
if (!C.inTopFrame())
return;
const auto *LCtx = C.getLocationContext();
const auto *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl());
const auto *SF = C.getStackFrame();
const auto *MD = dyn_cast<CXXMethodDecl>(SF->getDecl());
if (!MD)
return;
if (!MD->isCopyAssignmentOperator() && !MD->isMoveAssignmentOperator())
return;
auto &State = C.getState();
auto &SVB = C.getSValBuilder();
auto ThisVal =
State->getSVal(SVB.getCXXThis(MD, LCtx->getStackFrame()));
auto Param = SVB.makeLoc(State->getRegion(MD->getParamDecl(0), LCtx));
auto ThisVal = State->getSVal(SVB.getCXXThis(MD, SF));
auto Param = SVB.makeLoc(State->getRegion(MD->getParamDecl(0), SF));
auto ParamVal = State->getSVal(Param);
ProgramStateRef SelfAssignState = State->bindLoc(Param, ThisVal, LCtx);
ProgramStateRef SelfAssignState = State->bindLoc(Param, ThisVal, SF);
const NoteTag *SelfAssignTag =
C.getNoteTag([MD](PathSensitiveBugReport &BR) -> std::string {
SmallString<256> Msg;
@ -61,7 +60,7 @@ void CXXSelfAssignmentChecker::checkBeginFunction(CheckerContext &C) const {
});
C.addTransition(SelfAssignState, SelfAssignTag);
ProgramStateRef NonSelfAssignState = State->bindLoc(Param, ParamVal, LCtx);
ProgramStateRef NonSelfAssignState = State->bindLoc(Param, ParamVal, SF);
const NoteTag *NonSelfAssignTag =
C.getNoteTag([MD](PathSensitiveBugReport &BR) -> std::string {
SmallString<256> Msg;

View file

@ -430,8 +430,7 @@ ProgramStateRef CallAndMessageChecker::checkFunctionPointerCall(
const CallExpr *CE, CheckerContext &C, ProgramStateRef State) const {
const Expr *Callee = CE->getCallee()->IgnoreParens();
const LocationContext *LCtx = C.getLocationContext();
SVal L = State->getSVal(Callee, LCtx);
SVal L = State->getSVal(Callee, C.getStackFrame());
if (L.isUndef()) {
if (!ChecksEnabled[CK_FunctionPointer]) {
@ -700,18 +699,18 @@ void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C,
// return different values depending on the return type and the architecture.
QualType RetTy = Msg.getResultType();
CanQualType CanRetTy = Ctx.getCanonicalType(RetTy);
const LocationContext *LCtx = C.getLocationContext();
const StackFrame *SF = C.getStackFrame();
if (CanRetTy->isStructureOrClassType()) {
// Structure returns are safe since the compiler zeroes them out.
SVal V = C.getSValBuilder().makeZeroVal(RetTy);
C.addTransition(state->BindExpr(Msg.getOriginExpr(), LCtx, V));
C.addTransition(state->BindExpr(Msg.getOriginExpr(), SF, V));
return;
}
// Other cases: check if sizeof(return type) > sizeof(void*)
if (CanRetTy != Ctx.VoidTy && C.getLocationContext()->getParentMap()
.isConsumedExpr(Msg.getOriginExpr())) {
if (CanRetTy != Ctx.VoidTy &&
C.getStackFrame()->getParentMap().isConsumedExpr(Msg.getOriginExpr())) {
// Compute: sizeof(void *) and sizeof(return type)
const uint64_t voidPtrSize = Ctx.getTypeSize(Ctx.VoidPtrTy);
const uint64_t returnTypeSize = Ctx.getTypeSize(CanRetTy);
@ -743,7 +742,7 @@ void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C,
// of this case unless we have *a lot* more knowledge.
//
SVal V = C.getSValBuilder().makeZeroVal(RetTy);
C.addTransition(state->BindExpr(Msg.getOriginExpr(), LCtx, V));
C.addTransition(state->BindExpr(Msg.getOriginExpr(), SF, V));
return;
}

View file

@ -252,7 +252,7 @@ static void addCastTransition(const CallEvent &Call, DefinedOrUnknownSVal DV,
SVal V = CastSucceeds ? C.getSValBuilder().evalCast(DV, CastToTy, CastFromTy)
: C.getSValBuilder().makeNullWithType(CastToTy);
C.addTransition(
State->BindExpr(Call.getOriginExpr(), C.getLocationContext(), V, false),
State->BindExpr(Call.getOriginExpr(), C.getStackFrame(), V, false),
getNoteTag(C, CastInfo, CastToTy, Object, CastSucceeds, IsKnownCast));
}
@ -313,11 +313,11 @@ static void addInstanceOfTransition(const CallEvent &Call,
if (CastSucceeds) {
Success = true;
C.addTransition(
NewState->BindExpr(Call.getOriginExpr(), C.getLocationContext(),
C.getSValBuilder().makeTruthVal(true)),
getNoteTag(C, CastInfo, CastToTy, Call.getArgExpr(0), true,
IsKnownCast));
C.addTransition(NewState->BindExpr(Call.getOriginExpr(),
C.getStackFrame(),
C.getSValBuilder().makeTruthVal(true)),
getNoteTag(C, CastInfo, CastToTy, Call.getArgExpr(0),
true, IsKnownCast));
if (IsKnownCast)
return;
} else if (CastInfo && CastInfo->succeeds()) {
@ -327,10 +327,9 @@ static void addInstanceOfTransition(const CallEvent &Call,
}
if (!Success) {
C.addTransition(
State->BindExpr(Call.getOriginExpr(), C.getLocationContext(),
C.getSValBuilder().makeTruthVal(false)),
getNoteTag(C, CastToTyVec, Call.getArgExpr(0), IsAnyKnown));
C.addTransition(State->BindExpr(Call.getOriginExpr(), C.getStackFrame(),
C.getSValBuilder().makeTruthVal(false)),
getNoteTag(C, CastToTyVec, Call.getArgExpr(0), IsAnyKnown));
}
}
@ -357,8 +356,7 @@ static void evalNullParamNullReturn(const CallEvent &Call,
DefinedOrUnknownSVal DV,
CheckerContext &C) {
if (ProgramStateRef State = C.getState()->assume(DV, false))
C.addTransition(State->BindExpr(Call.getOriginExpr(),
C.getLocationContext(),
C.addTransition(State->BindExpr(Call.getOriginExpr(), C.getStackFrame(),
C.getSValBuilder().makeNullWithType(
Call.getOriginExpr()->getType()),
false),

View file

@ -157,14 +157,14 @@ private:
getDeallocReleaseRequirement(const ObjCPropertyImplDecl *PropImpl) const;
bool isInInstanceDealloc(const CheckerContext &C, SVal &SelfValOut) const;
bool isInInstanceDealloc(const CheckerContext &C, const LocationContext *LCtx,
bool isInInstanceDealloc(const CheckerContext &C, const StackFrame *SF,
SVal &SelfValOut) const;
bool instanceDeallocIsOnStack(const CheckerContext &C,
SVal &InstanceValOut) const;
bool isSuperDeallocMessage(const ObjCMethodCall &M) const;
const ObjCImplDecl *getContainingObjCImpl(const LocationContext *LCtx) const;
const ObjCImplDecl *getContainingObjCImpl(const StackFrame *SF) const;
const ObjCPropertyDecl *
findShadowedPropertyDecl(const ObjCPropertyImplDecl *PropImpl) const;
@ -267,7 +267,7 @@ void ObjCDeallocChecker::checkBeginFunction(
SymbolRef SelfSymbol = SelfVal.getAsSymbol();
const LocationContext *LCtx = C.getLocationContext();
const StackFrame *SF = C.getStackFrame();
ProgramStateRef InitialState = C.getState();
ProgramStateRef State = InitialState;
@ -282,7 +282,7 @@ void ObjCDeallocChecker::checkBeginFunction(
if (const SymbolSet *CurrSet = State->get<UnreleasedIvarMap>(SelfSymbol))
RequiredReleases = *CurrSet;
for (auto *PropImpl : getContainingObjCImpl(LCtx)->property_impls()) {
for (auto *PropImpl : getContainingObjCImpl(SF)->property_impls()) {
ReleaseRequirement Requirement = getDeallocReleaseRequirement(PropImpl);
if (Requirement != ReleaseRequirement::MustRelease)
continue;
@ -500,7 +500,7 @@ void ObjCDeallocChecker::diagnoseMissingReleases(CheckerContext &C) const {
return;
const MemRegion *SelfRegion = SelfVal.castAs<loc::MemRegionVal>().getRegion();
const LocationContext *LCtx = C.getLocationContext();
const StackFrame *SF = C.getStackFrame();
ExplodedNode *ErrNode = nullptr;
@ -530,7 +530,7 @@ void ObjCDeallocChecker::diagnoseMissingReleases(CheckerContext &C) const {
// Prevent an inlined call to -dealloc in a super class from warning
// about the values the subclass's -dealloc should release.
if (IvarDecl->getContainingInterface() !=
cast<ObjCMethodDecl>(LCtx->getDecl())->getClassInterface())
cast<ObjCMethodDecl>(SF->getDecl())->getClassInterface())
continue;
// Prevents diagnosing multiple times for the same instance variable
@ -604,7 +604,7 @@ void ObjCDeallocChecker::diagnoseMissingReleases(CheckerContext &C) const {
// Make sure that after checking in the top-most frame the list of
// tracked ivars is empty. This is intended to detect accidental leaks in
// the UnreleasedIvarMap program state.
assert(!LCtx->inTopFrame() || State->get<UnreleasedIvarMap>().isEmpty());
assert(!SF->inTopFrame() || State->get<UnreleasedIvarMap>().isEmpty());
}
/// Given a symbol, determine whether the symbol refers to an ivar on
@ -628,10 +628,10 @@ ObjCDeallocChecker::findPropertyOnDeallocatingInstance(
IvarRegion->getSuperRegion())
return nullptr;
const LocationContext *LCtx = C.getLocationContext();
const StackFrame *SF = C.getStackFrame();
const ObjCIvarDecl *IvarDecl = IvarRegion->getDecl();
const ObjCImplDecl *Container = getContainingObjCImpl(LCtx);
const ObjCImplDecl *Container = getContainingObjCImpl(SF);
const ObjCPropertyImplDecl *PropImpl =
Container->FindPropertyImplIvarDecl(IvarDecl->getIdentifier());
return PropImpl;
@ -688,7 +688,7 @@ bool ObjCDeallocChecker::diagnoseExtraRelease(SymbolRef ReleasedValue,
isReleasedByCIFilterDealloc(PropImpl)
);
const ObjCImplDecl *Container = getContainingObjCImpl(C.getLocationContext());
const ObjCImplDecl *Container = getContainingObjCImpl(C.getStackFrame());
OS << "The '" << *PropImpl->getPropertyIvarDecl()
<< "' ivar in '" << *Container;
@ -783,10 +783,10 @@ bool ObjCDeallocChecker::isSuperDeallocMessage(
return M.getSelector() == DeallocSel;
}
/// Returns the ObjCImplDecl containing the method declaration in LCtx.
/// Returns the ObjCImplDecl containing the method declaration in SF.
const ObjCImplDecl *
ObjCDeallocChecker::getContainingObjCImpl(const LocationContext *LCtx) const {
auto *MD = cast<ObjCMethodDecl>(LCtx->getDecl());
ObjCDeallocChecker::getContainingObjCImpl(const StackFrame *SF) const {
auto *MD = cast<ObjCMethodDecl>(SF->getDecl());
return cast<ObjCImplDecl>(MD->getDeclContext());
}
@ -957,24 +957,24 @@ ObjCDeallocChecker::getValueReleasedByNillingOut(const ObjCMethodCall &M,
/// 'self'.
bool ObjCDeallocChecker::isInInstanceDealloc(const CheckerContext &C,
SVal &SelfValOut) const {
return isInInstanceDealloc(C, C.getLocationContext(), SelfValOut);
return isInInstanceDealloc(C, C.getStackFrame(), SelfValOut);
}
/// Returns true if LCtx is a call to -dealloc and false
/// Returns true if SF is a call to -dealloc and false
/// otherwise. If true, it also sets SelfValOut to the value of
/// 'self'.
bool ObjCDeallocChecker::isInInstanceDealloc(const CheckerContext &C,
const LocationContext *LCtx,
const StackFrame *SF,
SVal &SelfValOut) const {
auto *MD = dyn_cast<ObjCMethodDecl>(LCtx->getDecl());
auto *MD = dyn_cast<ObjCMethodDecl>(SF->getDecl());
if (!MD || !MD->isInstanceMethod() || MD->getSelector() != DeallocSel)
return false;
const ImplicitParamDecl *SelfDecl = LCtx->getSelfDecl();
const ImplicitParamDecl *SelfDecl = SF->getSelfDecl();
assert(SelfDecl && "No self in -dealloc?");
ProgramStateRef State = C.getState();
SelfValOut = State->getSVal(State->getRegion(SelfDecl, LCtx));
SelfValOut = State->getSVal(State->getRegion(SelfDecl, SF));
return true;
}
@ -983,13 +983,13 @@ bool ObjCDeallocChecker::isInInstanceDealloc(const CheckerContext &C,
/// 'self' in the frame for -dealloc.
bool ObjCDeallocChecker::instanceDeallocIsOnStack(const CheckerContext &C,
SVal &InstanceValOut) const {
const LocationContext *LCtx = C.getLocationContext();
const StackFrame *SF = C.getStackFrame();
while (LCtx) {
if (isInInstanceDealloc(C, LCtx, InstanceValOut))
while (SF) {
if (isInInstanceDealloc(C, SF, InstanceValOut))
return true;
LCtx = LCtx->getParent();
SF = SF->getParent();
}
return false;

View file

@ -314,19 +314,18 @@ public:
/// by this change. For a simple bind, this list will be the same as
/// \p ExplicitRegions, since a bind does not affect the contents of
/// anything accessible through the base region.
/// \param LCtx LocationContext that is useful for getting various contextual
/// \param SF StackFrame that is useful for getting various contextual
/// info, like callstack, CFG etc.
/// \param Call The opaque call triggering this invalidation. Will be 0 if the
/// change was not triggered by a call.
///
/// check::RegionChanges
ProgramStateRef
checkRegionChanges(ProgramStateRef State,
const InvalidatedSymbols *Invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const LocationContext *LCtx,
const CallEvent *Call) const {
checkRegionChanges(ProgramStateRef State,
const InvalidatedSymbols *Invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions, const StackFrame *SF,
const CallEvent *Call) const {
return State;
}

View file

@ -74,7 +74,7 @@ bool ChrootChecker::evalCall(const CallEvent &Call, CheckerContext &C) const {
bool ChrootChecker::evalChroot(const CallEvent &Call, CheckerContext &C) const {
BasicValueFactory &BVF = C.getSValBuilder().getBasicValueFactory();
const LocationContext *LCtx = C.getLocationContext();
const StackFrame *SF = C.getStackFrame();
ProgramStateRef State = C.getState();
const auto *CE = cast<CallExpr>(Call.getOriginExpr());
@ -82,10 +82,10 @@ bool ChrootChecker::evalChroot(const CallEvent &Call, CheckerContext &C) const {
SVal Zero = nonloc::ConcreteInt{BVF.getValue(0, IntTy)};
SVal Minus1 = nonloc::ConcreteInt{BVF.getValue(-1, IntTy)};
ProgramStateRef ChrootFailed = State->BindExpr(CE, LCtx, Minus1);
ProgramStateRef ChrootFailed = State->BindExpr(CE, SF, Minus1);
C.addTransition(ChrootFailed->set<ChrootState>(ROOT_CHANGE_FAILED));
ProgramStateRef ChrootSucceeded = State->BindExpr(CE, LCtx, Zero);
ProgramStateRef ChrootSucceeded = State->BindExpr(CE, SF, Zero);
C.addTransition(ChrootSucceeded->set<ChrootState>(ROOT_CHANGED));
return true;
}
@ -136,7 +136,7 @@ public:
Satisfied = true;
PathDiagnosticLocation Pos(Call, BRC.getSourceManager(),
N->getLocationContext());
N->getStackFrame());
return std::make_shared<PathDiagnosticEventPiece>(Pos, "chroot called here",
/*addPosRange=*/true);
}

View file

@ -109,12 +109,10 @@ SymbolRef getContainerEnd(ProgramStateRef State, const MemRegion *Cont);
ProgramStateRef createContainerBegin(ProgramStateRef State,
const MemRegion *Cont,
ConstCFGElementRef Elem, QualType T,
const LocationContext *LCtx,
unsigned BlockCount);
const StackFrame *SF, unsigned BlockCount);
ProgramStateRef createContainerEnd(ProgramStateRef State, const MemRegion *Cont,
ConstCFGElementRef Elem, QualType T,
const LocationContext *LCtx,
unsigned BlockCount);
const StackFrame *SF, unsigned BlockCount);
ProgramStateRef setContainerData(ProgramStateRef State, const MemRegion *Cont,
const ContainerData &CData);
ProgramStateRef invalidateAllIteratorPositions(ProgramStateRef State,
@ -264,7 +262,7 @@ void ContainerModeling::handleBegin(CheckerContext &C, ConstCFGElementRef Elem,
auto BeginSym = getContainerBegin(State, ContReg);
if (!BeginSym) {
State = createContainerBegin(State, ContReg, Elem, C.getASTContext().LongTy,
C.getLocationContext(), C.blockCount());
C.getStackFrame(), C.blockCount());
BeginSym = getContainerBegin(State, ContReg);
}
State = setIteratorPosition(State, RetVal,
@ -286,7 +284,7 @@ void ContainerModeling::handleEnd(CheckerContext &C, ConstCFGElementRef Elem,
auto EndSym = getContainerEnd(State, ContReg);
if (!EndSym) {
State = createContainerEnd(State, ContReg, Elem, C.getASTContext().LongTy,
C.getLocationContext(), C.blockCount());
C.getStackFrame(), C.blockCount());
EndSym = getContainerEnd(State, ContReg);
}
State = setIteratorPosition(State, RetVal,
@ -330,7 +328,7 @@ void ContainerModeling::handleAssignment(CheckerContext &C, SVal Cont,
auto &SVB = C.getSValBuilder();
// Then generate and assign a new "end" symbol for the new container.
auto NewEndSym =
SymMgr.conjureSymbol(Elem, C.getLocationContext(),
SymMgr.conjureSymbol(Elem, C.getStackFrame(),
C.getASTContext().LongTy, C.blockCount());
State = assumeNoOverflow(State, NewEndSym, 4);
if (CData) {
@ -851,7 +849,7 @@ SymbolRef getContainerEnd(ProgramStateRef State, const MemRegion *Cont) {
ProgramStateRef createContainerBegin(ProgramStateRef State,
const MemRegion *Cont,
ConstCFGElementRef Elem, QualType T,
const LocationContext *LCtx,
const StackFrame *SF,
unsigned BlockCount) {
// Only create if it does not exist
const auto *CDataPtr = getContainerData(State, Cont);
@ -860,7 +858,7 @@ ProgramStateRef createContainerBegin(ProgramStateRef State,
auto &SymMgr = State->getSymbolManager();
const SymbolConjured *Sym =
SymMgr.conjureSymbol(Elem, LCtx, T, BlockCount, "begin");
SymMgr.conjureSymbol(Elem, SF, T, BlockCount, "begin");
State = assumeNoOverflow(State, Sym, 4);
if (CDataPtr) {
@ -874,8 +872,7 @@ ProgramStateRef createContainerBegin(ProgramStateRef State,
ProgramStateRef createContainerEnd(ProgramStateRef State, const MemRegion *Cont,
ConstCFGElementRef Elem, QualType T,
const LocationContext *LCtx,
unsigned BlockCount) {
const StackFrame *SF, unsigned BlockCount) {
// Only create if it does not exist
const auto *CDataPtr = getContainerData(State, Cont);
if (CDataPtr && CDataPtr->getEnd())
@ -883,7 +880,7 @@ ProgramStateRef createContainerEnd(ProgramStateRef State, const MemRegion *Cont,
auto &SymMgr = State->getSymbolManager();
const SymbolConjured *Sym =
SymMgr.conjureSymbol(Elem, LCtx, T, BlockCount, "end");
SymMgr.conjureSymbol(Elem, SF, T, BlockCount, "end");
State = assumeNoOverflow(State, Sym, 4);
if (CDataPtr) {

View file

@ -65,7 +65,7 @@ void ConversionChecker::checkPreStmt(const ImplicitCastExpr *Cast,
return;
// Get Parent.
const ParentMap &PM = C.getLocationContext()->getParentMap();
const ParentMap &PM = C.getStackFrame()->getParentMap();
const Stmt *Parent = PM.getParent(Cast);
if (!Parent)
return;

View file

@ -84,8 +84,8 @@ void DebugContainerModeling::analyzerContainerDataField(const CallExpr *CE,
if (Data) {
SymbolRef Field = get(Data);
if (Field) {
State = State->BindExpr(CE, C.getLocationContext(),
nonloc::SymbolVal(Field));
State =
State->BindExpr(CE, C.getStackFrame(), nonloc::SymbolVal(Field));
// Progpagate interestingness from the container's data (marked
// interesting by an `ExprInspection` debug call to the container
@ -105,8 +105,9 @@ void DebugContainerModeling::analyzerContainerDataField(const CallExpr *CE,
}
auto &BVF = C.getSValBuilder().getBasicValueFactory();
State = State->BindExpr(CE, C.getLocationContext(),
nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(0))));
State =
State->BindExpr(CE, C.getStackFrame(),
nonloc::ConcreteInt(BVF.getValue(llvm::APSInt::get(0))));
}
void DebugContainerModeling::analyzerContainerBegin(const CallExpr *CE,

View file

@ -85,9 +85,9 @@ void DebugIteratorModeling::analyzerIteratorDataField(const CallExpr *CE,
SVal V = C.getSVal(CE->getArg(0));
const auto *Pos = getIteratorPosition(State, V);
if (Pos) {
State = State->BindExpr(CE, C.getLocationContext(), get(Pos));
State = State->BindExpr(CE, C.getStackFrame(), get(Pos));
} else {
State = State->BindExpr(CE, C.getLocationContext(), Default);
State = State->BindExpr(CE, C.getStackFrame(), Default);
}
C.addTransition(State);
}

View file

@ -57,8 +57,7 @@ public:
static void AddDerefSource(raw_ostream &os,
SmallVectorImpl<SourceRange> &Ranges,
const Expr *Ex, const ProgramState *state,
const LocationContext *LCtx,
bool loadedFrom = false);
const StackFrame *SF, bool loadedFrom = false);
CheckerFrontend NullDerefChecker, FixedDerefChecker, NullPointerArithmChecker;
const DerefBugType NullBug{&NullDerefChecker, "Dereference of null pointer",
@ -86,20 +85,18 @@ struct ValueDescStr {
SmallVectorImpl<SourceRange> &Ranges;
const Expr *Ex;
const ProgramState *State;
const LocationContext *LCtx;
const StackFrame *SF;
bool IsPointer;
ConditionTruthVal IsNull;
};
} // end anonymous namespace
void
DereferenceChecker::AddDerefSource(raw_ostream &os,
SmallVectorImpl<SourceRange> &Ranges,
const Expr *Ex,
const ProgramState *state,
const LocationContext *LCtx,
bool loadedFrom) {
void DereferenceChecker::AddDerefSource(raw_ostream &os,
SmallVectorImpl<SourceRange> &Ranges,
const Expr *Ex,
const ProgramState *state,
const StackFrame *SF, bool loadedFrom) {
Ex = Ex->IgnoreParenLValueCasts();
switch (Ex->getStmtClass()) {
default:
@ -219,7 +216,7 @@ void DereferenceChecker::reportDerefBug(const DerefBugType &BT,
Out << "Array access";
const ArraySubscriptExpr *AE = cast<ArraySubscriptExpr>(S);
AddDerefSource(Out, Ranges, AE->getBase()->IgnoreParenCasts(), State.get(),
N->getLocationContext());
N->getStackFrame());
Out << " results in " << BT.getArrayMsg();
break;
}
@ -227,7 +224,7 @@ void DereferenceChecker::reportDerefBug(const DerefBugType &BT,
Out << "Array access";
const ArraySectionExpr *AE = cast<ArraySectionExpr>(S);
AddDerefSource(Out, Ranges, AE->getBase()->IgnoreParenCasts(), State.get(),
N->getLocationContext());
N->getStackFrame());
Out << " results in " << BT.getArrayMsg();
break;
}
@ -235,7 +232,7 @@ void DereferenceChecker::reportDerefBug(const DerefBugType &BT,
Out << BT.getDescription();
const UnaryOperator *U = cast<UnaryOperator>(S);
AddDerefSource(Out, Ranges, U->getSubExpr()->IgnoreParens(), State.get(),
N->getLocationContext(), true);
N->getStackFrame(), true);
break;
}
case Stmt::MemberExprClass: {
@ -244,7 +241,7 @@ void DereferenceChecker::reportDerefBug(const DerefBugType &BT,
Out << "Access to field '" << M->getMemberNameInfo() << "' results in "
<< BT.getFieldMsg();
AddDerefSource(Out, Ranges, M->getBase()->IgnoreParenCasts(), State.get(),
N->getLocationContext(), true);
N->getStackFrame(), true);
}
break;
}
@ -253,7 +250,7 @@ void DereferenceChecker::reportDerefBug(const DerefBugType &BT,
Out << "Access to instance variable '" << *IV->getDecl() << "' results in "
<< BT.getFieldMsg();
AddDerefSource(Out, Ranges, IV->getBase()->IgnoreParenCasts(), State.get(),
N->getLocationContext(), true);
N->getStackFrame(), true);
break;
}
default:
@ -407,7 +404,7 @@ template <> struct format_provider<ValueDescStr> {
<< ValueStr[V.IsPointer][V.IsNull.isConstrainedTrue()
? 0
: (V.IsNull.isConstrainedFalse() ? 1 : 2)];
DereferenceChecker::AddDerefSource(Stream, V.Ranges, V.Ex, V.State, V.LCtx,
DereferenceChecker::AddDerefSource(Stream, V.Ranges, V.Ex, V.State, V.SF,
false);
}
};
@ -462,10 +459,10 @@ void DereferenceChecker::checkPreStmt(const BinaryOperator *Op,
const char *OpcodeStr =
Op->getOpcode() == BO_Add ? "Addition" : "Subtraction";
const char *ResultStr = IsConstrained ? "results" : "may result";
ValueDescStr DerefArg1{
Ranges, E1, State.get(), C.getLocationContext(), T1IsPointer, V1IsNull};
ValueDescStr DerefArg2{
Ranges, E2, State.get(), C.getLocationContext(), T2IsPointer, V2IsNull};
ValueDescStr DerefArg1{Ranges, E1, State.get(), C.getStackFrame(),
T1IsPointer, V1IsNull};
ValueDescStr DerefArg2{Ranges, E2, State.get(), C.getStackFrame(),
T2IsPointer, V2IsNull};
std::string Msg =
llvm::formatv("{0} of a {1} and a {2} {3} in undefined behavior",
OpcodeStr, DerefArg1, DerefArg2, ResultStr);

View file

@ -62,7 +62,7 @@ class DirectIvarAssignment :
const ObjCInterfaceDecl *InterfD;
BugReporter &BR;
const CheckerBase *Checker;
LocationOrAnalysisDeclContext DCtx;
StackFrameOrAnalysisDeclContext DCtx;
public:
MethodCrawler(const IvarToPropertyMapTy &InMap, const ObjCMethodDecl *InMD,

View file

@ -129,8 +129,7 @@ PathDiagnosticPieceRef DynamicTypeChecker::DynamicTypeBugVisitor::VisitNode(
}
// Generate the extra diagnostic.
PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
N->getLocationContext());
PathDiagnosticLocation Pos(S, BRC.getSourceManager(), N->getStackFrame());
return std::make_shared<PathDiagnosticEventPiece>(Pos, OS.str(), true);
}

View file

@ -190,7 +190,7 @@ RuntimeType inferReceiverType(const ObjCMethodCall &Message,
return {cast<ObjCObjectType>(DTI.getType()), !DTI.canBeASubClass()};
}
SVal SelfSVal = State->getSelfSVal(C.getLocationContext());
SVal SelfSVal = State->getSelfSVal(C.getStackFrame());
// Another way we can guess what is in Class object, is when it is a
// 'self' variable of the current class method.
@ -369,7 +369,7 @@ void DynamicTypePropagation::checkPostCall(const CallEvent &Call,
if (const MemRegion *Target = Ctor->getCXXThisVal().getAsRegion()) {
// We just finished a base constructor. Now we can use the subclass's
// type when resolving virtual calls.
const LocationContext *LCtx = C.getLocationContext();
const StackFrame *SF = C.getStackFrame();
// FIXME: In C++17 classes with non-virtual bases may be treated as
// aggregates, and in such case no top-frame constructor will be called.
@ -378,10 +378,10 @@ void DynamicTypePropagation::checkPostCall(const CallEvent &Call,
// trigger-statement (InitListExpr or CXXParenListInitExpr in this case)
// available in this callback, ideally as part of CallEvent.
if (isa_and_nonnull<InitListExpr, CXXParenListInitExpr>(
LCtx->getParentMap().getParent(Ctor->getOriginExpr())))
SF->getParentMap().getParent(Ctor->getOriginExpr())))
return;
recordFixedType(Target, cast<CXXConstructorDecl>(LCtx->getDecl()), C);
recordFixedType(Target, cast<CXXConstructorDecl>(SF->getDecl()), C);
}
return;
}
@ -1090,8 +1090,7 @@ PathDiagnosticPieceRef DynamicTypePropagation::GenericsBugVisitor::VisitNode(
}
// Generate the extra diagnostic.
PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
N->getLocationContext());
PathDiagnosticLocation Pos(S, BRC.getSourceManager(), N->getStackFrame());
return std::make_shared<PathDiagnosticEventPiece>(Pos, OS.str(), true);
}

View file

@ -40,8 +40,8 @@ public:
checkRegionChanges(ProgramStateRef State,
const InvalidatedSymbols *Invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const LocationContext *LCtx, const CallEvent *Call) const;
ArrayRef<const MemRegion *> Regions, const StackFrame *SF,
const CallEvent *Call) const;
/// Indicates if a read (load) of \c errno is allowed in a non-condition part
/// of \c if, \c switch, loop and conditional statements when the errno
@ -217,7 +217,7 @@ void ErrnoChecker::checkPreCall(const CallEvent &Call,
ProgramStateRef ErrnoChecker::checkRegionChanges(
ProgramStateRef State, const InvalidatedSymbols *Invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions, const LocationContext *LCtx,
ArrayRef<const MemRegion *> Regions, const StackFrame *SF,
const CallEvent *Call) const {
std::optional<ento::Loc> ErrnoLoc = getErrnoLoc(State);
if (!ErrnoLoc)

View file

@ -103,7 +103,7 @@ void ErrnoModeling::checkBeginFunction(CheckerContext &C) const {
if (ErrnoDecl) {
// There is an external 'errno' variable, so we can simply use the memory
// region that's associated with it.
ErrnoR = State->getRegion(ErrnoDecl, C.getLocationContext());
ErrnoR = State->getRegion(ErrnoDecl, C.getStackFrame());
assert(ErrnoR && "Memory region should exist for the 'errno' variable.");
} else {
// There is no 'errno' variable, so create a new symbolic memory region
@ -122,7 +122,7 @@ void ErrnoModeling::checkBeginFunction(CheckerContext &C) const {
// of the data member `ErrnoDecl` of the singleton `ErrnoModeling` checker
// object.
const SymbolConjured *Sym = SVB.conjureSymbol(
C.getCFGElementRef(), C.getLocationContext(),
C.getCFGElementRef(), C.getStackFrame(),
ACtx.getLValueReferenceType(ACtx.IntTy), C.blockCount(), &ErrnoDecl);
// The symbolic region is untyped, create a typed sub-region in it.
@ -148,7 +148,7 @@ bool ErrnoModeling::evalCall(const CallEvent &Call, CheckerContext &C) const {
if (!ErrnoR)
return false;
State = State->BindExpr(Call.getOriginExpr(), C.getLocationContext(),
State = State->BindExpr(Call.getOriginExpr(), C.getStackFrame(),
loc::MemRegionVal{ErrnoR});
C.addTransition(State);
return true;
@ -176,15 +176,14 @@ std::optional<SVal> getErrnoValue(ProgramStateRef State) {
return State->getSVal(ErrnoR, IntTy);
}
ProgramStateRef setErrnoValue(ProgramStateRef State,
const LocationContext *LCtx, SVal Value,
ErrnoCheckState EState) {
ProgramStateRef setErrnoValue(ProgramStateRef State, const StackFrame *SF,
SVal Value, ErrnoCheckState EState) {
const MemRegion *ErrnoR = State->get<ErrnoRegion>();
if (!ErrnoR)
return State;
// First set the errno value, the old state is still available at 'checkBind'
// or 'checkLocation' for errno value.
State = State->bindLoc(loc::MemRegionVal{ErrnoR}, Value, LCtx);
State = State->bindLoc(loc::MemRegionVal{ErrnoR}, Value, SF);
return State->set<ErrnoState>(EState);
}
@ -196,7 +195,7 @@ ProgramStateRef setErrnoValue(ProgramStateRef State, CheckerContext &C,
State = State->bindLoc(
loc::MemRegionVal{ErrnoR},
C.getSValBuilder().makeIntVal(Value, C.getASTContext().IntTy),
C.getLocationContext());
C.getStackFrame());
return State->set<ErrnoState>(EState);
}
@ -249,7 +248,7 @@ ProgramStateRef setErrnoForStdFailure(ProgramStateRef State, CheckerContext &C,
State = State->assume(Cond, true);
if (!State)
return nullptr;
return setErrnoValue(State, C.getLocationContext(), ErrnoSym, Irrelevant);
return setErrnoValue(State, C.getStackFrame(), ErrnoSym, Irrelevant);
}
ProgramStateRef setErrnoStdMustBeChecked(ProgramStateRef State,
@ -259,7 +258,7 @@ ProgramStateRef setErrnoStdMustBeChecked(ProgramStateRef State,
if (!ErrnoR)
return State;
State = State->invalidateRegions(ErrnoR, Elem, C.blockCount(),
C.getLocationContext(), false);
C.getStackFrame(), false);
if (!State)
return nullptr;
return setErrnoState(State, MustBeChecked);

View file

@ -56,9 +56,8 @@ std::optional<Loc> getErrnoLoc(ProgramStateRef State);
/// Set value of 'errno' to any SVal, if possible.
/// The errno check state is set always when the 'errno' value is set.
ProgramStateRef setErrnoValue(ProgramStateRef State,
const LocationContext *LCtx, SVal Value,
ErrnoCheckState EState);
ProgramStateRef setErrnoValue(ProgramStateRef State, const StackFrame *SF,
SVal Value, ErrnoCheckState EState);
/// Set value of 'errno' to a concrete (signed) integer, if possible.
/// The errno check state is set always when the 'errno' value is set.

View file

@ -86,7 +86,7 @@ private:
void ErrnoTesterChecker::evalSetErrno(CheckerContext &C,
const CallEvent &Call) {
C.addTransition(setErrnoValue(C.getState(), C.getLocationContext(),
C.addTransition(setErrnoValue(C.getState(), C.getStackFrame(),
Call.getArgSVal(0), Irrelevant));
}
@ -96,8 +96,7 @@ void ErrnoTesterChecker::evalGetErrno(CheckerContext &C,
std::optional<SVal> ErrnoVal = getErrnoValue(State);
assert(ErrnoVal && "Errno value should be available.");
State =
State->BindExpr(Call.getOriginExpr(), C.getLocationContext(), *ErrnoVal);
State = State->BindExpr(Call.getOriginExpr(), C.getStackFrame(), *ErrnoVal);
C.addTransition(State);
}
@ -108,11 +107,11 @@ void ErrnoTesterChecker::evalSetErrnoIfError(CheckerContext &C,
SValBuilder &SVB = C.getSValBuilder();
ProgramStateRef StateSuccess = State->BindExpr(
Call.getOriginExpr(), C.getLocationContext(), SVB.makeIntVal(0, true));
Call.getOriginExpr(), C.getStackFrame(), SVB.makeIntVal(0, true));
StateSuccess = setErrnoState(StateSuccess, MustNotBeChecked);
ProgramStateRef StateFailure = State->BindExpr(
Call.getOriginExpr(), C.getLocationContext(), SVB.makeIntVal(1, true));
Call.getOriginExpr(), C.getStackFrame(), SVB.makeIntVal(1, true));
StateFailure = setErrnoValue(StateFailure, C, 11, Irrelevant);
C.addTransition(StateSuccess);
@ -125,16 +124,16 @@ void ErrnoTesterChecker::evalSetErrnoIfErrorRange(CheckerContext &C,
SValBuilder &SVB = C.getSValBuilder();
ProgramStateRef StateSuccess = State->BindExpr(
Call.getOriginExpr(), C.getLocationContext(), SVB.makeIntVal(0, true));
Call.getOriginExpr(), C.getStackFrame(), SVB.makeIntVal(0, true));
StateSuccess = setErrnoState(StateSuccess, MustNotBeChecked);
ProgramStateRef StateFailure = State->BindExpr(
Call.getOriginExpr(), C.getLocationContext(), SVB.makeIntVal(1, true));
Call.getOriginExpr(), C.getStackFrame(), SVB.makeIntVal(1, true));
DefinedOrUnknownSVal ErrnoVal = SVB.conjureSymbolVal(Call, C.blockCount());
StateFailure = StateFailure->assume(ErrnoVal, true);
assert(StateFailure && "Failed to assume on an initial value.");
StateFailure =
setErrnoValue(StateFailure, C.getLocationContext(), ErrnoVal, Irrelevant);
setErrnoValue(StateFailure, C.getStackFrame(), ErrnoVal, Irrelevant);
C.addTransition(StateSuccess);
C.addTransition(StateFailure);
@ -146,15 +145,15 @@ void ErrnoTesterChecker::evalSetErrnoCheckState(CheckerContext &C,
SValBuilder &SVB = C.getSValBuilder();
ProgramStateRef StateSuccess = State->BindExpr(
Call.getOriginExpr(), C.getLocationContext(), SVB.makeIntVal(0, true));
Call.getOriginExpr(), C.getStackFrame(), SVB.makeIntVal(0, true));
StateSuccess = setErrnoState(StateSuccess, MustNotBeChecked);
ProgramStateRef StateFailure1 = State->BindExpr(
Call.getOriginExpr(), C.getLocationContext(), SVB.makeIntVal(1, true));
Call.getOriginExpr(), C.getStackFrame(), SVB.makeIntVal(1, true));
StateFailure1 = setErrnoValue(StateFailure1, C, 1, Irrelevant);
ProgramStateRef StateFailure2 = State->BindExpr(
Call.getOriginExpr(), C.getLocationContext(), SVB.makeIntVal(2, true));
Call.getOriginExpr(), C.getStackFrame(), SVB.makeIntVal(2, true));
StateFailure2 = setErrnoValue(StateFailure2, C, 2, MustBeChecked);
C.addTransition(StateSuccess,

View file

@ -136,11 +136,11 @@ static const char *getArgumentValueString(const CallExpr *CE,
return "Missing assertion argument";
ExplodedNode *N = C.getPredecessor();
const LocationContext *LC = N->getLocationContext();
const StackFrame *SF = N->getStackFrame();
ProgramStateRef State = N->getState();
const Expr *Assertion = CE->getArg(0);
SVal AssertionVal = State->getSVal(Assertion, LC);
SVal AssertionVal = State->getSVal(Assertion, SF);
if (AssertionVal.isUndef())
return "UNDEFINED";
@ -210,11 +210,11 @@ const MemRegion *ExprInspectionChecker::getArgRegion(const CallExpr *CE,
void ExprInspectionChecker::analyzerEval(const CallExpr *CE,
CheckerContext &C) const {
const LocationContext *LC = C.getPredecessor()->getLocationContext();
const StackFrame *SF = C.getPredecessor()->getStackFrame();
// A specific instantiation of an inlined function may have more constrained
// values than can generally be assumed. Skip the check.
if (LC->getStackFrame()->getParent() != nullptr)
if (SF->getParent() != nullptr)
return;
reportBug(getArgumentValueString(CE, C), C);
@ -237,14 +237,14 @@ void ExprInspectionChecker::analyzerNumTimesReached(const CallExpr *CE,
void ExprInspectionChecker::analyzerCheckInlined(const CallExpr *CE,
CheckerContext &C) const {
const LocationContext *LC = C.getPredecessor()->getLocationContext();
const StackFrame *SF = C.getPredecessor()->getStackFrame();
// An inlined function could conceivably also be analyzed as a top-level
// function. We ignore this case and only emit a message (TRUE or FALSE)
// when we are analyzing it as an inlined function. This means that
// clang_analyzer_checkInlined(true) should always print TRUE, but
// clang_analyzer_checkInlined(false) should never actually print anything.
if (LC->getStackFrame()->getParent() == nullptr)
if (SF->getParent() == nullptr)
return;
reportBug(getArgumentValueString(CE, C), C);
@ -329,7 +329,7 @@ void ExprInspectionChecker::analyzerGetExtent(const CallExpr *CE,
ProgramStateRef State = C.getState();
SVal Size = getDynamicExtentWithOffset(State, C.getSVal(Arg));
State = State->BindExpr(CE, C.getLocationContext(), Size);
State = State->BindExpr(CE, C.getStackFrame(), Size);
C.addTransition(State);
}
@ -430,8 +430,8 @@ void ExprInspectionChecker::analyzerHashDump(const CallExpr *CE,
const LangOptions &Opts = C.getLangOpts();
const SourceManager &SM = C.getSourceManager();
FullSourceLoc FL(CE->getArg(0)->getBeginLoc(), SM);
std::string HashContent = getIssueString(
FL, getName(), "Category", C.getLocationContext()->getDecl(), Opts);
std::string HashContent = getIssueString(FL, getName(), "Category",
C.getStackFrame()->getDecl(), Opts);
reportBug(HashContent, C);
}
@ -551,7 +551,7 @@ void ExprInspectionChecker::analyzerIsTainted(const CallExpr *CE,
return;
}
const bool IsTainted =
taint::isTainted(C.getState(), CE->getArg(0), C.getLocationContext());
taint::isTainted(C.getState(), CE->getArg(0), C.getStackFrame());
reportBug(IsTainted ? "YES" : "NO", C);
}

View file

@ -656,12 +656,12 @@ void FuchsiaHandleChecker::reportBug(SymbolRef Sym, ExplodedNode *ErrorNode,
const Stmt *S = AcquireNode->getStmtForDiagnostics();
assert(S && "Statement cannot be null.");
PathDiagnosticLocation LocUsedForUniqueing =
PathDiagnosticLocation::createBegin(
S, C.getSourceManager(), AcquireNode->getLocationContext());
PathDiagnosticLocation::createBegin(S, C.getSourceManager(),
AcquireNode->getStackFrame());
R = std::make_unique<PathSensitiveBugReport>(
Type, Msg, ErrorNode, LocUsedForUniqueing,
AcquireNode->getLocationContext()->getDecl());
AcquireNode->getStackFrame()->getDecl());
}
}
if (!R)

View file

@ -149,12 +149,12 @@ bool isTaintedOrPointsToTainted(ProgramStateRef State, SVal ExprSVal) {
const NoteTag *taintOriginTrackerTag(CheckerContext &C,
std::vector<SymbolRef> TaintedSymbols,
std::vector<ArgIdxTy> TaintedArgs,
const LocationContext *CallLocation) {
const StackFrame *CallSF) {
return C.getNoteTag([TaintedSymbols = std::move(TaintedSymbols),
TaintedArgs = std::move(TaintedArgs), CallLocation](
PathSensitiveBugReport &BR) -> std::string {
TaintedArgs = std::move(TaintedArgs),
CallSF](PathSensitiveBugReport &BR) -> std::string {
// We give diagnostics only for taint related reports
if (!BR.isInteresting(CallLocation) ||
if (!BR.isInteresting(CallSF) ||
BR.getBugType().getCategory() != categories::TaintedData) {
return "";
}
@ -177,11 +177,11 @@ const NoteTag *taintOriginTrackerTag(CheckerContext &C,
/// when the return value, or the outgoing parameters are tainted.
const NoteTag *taintPropagationExplainerTag(
CheckerContext &C, std::vector<SymbolRef> TaintedSymbols,
std::vector<ArgIdxTy> TaintedArgs, const LocationContext *CallLocation) {
std::vector<ArgIdxTy> TaintedArgs, const StackFrame *CallSF) {
assert(TaintedSymbols.size() == TaintedArgs.size());
return C.getNoteTag([TaintedSymbols = std::move(TaintedSymbols),
TaintedArgs = std::move(TaintedArgs), CallLocation](
PathSensitiveBugReport &BR) -> std::string {
TaintedArgs = std::move(TaintedArgs),
CallSF](PathSensitiveBugReport &BR) -> std::string {
SmallString<256> Msg;
llvm::raw_svector_ostream Out(Msg);
// We give diagnostics only for taint related reports
@ -192,7 +192,7 @@ const NoteTag *taintPropagationExplainerTag(
int nofTaintedArgs = 0;
for (auto [Idx, Sym] : llvm::enumerate(TaintedSymbols)) {
if (BR.isInteresting(Sym)) {
BR.markInteresting(CallLocation);
BR.markInteresting(CallSF);
if (TaintedArgs[Idx] != ReturnValueIndex) {
LLVM_DEBUG(llvm::dbgs() << "Taint Propagated to argument "
<< TaintedArgs[Idx] + 1 << "\n");
@ -471,7 +471,7 @@ template <> struct ScalarEnumerationTraits<TaintConfiguration::VariadicType> {
/// to the call post-visit. The values are signed integers, which are either
/// ReturnValueIndex, or indexes of the pointer/reference argument, which
/// points to data, which should be tainted on return.
REGISTER_MAP_WITH_PROGRAMSTATE(TaintArgsOnPostVisit, const LocationContext *,
REGISTER_MAP_WITH_PROGRAMSTATE(TaintArgsOnPostVisit, const StackFrame *,
ImmutableSet<ArgIdxTy>)
REGISTER_SET_FACTORY_WITH_PROGRAMSTATE(ArgIdxFactory, ArgIdxTy)
@ -847,7 +847,7 @@ void GenericTaintChecker::checkBeginFunction(CheckerContext &C) const {
.ShouldAssumeControlledEnvironment)
return;
const auto *FD = dyn_cast<FunctionDecl>(C.getLocationContext()->getDecl());
const auto *FD = dyn_cast<FunctionDecl>(C.getStackFrame()->getDecl());
if (!FD || !FD->isMain() || FD->param_size() < 2)
return;
@ -859,7 +859,7 @@ void GenericTaintChecker::checkBeginFunction(CheckerContext &C) const {
ProgramStateRef State = C.getState();
const MemRegion *ArgcReg =
State->getRegion(FD->parameters()[0], C.getLocationContext());
State->getRegion(FD->parameters()[0], C.getStackFrame());
SVal ArgcSVal = State->getSVal(ArgcReg);
State = addTaint(State, ArgcSVal);
StringRef ArgcName = FD->parameters()[0]->getName();
@ -872,7 +872,7 @@ void GenericTaintChecker::checkBeginFunction(CheckerContext &C) const {
}
const MemRegion *ArgvReg =
State->getRegion(FD->parameters()[1], C.getLocationContext());
State->getRegion(FD->parameters()[1], C.getStackFrame());
SVal ArgvSVal = State->getSVal(ArgvReg);
State = addTaint(State, ArgvSVal);
StringRef ArgvName = FD->parameters()[1]->getName();
@ -884,7 +884,7 @@ void GenericTaintChecker::checkBeginFunction(CheckerContext &C) const {
return;
if (HaveEnvp) {
const MemRegion *EnvPReg =
State->getRegion(FD->parameters()[2], C.getLocationContext());
State->getRegion(FD->parameters()[2], C.getStackFrame());
EnvpSVal = State->getSVal(EnvPReg);
EnvpName = FD->parameters()[2]->getName();
State = addTaint(State, EnvpSVal);

View file

@ -309,8 +309,7 @@ PathDiagnosticPieceRef InnerPointerChecker::InnerPointerBRVisitor::VisitNode(
SmallString<256> Buf;
llvm::raw_svector_ostream OS(Buf);
OS << "Pointer to inner buffer of '" << ObjTy << "' obtained here";
PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
N->getLocationContext());
PathDiagnosticLocation Pos(S, BRC.getSourceManager(), N->getStackFrame());
return std::make_shared<PathDiagnosticEventPiece>(Pos, OS.str(), true);
}

View file

@ -74,7 +74,7 @@ void InvalidatedIteratorChecker::checkPreStmt(const UnaryOperator *UO,
ProgramStateRef State = C.getState();
UnaryOperatorKind OK = UO->getOpcode();
SVal SubVal = State->getSVal(UO->getSubExpr(), C.getLocationContext());
SVal SubVal = State->getSVal(UO->getSubExpr(), C.getStackFrame());
if (isAccessOperator(OK)) {
verifyAccess(C, SubVal);
@ -85,7 +85,7 @@ void InvalidatedIteratorChecker::checkPreStmt(const BinaryOperator *BO,
CheckerContext &C) const {
ProgramStateRef State = C.getState();
BinaryOperatorKind OK = BO->getOpcode();
SVal LVal = State->getSVal(BO->getLHS(), C.getLocationContext());
SVal LVal = State->getSVal(BO->getLHS(), C.getStackFrame());
if (isAccessOperator(OK)) {
verifyAccess(C, LVal);
@ -95,7 +95,7 @@ void InvalidatedIteratorChecker::checkPreStmt(const BinaryOperator *BO,
void InvalidatedIteratorChecker::checkPreStmt(const ArraySubscriptExpr *ASE,
CheckerContext &C) const {
ProgramStateRef State = C.getState();
SVal LVal = State->getSVal(ASE->getLHS(), C.getLocationContext());
SVal LVal = State->getSVal(ASE->getLHS(), C.getStackFrame());
verifyAccess(C, LVal);
}
@ -105,7 +105,7 @@ void InvalidatedIteratorChecker::checkPreStmt(const MemberExpr *ME,
return;
ProgramStateRef State = C.getState();
SVal BaseVal = State->getSVal(ME->getBase(), C.getLocationContext());
SVal BaseVal = State->getSVal(ME->getBase(), C.getStackFrame());
verifyAccess(C, BaseVal);
}

View file

@ -209,13 +209,13 @@ ProgramStateRef setIteratorPosition(ProgramStateRef State, SVal Val,
ProgramStateRef createIteratorPosition(ProgramStateRef State, SVal Val,
const MemRegion *Cont,
ConstCFGElementRef Elem,
const LocationContext *LCtx,
const StackFrame *SF,
unsigned blockCount) {
auto &StateMgr = State->getStateManager();
auto &SymMgr = StateMgr.getSymbolManager();
auto &ACtx = StateMgr.getContext();
auto *Sym = SymMgr.conjureSymbol(Elem, LCtx, ACtx.LongTy, blockCount);
auto *Sym = SymMgr.conjureSymbol(Elem, SF, ACtx.LongTy, blockCount);
State = assumeNoOverflow(State, Sym, 4);
return setIteratorPosition(State, Val,
IteratorPosition::getPosition(Cont, Sym));

View file

@ -167,7 +167,7 @@ ProgramStateRef setIteratorPosition(ProgramStateRef State, SVal Val,
ProgramStateRef createIteratorPosition(ProgramStateRef State, SVal Val,
const MemRegion *Cont,
ConstCFGElementRef Elem,
const LocationContext *LCtx,
const StackFrame *SF,
unsigned blockCount);
ProgramStateRef advancePosition(ProgramStateRef State, SVal Iter,
OverloadedOperatorKind Op, SVal Distance);

View file

@ -268,11 +268,11 @@ void IteratorModeling::checkPostStmt(const BinaryOperator *BO,
const BinaryOperatorKind OK = BO->getOpcode();
const Expr *const LHS = BO->getLHS();
const Expr *const RHS = BO->getRHS();
const SVal LVal = State->getSVal(LHS, C.getLocationContext());
const SVal RVal = State->getSVal(RHS, C.getLocationContext());
const SVal LVal = State->getSVal(LHS, C.getStackFrame());
const SVal RVal = State->getSVal(RHS, C.getStackFrame());
if (isSimpleComparisonOperator(BO->getOpcode())) {
SVal Result = State->getSVal(BO, C.getLocationContext());
SVal Result = State->getSVal(BO, C.getStackFrame());
handleComparison(C, BO, C.getCFGElementRef(), Result, LVal, RVal,
BinaryOperator::getOverloadedOperator(OK));
} else if (isRandomIncrOrDecrOperator(OK)) {
@ -472,7 +472,7 @@ void IteratorModeling::handleComparison(CheckerContext &C, const Expr *CE,
SymbolRef Sym;
if (!LPos || !RPos) {
auto &SymMgr = C.getSymbolManager();
Sym = SymMgr.conjureSymbol(Elem, C.getLocationContext(),
Sym = SymMgr.conjureSymbol(Elem, C.getStackFrame(),
C.getASTContext().LongTy, C.blockCount());
State = assumeNoOverflow(State, Sym, 4);
}
@ -497,10 +497,10 @@ void IteratorModeling::handleComparison(CheckerContext &C, const Expr *CE,
// instead.
if (RetVal.isUnknown()) {
auto &SymMgr = C.getSymbolManager();
auto *LCtx = C.getLocationContext();
auto *SF = C.getStackFrame();
RetVal = nonloc::SymbolVal(SymMgr.conjureSymbol(
Elem, LCtx, C.getASTContext().BoolTy, C.blockCount()));
State = State->BindExpr(CE, LCtx, RetVal);
Elem, SF, C.getASTContext().BoolTy, C.blockCount()));
State = State->BindExpr(CE, SF, RetVal);
}
processComparison(C, State, LPos->getOffset(), RPos->getOffset(), RetVal, Op);
@ -641,7 +641,7 @@ void IteratorModeling::handlePtrIncrOrDecr(CheckerContext &C,
QualType ElementType = PtrType->getPointeeType();
ProgramStateRef State = C.getState();
SVal OldVal = State->getSVal(Iterator, C.getLocationContext());
SVal OldVal = State->getSVal(Iterator, C.getStackFrame());
const IteratorPosition *OldPos = getIteratorPosition(State, OldVal);
if (!OldPos)
@ -694,9 +694,8 @@ void IteratorModeling::assignToContainer(CheckerContext &C,
Cont = Cont->getMostDerivedObjectRegion();
auto State = C.getState();
const auto *LCtx = C.getLocationContext();
State =
createIteratorPosition(State, RetVal, Cont, Elem, LCtx, C.blockCount());
const auto *SF = C.getStackFrame();
State = createIteratorPosition(State, RetVal, Cont, Elem, SF, C.blockCount());
C.addTransition(State);
}

View file

@ -147,7 +147,7 @@ void IteratorRangeChecker::checkPreStmt(const UnaryOperator *UO,
ProgramStateRef State = C.getState();
UnaryOperatorKind OK = UO->getOpcode();
SVal SubVal = State->getSVal(UO->getSubExpr(), C.getLocationContext());
SVal SubVal = State->getSVal(UO->getSubExpr(), C.getStackFrame());
if (isDereferenceOperator(OK)) {
verifyDereference(C, SubVal);
@ -162,12 +162,12 @@ void IteratorRangeChecker::checkPreStmt(const BinaryOperator *BO,
CheckerContext &C) const {
ProgramStateRef State = C.getState();
BinaryOperatorKind OK = BO->getOpcode();
SVal LVal = State->getSVal(BO->getLHS(), C.getLocationContext());
SVal LVal = State->getSVal(BO->getLHS(), C.getStackFrame());
if (isDereferenceOperator(OK)) {
verifyDereference(C, LVal);
} else if (isRandomIncrOrDecrOperator(OK)) {
SVal RVal = State->getSVal(BO->getRHS(), C.getLocationContext());
SVal RVal = State->getSVal(BO->getRHS(), C.getStackFrame());
if (!BO->getRHS()->getType()->isIntegralOrEnumerationType())
return;
verifyRandomIncrOrDecr(C, BinaryOperator::getOverloadedOperator(OK), LVal,
@ -178,7 +178,7 @@ void IteratorRangeChecker::checkPreStmt(const BinaryOperator *BO,
void IteratorRangeChecker::checkPreStmt(const ArraySubscriptExpr *ASE,
CheckerContext &C) const {
ProgramStateRef State = C.getState();
SVal LVal = State->getSVal(ASE->getLHS(), C.getLocationContext());
SVal LVal = State->getSVal(ASE->getLHS(), C.getStackFrame());
verifyDereference(C, LVal);
}
@ -188,7 +188,7 @@ void IteratorRangeChecker::checkPreStmt(const MemberExpr *ME,
return;
ProgramStateRef State = C.getState();
SVal BaseVal = State->getSVal(ME->getBase(), C.getLocationContext());
SVal BaseVal = State->getSVal(ME->getBase(), C.getStackFrame());
verifyDereference(C, BaseVal);
}

View file

@ -1031,7 +1031,7 @@ class EmptyLocalizationContextChecker
BugReporter &BR;
AnalysisManager &Mgr;
const CheckerBase *Checker;
LocationOrAnalysisDeclContext DCtx;
StackFrameOrAnalysisDeclContext DCtx;
public:
MethodCrawler(const ObjCMethodDecl *InMD, BugReporter &InBR,

View file

@ -149,14 +149,12 @@ static const ParmVarDecl *getOriginParam(SVal V, CheckerContext &C,
}
static bool isInMIGCall(CheckerContext &C) {
const LocationContext *LC = C.getLocationContext();
assert(LC && "Unknown location context");
const StackFrame *SF = C.getStackFrame();
assert(SF && "Unknown stack frame");
const StackFrame *SF;
// Find the top frame.
while (LC) {
SF = LC->getStackFrame();
LC = SF->getParent();
while (SF->getParent()) {
SF = SF->getParent();
}
const Decl *D = SF->getDecl();

View file

@ -408,7 +408,7 @@ void MacOSKeychainAPIChecker::checkPostStmt(const CallExpr *CE,
// If the argument entered as an enclosing function parameter, skip it to
// avoid false positives.
if (isEnclosingFunctionParam(ArgExpr) &&
C.getLocationContext()->getParent() == nullptr)
C.getStackFrame()->getParent() == nullptr)
return;
if (SymbolRef V = getAsPointeeSymbol(ArgExpr, C)) {
@ -440,7 +440,7 @@ const ExplodedNode *
MacOSKeychainAPIChecker::getAllocationNode(const ExplodedNode *N,
SymbolRef Sym,
CheckerContext &C) const {
const LocationContext *LeakContext = N->getLocationContext();
const StackFrame *LeakStackFrame = N->getStackFrame();
// Walk the ExplodedGraph backwards and find the first node that referred to
// the tracked symbol.
const ExplodedNode *AllocNode = N;
@ -450,9 +450,8 @@ MacOSKeychainAPIChecker::getAllocationNode(const ExplodedNode *N,
break;
// Allocation node, is the last node in the current or parent context in
// which the symbol was tracked.
const LocationContext *NContext = N->getLocationContext();
if (NContext == LeakContext ||
NContext->isParentOf(LeakContext))
const StackFrame *NSF = N->getStackFrame();
if (NSF == LeakStackFrame || NSF->isParentOf(LeakStackFrame))
AllocNode = N;
N = N->pred_empty() ? nullptr : *(N->pred_begin());
}
@ -477,13 +476,12 @@ MacOSKeychainAPIChecker::generateAllocatedDataNotReleasedReport(
const Stmt *AllocStmt = AllocNode->getStmtForDiagnostics();
if (AllocStmt)
LocUsedForUniqueing = PathDiagnosticLocation::createBegin(AllocStmt,
C.getSourceManager(),
AllocNode->getLocationContext());
LocUsedForUniqueing = PathDiagnosticLocation::createBegin(
AllocStmt, C.getSourceManager(), AllocNode->getStackFrame());
auto Report = std::make_unique<PathSensitiveBugReport>(
BT, os.str(), N, LocUsedForUniqueing,
AllocNode->getLocationContext()->getDecl());
AllocNode->getStackFrame()->getDecl());
Report->addVisitor(std::make_unique<SecKeychainBugVisitor>(AP.first));
markInteresting(Report.get(), AP);
@ -631,7 +629,7 @@ MacOSKeychainAPIChecker::SecKeychainBugVisitor::VisitNode(
assert(Idx != InvalidIdx && "This should be a call to an allocator.");
const Expr *ArgExpr = CE->getArg(FunctionsToTrack[Idx].Param);
PathDiagnosticLocation Pos(ArgExpr, BRC.getSourceManager(),
N->getLocationContext());
N->getStackFrame());
return std::make_shared<PathDiagnosticEventPiece>(Pos,
"Data is allocated here.");
}

View file

@ -985,14 +985,14 @@ protected:
// A release function stack frame in which memory was released. Used for
// miscellaneous false positive suppression.
const StackFrame *ReleaseFunctionLC;
const StackFrame *ReleaseFunctionSF;
bool IsLeak;
public:
MallocBugVisitor(SymbolRef S, bool isLeak = false)
: Sym(S), Mode(Normal), FailedReallocSymbol(nullptr),
ReleaseFunctionLC(nullptr), IsLeak(isLeak) {}
ReleaseFunctionSF(nullptr), IsLeak(isLeak) {}
static void *getTag() {
static int Tag = 0;
@ -1491,8 +1491,8 @@ void MallocChecker::checkCXXNewOrCXXDelete(ProgramStateRef State,
const FunctionDecl *FD = C.getCalleeDecl(CE);
if (const auto *BufArg = getPlacementNewBufferArg(CE, FD)) {
// Placement new does not allocate memory
auto RetVal = State->getSVal(BufArg, Call.getLocationContext());
State = State->BindExpr(CE, C.getLocationContext(), RetVal);
auto RetVal = State->getSVal(BufArg, Call.getStackFrame());
State = State->BindExpr(CE, C.getStackFrame(), RetVal);
C.addTransition(State);
return;
}
@ -1739,12 +1739,12 @@ ProgramStateRef MallocChecker::ProcessZeroAllocCheck(
}
if (!RetVal)
RetVal = State->getSVal(Call.getOriginExpr(), C.getLocationContext());
RetVal = State->getSVal(Call.getOriginExpr(), C.getStackFrame());
assert(Arg);
auto DefArgVal =
State->getSVal(Arg, Call.getLocationContext()).getAs<DefinedSVal>();
State->getSVal(Arg, Call.getStackFrame()).getAs<DefinedSVal>();
if (!DefArgVal)
return State;
@ -1828,7 +1828,7 @@ MallocChecker::processNewAllocation(const CXXAllocatorCall &Call,
return nullptr;
const CXXNewExpr *NE = Call.getOriginExpr();
const ParentMap &PM = C.getLocationContext()->getParentMap();
const ParentMap &PM = C.getStackFrame()->getParentMap();
ProgramStateRef State = C.getState();
// Non-trivial constructors have a chance to escape 'this', but marking all
@ -1942,12 +1942,12 @@ ProgramStateRef MallocChecker::MallocBindRetVal(CheckerContext &C,
unsigned Count = C.blockCount();
SValBuilder &SVB = C.getSValBuilder();
const LocationContext *LCtx = C.getPredecessor()->getLocationContext();
const StackFrame *SF = C.getPredecessor()->getStackFrame();
DefinedSVal RetVal =
isAlloca ? SVB.getAllocaRegionVal(CE, LCtx, Count)
: SVB.getConjuredHeapSymbolVal(Call.getCFGElementRef(), LCtx,
isAlloca ? SVB.getAllocaRegionVal(CE, SF, Count)
: SVB.getConjuredHeapSymbolVal(Call.getCFGElementRef(), SF,
CE->getType(), Count);
return State->BindExpr(CE, C.getLocationContext(), RetVal);
return State->BindExpr(CE, C.getStackFrame(), RetVal);
}
ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
@ -2029,11 +2029,11 @@ ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
assert(Loc::isLocType(CE->getType()) &&
"Allocation functions must return a pointer");
const LocationContext *LCtx = C.getPredecessor()->getLocationContext();
SVal RetVal = State->getSVal(CE, C.getLocationContext());
const StackFrame *SF = C.getPredecessor()->getStackFrame();
SVal RetVal = State->getSVal(CE, C.getStackFrame());
// Fill the region with the initialization value.
State = State->bindDefaultInitial(RetVal, Init, LCtx);
State = State->bindDefaultInitial(RetVal, Init, SF);
// If Size is somehow undefined at this point, this line prevents a crash.
if (Size.isUndef())
@ -2057,7 +2057,7 @@ static ProgramStateRef MallocUpdateRefState(CheckerContext &C, const Expr *E,
// Get the return value.
if (!RetVal)
RetVal = State->getSVal(E, C.getLocationContext());
RetVal = State->getSVal(E, C.getStackFrame());
// We expect the malloc functions to return a pointer.
if (!RetVal->getAs<Loc>())
@ -2415,7 +2415,7 @@ MallocChecker::FreeMemAux(CheckerContext &C, const Expr *ArgExpr,
// conforts languages standards, since reading from freed memory is considered
// UB and may result in arbitrary value.
State = State->invalidateRegions({location}, Call.getCFGElementRef(),
C.blockCount(), C.getLocationContext(),
C.blockCount(), C.getStackFrame(),
/*CausesPointerEscape=*/false,
/*InvalidatedSymbols=*/nullptr);
@ -2940,7 +2940,7 @@ MallocChecker::ReallocMemAux(CheckerContext &C, const CallEvent &Call,
// Get the from and to pointer symbols as in toPtr = realloc(fromPtr, size).
SymbolRef FromPtr = arg0Val.getLocSymbolInBase();
SVal RetVal = stateRealloc->getSVal(CE, C.getLocationContext());
SVal RetVal = stateRealloc->getSVal(CE, C.getStackFrame());
SymbolRef ToPtr = RetVal.getAsSymbol();
assert(FromPtr && ToPtr &&
"By this point, FreeMemAux and MallocMemAux should have checked "
@ -2978,7 +2978,7 @@ ProgramStateRef MallocChecker::CallocMem(CheckerContext &C,
MallocChecker::LeakInfo MallocChecker::getAllocationSite(const ExplodedNode *N,
SymbolRef Sym,
CheckerContext &C) {
const LocationContext *LeakContext = N->getLocationContext();
const StackFrame *LeakStackFrame = N->getStackFrame();
// Walk the ExplodedGraph backwards and find the first node that referred to
// the tracked symbol.
const ExplodedNode *AllocNode = N;
@ -2998,7 +2998,7 @@ MallocChecker::LeakInfo MallocChecker::getAllocationSite(const ExplodedNode *N,
const VarRegion *VR = MR->getBaseRegion()->getAs<VarRegion>();
// Do not show local variables belonging to a function other than
// where the error is reported.
if (!VR || (VR->getStackFrame() == LeakContext->getStackFrame()))
if (!VR || (VR->getStackFrame() == LeakStackFrame))
ReferenceRegion = MR;
}
}
@ -3006,9 +3006,8 @@ MallocChecker::LeakInfo MallocChecker::getAllocationSite(const ExplodedNode *N,
// Allocation node, is the last node in the current or parent context in
// which the symbol was tracked.
const LocationContext *NContext = N->getLocationContext();
if (NContext == LeakContext ||
NContext->isParentOf(LeakContext))
const StackFrame *NSF = N->getStackFrame();
if (NSF == LeakStackFrame || NSF->isParentOf(LeakStackFrame))
AllocNode = N;
N = N->pred_empty() ? nullptr : *(N->pred_begin());
}
@ -3044,9 +3043,8 @@ void MallocChecker::HandleLeak(SymbolRef Sym, ExplodedNode *N,
const Stmt *AllocationStmt = AllocNode->getStmtForDiagnostics();
if (AllocationStmt)
LocUsedForUniqueing = PathDiagnosticLocation::createBegin(AllocationStmt,
C.getSourceManager(),
AllocNode->getLocationContext());
LocUsedForUniqueing = PathDiagnosticLocation::createBegin(
AllocationStmt, C.getSourceManager(), AllocNode->getStackFrame());
SmallString<200> buf;
llvm::raw_svector_ostream os(buf);
@ -3059,7 +3057,7 @@ void MallocChecker::HandleLeak(SymbolRef Sym, ExplodedNode *N,
auto R = std::make_unique<PathSensitiveBugReport>(
Frontend->LeakBug, os.str(), N, LocUsedForUniqueing,
AllocNode->getLocationContext()->getDecl());
AllocNode->getStackFrame()->getDecl());
R->markInteresting(Sym);
R->addVisitor<MallocBugVisitor>(Sym, true);
if (ShouldRegisterNoOwnershipChangeVisitor)
@ -3528,14 +3526,13 @@ void MallocChecker::checkPostStmt(const BlockExpr *BE,
if (ReferencedVars.empty())
return;
SmallVector<const MemRegion*, 10> Regions;
const LocationContext *LC = C.getLocationContext();
SmallVector<const MemRegion *, 10> Regions;
MemRegionManager &MemMgr = C.getSValBuilder().getRegionManager();
for (const auto &Var : ReferencedVars) {
const VarRegion *VR = Var.getCapturedRegion();
if (VR->getSuperRegion() == R) {
VR = MemMgr.getVarRegion(VR->getDecl(), LC);
VR = MemMgr.getVarRegion(VR->getDecl(), C.getStackFrame());
}
Regions.push_back(VR);
}
@ -3936,7 +3933,7 @@ PathDiagnosticPieceRef MallocBugVisitor::VisitNode(const ExplodedNode *N,
if (!S && (!RSCurr || RSCurr->getAllocationFamily().Kind != AF_InnerBuffer))
return nullptr;
const LocationContext *CurrentLC = N->getLocationContext();
const StackFrame *CurrentSF = N->getStackFrame();
// If we find an atomic fetch_add or fetch_sub within the function in which
// the pointer was released (before the release), this is likely a release
@ -3946,8 +3943,8 @@ PathDiagnosticPieceRef MallocBugVisitor::VisitNode(const ExplodedNode *N,
// original reference count is positive, we should not report use-after-frees
// on objects deleted in such functions. This can probably be improved
// through better shared pointer modeling.
if (ReleaseFunctionLC && (ReleaseFunctionLC == CurrentLC ||
ReleaseFunctionLC->isParentOf(CurrentLC))) {
if (ReleaseFunctionSF && (ReleaseFunctionSF == CurrentSF ||
ReleaseFunctionSF->isParentOf(CurrentSF))) {
if (const auto *AE = dyn_cast<AtomicExpr>(S)) {
// Check for manual use of atomic builtins.
AtomicExpr::AtomicOp Op = AE->getOp();
@ -4024,7 +4021,7 @@ PathDiagnosticPieceRef MallocBugVisitor::VisitNode(const ExplodedNode *N,
} else if (const auto *CallE = dyn_cast<CallExpr>(S)) {
auto &CEMgr = BRC.getStateManager().getCallEventManager();
CallEventRef<> Call =
CEMgr.getSimpleCall(CallE, state, CurrentLC, {nullptr, 0});
CEMgr.getSimpleCall(CallE, state, CurrentSF, {nullptr, 0});
if (const auto *D = dyn_cast_or_null<NamedDecl>(Call->getDecl()))
OS << D->getDeclName();
else
@ -4048,11 +4045,11 @@ PathDiagnosticPieceRef MallocBugVisitor::VisitNode(const ExplodedNode *N,
//
// Usually (e.g. in C) we say that the _responsible_ stack frame is the
// current innermost stack frame:
ReleaseFunctionLC = CurrentLC->getStackFrame();
ReleaseFunctionSF = CurrentSF;
// ...but if the stack contains a destructor call, then we say that the
// outermost destructor stack frame is the _responsible_ one:
for (const LocationContext *LC = CurrentLC; LC; LC = LC->getParent()) {
if (const auto *DD = dyn_cast<CXXDestructorDecl>(LC->getDecl())) {
for (const StackFrame *SF = CurrentSF; SF; SF = SF->getParent()) {
if (const auto *DD = dyn_cast<CXXDestructorDecl>(SF->getDecl())) {
if (isReferenceCountingPointerDestructor(DD)) {
// This immediately looks like a reference-counting destructor.
// We're bad at guessing the original reference count of the
@ -4076,7 +4073,7 @@ PathDiagnosticPieceRef MallocBugVisitor::VisitNode(const ExplodedNode *N,
// free(buffer);
// }
//
// This way ReleaseFunctionLC will point to outermost destructor and
// This way ReleaseFunctionSF will point to outermost destructor and
// it would be possible to catch wider range of FP.
//
// NOTE: it would be great to support smth like that in C, since
@ -4088,7 +4085,7 @@ PathDiagnosticPieceRef MallocBugVisitor::VisitNode(const ExplodedNode *N,
// if (refPut(data))
// doFree(data);
// }
ReleaseFunctionLC = LC->getStackFrame();
ReleaseFunctionSF = SF;
}
}
@ -4142,8 +4139,7 @@ PathDiagnosticPieceRef MallocBugVisitor::VisitNode(const ExplodedNode *N,
Pos = PathDiagnosticLocation(PostImplCall->getLocation(),
BRC.getSourceManager());
} else {
Pos = PathDiagnosticLocation(S, BRC.getSourceManager(),
N->getLocationContext());
Pos = PathDiagnosticLocation(S, BRC.getSourceManager(), N->getStackFrame());
}
auto P = std::make_shared<PathDiagnosticEventPiece>(Pos, Msg, true);

View file

@ -193,8 +193,8 @@ void MismatchedIteratorChecker::checkPreStmt(const BinaryOperator *BO,
return;
ProgramStateRef State = C.getState();
SVal LVal = State->getSVal(BO->getLHS(), C.getLocationContext());
SVal RVal = State->getSVal(BO->getRHS(), C.getLocationContext());
SVal LVal = State->getSVal(BO->getLHS(), C.getStackFrame());
SVal RVal = State->getSVal(BO->getRHS(), C.getStackFrame());
verifyMatch(C, LVal, RVal);
}

View file

@ -57,7 +57,7 @@ public:
const InvalidatedSymbols *Invalidated,
ArrayRef<const MemRegion *> RequestedRegions,
ArrayRef<const MemRegion *> InvalidatedRegions,
const LocationContext *LCtx, const CallEvent *Call) const;
const StackFrame *SF, const CallEvent *Call) const;
void printState(raw_ostream &Out, ProgramStateRef State,
const char *NL, const char *Sep) const override;
@ -219,7 +219,7 @@ private:
ExplodedNode *tryToReportBug(const MemRegion *Region, const CXXRecordDecl *RD,
CheckerContext &C, MisuseKind MK) const;
bool isInMoveSafeContext(const LocationContext *LC) const;
bool isInMoveSafeStackFrame(const StackFrame *SF) const;
bool isStateResetMethod(const CXXMethodDecl *MethodDec) const;
bool isMoveSafeMethod(const CXXMethodDecl *MethodDec) const;
const ExplodedNode *getMoveLocation(const ExplodedNode *N,
@ -328,8 +328,7 @@ MoveChecker::MovedBugVisitor::VisitNode(const ExplodedNode *N,
}
// Generate the extra diagnostic.
PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
N->getLocationContext());
PathDiagnosticLocation Pos(S, BRC.getSourceManager(), N->getStackFrame());
return std::make_shared<PathDiagnosticEventPiece>(Pos, OS.str(), true);
}
@ -362,8 +361,8 @@ void MoveChecker::modelUse(ProgramStateRef State, const MemRegion *Region,
if (MK == MK_Dereference && OK.StdKind != SK_SmartPtr)
MK = MK_FunCall;
if (!RS || !shouldWarnAbout(OK, MK)
|| isInMoveSafeContext(C.getLocationContext())) {
if (!RS || !shouldWarnAbout(OK, MK) ||
isInMoveSafeStackFrame(C.getStackFrame())) {
// Finalize changes made by the caller.
C.addTransition(State);
return;
@ -403,7 +402,7 @@ ExplodedNode *MoveChecker::tryToReportBug(const MemRegion *Region,
if (const Stmt *MoveStmt = MoveNode->getStmtForDiagnostics())
LocUsedForUniqueing = PathDiagnosticLocation::createBegin(
MoveStmt, C.getSourceManager(), MoveNode->getLocationContext());
MoveStmt, C.getSourceManager(), MoveNode->getStackFrame());
// Creating the error message.
llvm::SmallString<128> Str;
@ -432,7 +431,7 @@ ExplodedNode *MoveChecker::tryToReportBug(const MemRegion *Region,
auto R = std::make_unique<PathSensitiveBugReport>(
BT, OS.str(), N, LocUsedForUniqueing,
MoveNode->getLocationContext()->getDecl());
MoveNode->getStackFrame()->getDecl());
R->addVisitor(std::make_unique<MovedBugVisitor>(*this, Region, RD, MK));
C.emitReport(std::move(R));
return N;
@ -530,18 +529,18 @@ bool MoveChecker::isStateResetMethod(const CXXMethodDecl *MethodDec) const {
// Don't report an error inside a move related operation.
// We assume that the programmer knows what she does.
bool MoveChecker::isInMoveSafeContext(const LocationContext *LC) const {
bool MoveChecker::isInMoveSafeStackFrame(const StackFrame *SF) const {
do {
const auto *CtxDec = LC->getDecl();
auto *CtorDec = dyn_cast_or_null<CXXConstructorDecl>(CtxDec);
auto *DtorDec = dyn_cast_or_null<CXXDestructorDecl>(CtxDec);
auto *MethodDec = dyn_cast_or_null<CXXMethodDecl>(CtxDec);
const auto *SFDec = SF->getDecl();
auto *CtorDec = dyn_cast_or_null<CXXConstructorDecl>(SFDec);
auto *DtorDec = dyn_cast_or_null<CXXDestructorDecl>(SFDec);
auto *MethodDec = dyn_cast_or_null<CXXMethodDecl>(SFDec);
if (DtorDec || (CtorDec && CtorDec->isCopyOrMoveConstructor()) ||
(MethodDec && MethodDec->isOverloadedOperator() &&
MethodDec->getOverloadedOperator() == OO_Equal) ||
isStateResetMethod(MethodDec) || isMoveSafeMethod(MethodDec))
return true;
} while ((LC = LC->getParent()));
} while ((SF = SF->getParent()));
return false;
}
@ -703,8 +702,8 @@ void MoveChecker::checkDeadSymbols(SymbolReaper &SymReaper,
ProgramStateRef MoveChecker::checkRegionChanges(
ProgramStateRef State, const InvalidatedSymbols *Invalidated,
ArrayRef<const MemRegion *> RequestedRegions,
ArrayRef<const MemRegion *> InvalidatedRegions,
const LocationContext *LCtx, const CallEvent *Call) const {
ArrayRef<const MemRegion *> InvalidatedRegions, const StackFrame *SF,
const CallEvent *Call) const {
if (Call) {
// Relax invalidation upon function calls: only invalidate parameters
// that are passed directly via non-const pointers or non-const references

View file

@ -70,8 +70,7 @@ NoOwnershipChangeVisitor::getFunctionName(const ExplodedNode *CallEnterN) {
bool NoOwnershipChangeVisitor::wasModifiedInFunction(
const ExplodedNode *CallEnterN, const ExplodedNode *CallExitEndN) {
const Decl *Callee =
CallExitEndN->getFirstPred()->getLocationContext()->getDecl();
const Decl *Callee = CallExitEndN->getFirstPred()->getStackFrame()->getDecl();
if (!doesFnIntendToHandleOwnership(
Callee,
CallExitEndN->getState()->getAnalysisManager().getASTContext()))

View file

@ -239,9 +239,9 @@ void NonNullParamChecker::checkBeginFunction(CheckerContext &Context) const {
if (!Context.inTopFrame())
return;
const LocationContext *LocContext = Context.getLocationContext();
const StackFrame *SF = Context.getStackFrame();
const Decl *FD = LocContext->getDecl();
const Decl *FD = SF->getDecl();
// AnyCall helps us here to avoid checking for FunctionDecl and ObjCMethodDecl
// separately and aggregates interfaces of these classes.
auto AbstractCall = AnyCall::forDecl(FD);
@ -262,7 +262,7 @@ void NonNullParamChecker::checkBeginFunction(CheckerContext &Context) const {
if (!Parameter->getType()->isPointerType())
continue;
Loc ParameterLoc = State->getLValue(Parameter, LocContext);
Loc ParameterLoc = State->getLValue(Parameter, SF);
// We never consider top-level function parameters undefined.
auto StoredVal =
State->getSVal(ParameterLoc).castAs<DefinedOrUnknownSVal>();

View file

@ -367,8 +367,7 @@ PathDiagnosticPieceRef NullabilityChecker::NullabilityBugVisitor::VisitNode(
.str();
// Generate the extra diagnostic.
PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
N->getLocationContext());
PathDiagnosticLocation Pos(S, BRC.getSourceManager(), N->getStackFrame());
return std::make_shared<PathDiagnosticEventPiece>(Pos, InfoText, true);
}
@ -399,15 +398,14 @@ static bool checkValueAtLValForInvariantViolation(ProgramStateRef State,
return false;
}
static bool
checkParamsForPreconditionViolation(ArrayRef<ParmVarDecl *> Params,
ProgramStateRef State,
const LocationContext *LocCtxt) {
static bool checkParamsForPreconditionViolation(ArrayRef<ParmVarDecl *> Params,
ProgramStateRef State,
const StackFrame *SF) {
for (const auto *ParamDecl : Params) {
if (ParamDecl->isParameterPack())
break;
SVal LV = State->getLValue(ParamDecl, LocCtxt);
SVal LV = State->getLValue(ParamDecl, SF);
if (checkValueAtLValForInvariantViolation(State, LV,
ParamDecl->getType())) {
return true;
@ -416,18 +414,17 @@ checkParamsForPreconditionViolation(ArrayRef<ParmVarDecl *> Params,
return false;
}
static bool
checkSelfIvarsForInvariantViolation(ProgramStateRef State,
const LocationContext *LocCtxt) {
auto *MD = dyn_cast<ObjCMethodDecl>(LocCtxt->getDecl());
static bool checkSelfIvarsForInvariantViolation(ProgramStateRef State,
const StackFrame *SF) {
auto *MD = dyn_cast<ObjCMethodDecl>(SF->getDecl());
if (!MD || !MD->isInstanceMethod())
return false;
const ImplicitParamDecl *SelfDecl = LocCtxt->getSelfDecl();
const ImplicitParamDecl *SelfDecl = SF->getSelfDecl();
if (!SelfDecl)
return false;
SVal SelfVal = State->getSVal(State->getRegion(SelfDecl, LocCtxt));
SVal SelfVal = State->getSVal(State->getRegion(SelfDecl, SF));
const ObjCObjectPointerType *SelfType =
dyn_cast<ObjCObjectPointerType>(SelfDecl->getType());
@ -452,8 +449,8 @@ static bool checkInvariantViolation(ProgramStateRef State, ExplodedNode *N,
if (State->get<InvariantViolated>())
return true;
const LocationContext *LocCtxt = C.getLocationContext();
const Decl *D = LocCtxt->getDecl();
const StackFrame *SF = C.getStackFrame();
const Decl *D = SF->getDecl();
if (!D)
return false;
@ -467,8 +464,8 @@ static bool checkInvariantViolation(ProgramStateRef State, ExplodedNode *N,
else
return false;
if (checkParamsForPreconditionViolation(Params, State, LocCtxt) ||
checkSelfIvarsForInvariantViolation(State, LocCtxt)) {
if (checkParamsForPreconditionViolation(Params, State, SF) ||
checkSelfIvarsForInvariantViolation(State, SF)) {
if (!N->isSink())
C.addTransition(State->set<InvariantViolated>(true), N);
return true;
@ -565,8 +562,8 @@ void NullabilityChecker::checkBeginFunction(CheckerContext &C) const {
if (!C.inTopFrame())
return;
const LocationContext *LCtx = C.getLocationContext();
auto AbstractCall = AnyCall::forDecl(LCtx->getDecl());
const StackFrame *SF = C.getStackFrame();
auto AbstractCall = AnyCall::forDecl(SF->getDecl());
if (!AbstractCall || AbstractCall->parameters().empty())
return;
@ -580,7 +577,7 @@ void NullabilityChecker::checkBeginFunction(CheckerContext &C) const {
if (RequiredNullability != Nullability::Nullable)
continue;
const VarRegion *ParamRegion = State->getRegion(Param, LCtx);
const VarRegion *ParamRegion = State->getRegion(Param, SF);
const MemRegion *ParamPointeeRegion =
State->getSVal(ParamRegion).getAsRegion();
if (!ParamPointeeRegion)
@ -668,8 +665,7 @@ void NullabilityChecker::checkPreStmt(const ReturnStmt *S,
bool InSuppressedMethodFamily = false;
QualType RequiredRetType;
AnalysisDeclContext *DeclCtxt =
C.getLocationContext()->getAnalysisDeclContext();
AnalysisDeclContext *DeclCtxt = C.getStackFrame()->getAnalysisDeclContext();
const Decl *D = DeclCtxt->getDecl();
if (auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
// HACK: This is a big hammer to avoid warning when there are defensive
@ -690,7 +686,7 @@ void NullabilityChecker::checkPreStmt(const ReturnStmt *S,
NullConstraint Nullness = getNullConstraint(*RetSVal, State);
Nullability RequiredNullability = getNullabilityAnnotation(RequiredRetType);
if (const auto *FunDecl = C.getLocationContext()->getDecl();
if (const auto *FunDecl = C.getStackFrame()->getDecl();
FunDecl && FunDecl->getAttr<ReturnsNonNullAttr>() &&
(RequiredNullability == Nullability::Unspecified ||
RequiredNullability == Nullability::Nullable)) {

View file

@ -117,8 +117,7 @@ void ObjCSuperDeallocChecker::checkPostObjCMessage(const ObjCMethodCall &M,
return;
ProgramStateRef State = C.getState();
const LocationContext *LC = C.getLocationContext();
SymbolRef SelfSymbol = State->getSelfSVal(LC).getAsSymbol();
SymbolRef SelfSymbol = State->getSelfSVal(C.getStackFrame()).getAsSymbol();
assert(SelfSymbol && "No receiver symbol at call to [super dealloc]?");
// We add this transition in checkPostObjCMessage to avoid warning when

View file

@ -251,8 +251,8 @@ public:
ProgramStateRef
checkRegionChanges(ProgramStateRef State, const InvalidatedSymbols *Symbols,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const LocationContext *LCtx, const CallEvent *Call) const;
ArrayRef<const MemRegion *> Regions, const StackFrame *SF,
const CallEvent *Call) const;
void printState(raw_ostream &Out, ProgramStateRef State, const char *NL,
const char *Sep) const override;
@ -694,7 +694,7 @@ void PthreadLockChecker::checkDeadSymbols(SymbolReaper &SymReaper,
ProgramStateRef PthreadLockChecker::checkRegionChanges(
ProgramStateRef State, const InvalidatedSymbols *Symbols,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions, const LocationContext *LCtx,
ArrayRef<const MemRegion *> Regions, const StackFrame *SF,
const CallEvent *Call) const {
bool IsLibraryFunction = false;

View file

@ -162,13 +162,13 @@ void RetainCountChecker::checkPostStmt(const BlockExpr *BE,
// via captured variables, even though captured variables result in a copy
// and in implicit increment/decrement of a retain count.
SmallVector<const MemRegion*, 10> Regions;
const LocationContext *LC = C.getLocationContext();
const StackFrame *SF = C.getStackFrame();
MemRegionManager &MemMgr = C.getSValBuilder().getRegionManager();
for (auto Var : ReferencedVars) {
const VarRegion *VR = Var.getCapturedRegion();
if (VR->getSuperRegion() == R) {
VR = MemMgr.getVarRegion(VR->getDecl(), LC);
VR = MemMgr.getVarRegion(VR->getDecl(), SF);
}
Regions.push_back(VR);
}
@ -245,8 +245,7 @@ void RetainCountChecker::processObjCLiterals(CheckerContext &C,
// Return the object as autoreleased.
// RetEffect RE = RetEffect::MakeNotOwned(ObjKind::ObjC);
if (SymbolRef sym =
state->getSVal(Ex, pred->getLocationContext()).getAsSymbol()) {
if (SymbolRef sym = state->getSVal(Ex, pred->getStackFrame()).getAsSymbol()) {
QualType ResultTy = Ex->getType();
state = setRefBinding(state, sym,
RefVal::makeNotOwned(ObjKind::ObjC, ResultTy));
@ -340,7 +339,7 @@ static bool isReceiverUnconsumedSelf(const CallEvent &Call) {
// Check if the message is not consumed, we know it will not be used in
// an assignment, ex: "self = [super init]".
return MC->getMethodFamily() == OMF_init && MC->isReceiverSelfOrSuper() &&
!Call.getLocationContext()
!Call.getStackFrame()
->getAnalysisDeclContext()
->getParentMap()
.isConsumedExpr(Call.getOriginExpr());
@ -910,7 +909,7 @@ bool RetainCountChecker::evalCall(const CallEvent &Call,
// annotate attribute. If it does, we will not inline it.
bool hasTrustedImplementationAnnotation = false;
const LocationContext *LCtx = C.getLocationContext();
const StackFrame *SF = C.getStackFrame();
using BehaviorSummary = RetainSummaryManager::BehaviorSummary;
std::optional<BehaviorSummary> BSmr =
@ -929,7 +928,7 @@ bool RetainCountChecker::evalCall(const CallEvent &Call,
(BSmr == BehaviorSummary::IdentityThis)
? cast<CXXMemberCallExpr>(CE)->getImplicitObjectArgument()
: CE->getArg(0);
SVal RetVal = state->getSVal(BindReturnTo, LCtx);
SVal RetVal = state->getSVal(BindReturnTo, SF);
// If the receiver is unknown or the function has
// 'rc_ownership_trusted_implementation' annotate attribute, conjure a
@ -942,7 +941,7 @@ bool RetainCountChecker::evalCall(const CallEvent &Call,
}
// Bind the value.
state = state->BindExpr(CE, LCtx, RetVal, /*Invalidate=*/false);
state = state->BindExpr(CE, SF, RetVal, /*Invalidate=*/false);
if (BSmr == BehaviorSummary::IdentityOrZero) {
// Add a branch where the output is zero.
@ -950,7 +949,7 @@ bool RetainCountChecker::evalCall(const CallEvent &Call,
// Assume that output is zero on the other branch.
NullOutputState = NullOutputState->BindExpr(
CE, LCtx, C.getSValBuilder().makeNullWithType(ResultTy),
CE, SF, C.getSValBuilder().makeNullWithType(ResultTy),
/*Invalidate=*/false);
C.addTransition(NullOutputState, &getCastFailTag());
@ -988,7 +987,7 @@ ExplodedNode * RetainCountChecker::processReturn(const ReturnStmt *S,
ProgramStateRef state = C.getState();
// We need to dig down to the symbolic base here because various
// custom allocators do sometimes return the symbol with an offset.
SymbolRef Sym = state->getSValAsScalarOrLoc(RetE, C.getLocationContext())
SymbolRef Sym = state->getSValAsScalarOrLoc(RetE, C.getStackFrame())
.getAsLocSymbol(/*IncludeBaseRegions=*/true);
if (!Sym)
return Pred;
@ -1185,7 +1184,7 @@ ProgramStateRef RetainCountChecker::evalAssume(ProgramStateRef state,
ProgramStateRef RetainCountChecker::checkRegionChanges(
ProgramStateRef state, const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions, const LocationContext *LCtx,
ArrayRef<const MemRegion *> Regions, const StackFrame *SF,
const CallEvent *Call) const {
if (!invalidated)
return state;
@ -1332,8 +1331,8 @@ void RetainCountChecker::checkBeginFunction(CheckerContext &Ctx) const {
return;
RetainSummaryManager &SmrMgr = getSummaryManager(Ctx);
const LocationContext *LCtx = Ctx.getLocationContext();
const Decl *D = LCtx->getDecl();
const StackFrame *SF = Ctx.getStackFrame();
const Decl *D = SF->getDecl();
std::optional<AnyCall> C = AnyCall::forDecl(D);
if (!C || SmrMgr.isTrustedReferenceCountImplementation(D))
@ -1345,7 +1344,7 @@ void RetainCountChecker::checkBeginFunction(CheckerContext &Ctx) const {
for (unsigned idx = 0, e = C->param_size(); idx != e; ++idx) {
const ParmVarDecl *Param = C->parameters()[idx];
SymbolRef Sym = state->getSVal(state->getRegion(Param, LCtx)).getAsSymbol();
SymbolRef Sym = state->getSVal(state->getRegion(Param, SF)).getAsSymbol();
QualType Ty = Param->getType();
const ArgEffect *AE = CalleeSideArgEffects.lookup(idx);
@ -1376,9 +1375,9 @@ void RetainCountChecker::checkEndFunction(const ReturnStmt *RS,
RefBindingsTy B = state->get<RefBindings>();
// Don't process anything within synthesized bodies.
const LocationContext *LCtx = Pred->getLocationContext();
if (LCtx->getAnalysisDeclContext()->isBodyAutosynthesized()) {
assert(!LCtx->inTopFrame());
const StackFrame *SF = Pred->getStackFrame();
if (SF->getAnalysisDeclContext()->isBodyAutosynthesized()) {
assert(!SF->inTopFrame());
return;
}
@ -1388,11 +1387,11 @@ void RetainCountChecker::checkEndFunction(const ReturnStmt *RS,
return;
}
// If the current LocationContext has a parent, don't check for leaks.
// If the current StackFrame has a parent, don't check for leaks.
// We will do that later.
// FIXME: we should instead check for imbalances of the retain/releases,
// and suggest annotations.
if (LCtx->getParent())
if (SF->getParent())
return;
B = state->get<RefBindings>();

View file

@ -309,8 +309,7 @@ public:
checkRegionChanges(ProgramStateRef state,
const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const LocationContext* LCtx,
ArrayRef<const MemRegion *> Regions, const StackFrame *SF,
const CallEvent *Call) const;
ExplodedNode* checkReturnWithRetEffect(const ReturnStmt *S, CheckerContext &C,

View file

@ -117,8 +117,8 @@ static bool shouldGenerateNote(llvm::raw_string_ostream &os,
/// corresponding to the symbol @c Sym.
/// If none found, returns std::nullopt.
static std::optional<unsigned>
findArgIdxOfSymbol(ProgramStateRef CurrSt, const LocationContext *LCtx,
SymbolRef &Sym, std::optional<CallEventRef<>> CE) {
findArgIdxOfSymbol(ProgramStateRef CurrSt, const StackFrame *SF, SymbolRef &Sym,
std::optional<CallEventRef<>> CE) {
if (!CE)
return std::nullopt;
@ -157,7 +157,7 @@ static std::string findAllocatedObjectName(const Stmt *S, QualType QT) {
}
static void generateDiagnosticsForCallLike(ProgramStateRef CurrSt,
const LocationContext *LCtx,
const StackFrame *SF,
const RefVal &CurrV, SymbolRef &Sym,
const Stmt *S,
llvm::raw_string_ostream &os) {
@ -165,7 +165,7 @@ static void generateDiagnosticsForCallLike(ProgramStateRef CurrSt,
if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
// Get the name of the callee (if it is available)
// from the tracked SVal.
SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee(), LCtx);
SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee(), SF);
const FunctionDecl *FD = X.getAsFunctionDecl();
// If failed, try to get it from AST.
@ -184,7 +184,7 @@ static void generateDiagnosticsForCallLike(ProgramStateRef CurrSt,
} else {
assert(isa<ObjCMessageExpr>(S));
CallEventRef<ObjCMethodCall> Call = Mgr.getObjCMethodCall(
cast<ObjCMessageExpr>(S), CurrSt, LCtx, {nullptr, 0});
cast<ObjCMessageExpr>(S), CurrSt, SF, {nullptr, 0});
switch (Call->getMessageKind()) {
case OCM_Message:
@ -199,8 +199,8 @@ static void generateDiagnosticsForCallLike(ProgramStateRef CurrSt,
}
}
std::optional<CallEventRef<>> CE = Mgr.getCall(S, CurrSt, LCtx, {nullptr, 0});
auto Idx = findArgIdxOfSymbol(CurrSt, LCtx, Sym, CE);
std::optional<CallEventRef<>> CE = Mgr.getCall(S, CurrSt, SF, {nullptr, 0});
auto Idx = findArgIdxOfSymbol(CurrSt, SF, Sym, CE);
// If index is not found, we assume that the symbol was returned.
if (!Idx) {
@ -303,15 +303,15 @@ private:
/// Find the first node with the parent stack frame.
static const ExplodedNode *getCalleeNode(const ExplodedNode *Pred) {
const StackFrame *SC = Pred->getStackFrame();
if (SC->inTopFrame())
const StackFrame *SF = Pred->getStackFrame();
if (SF->inTopFrame())
return nullptr;
const StackFrame *PC = SC->getParent()->getStackFrame();
if (!PC)
const StackFrame *PSF = SF->getParent();
if (!PSF)
return nullptr;
const ExplodedNode *N = Pred;
while (N && N->getStackFrame() != PC) {
while (N && N->getStackFrame() != PSF) {
N = N->getFirstPred();
}
return N;
@ -422,7 +422,7 @@ RefCountReportVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC,
const ExplodedNode *PrevNode = N->getFirstPred();
ProgramStateRef PrevSt = PrevNode->getState();
ProgramStateRef CurrSt = N->getState();
const LocationContext *LCtx = N->getLocationContext();
const StackFrame *SF = N->getStackFrame();
const RefVal* CurrT = getRefBinding(CurrSt, Sym);
if (!CurrT)
@ -447,9 +447,8 @@ RefCountReportVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC,
if (!PrevT) {
const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
if (isa<ObjCIvarRefExpr>(S) &&
isSynthesizedAccessor(LCtx->getStackFrame())) {
S = LCtx->getStackFrame()->getCallSite();
if (isa<ObjCIvarRefExpr>(S) && isSynthesizedAccessor(SF)) {
S = SF->getCallSite();
}
if (isa<ObjCArrayLiteral>(S)) {
@ -477,10 +476,10 @@ RefCountReportVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC,
} else if (isa<ObjCIvarRefExpr>(S)) {
os << "Object loaded from instance variable";
} else {
generateDiagnosticsForCallLike(CurrSt, LCtx, CurrV, Sym, S, os);
generateDiagnosticsForCallLike(CurrSt, SF, CurrV, Sym, S, os);
}
PathDiagnosticLocation Pos(S, SM, N->getLocationContext());
PathDiagnosticLocation Pos(S, SM, N->getStackFrame());
return std::make_shared<PathDiagnosticEventPiece>(Pos, sbuf);
}
@ -508,16 +507,15 @@ RefCountReportVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC,
// Retrieve the value of the argument. Is it the symbol
// we are interested in?
if (CurrSt->getSValAsScalarOrLoc(*AI, LCtx).getAsLocSymbol() != Sym)
if (CurrSt->getSValAsScalarOrLoc(*AI, SF).getAsLocSymbol() != Sym)
continue;
// We have an argument. Get the effect!
DeallocSent = true;
}
} else if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) {
if (const Expr *receiver = ME->getInstanceReceiver()) {
if (CurrSt->getSValAsScalarOrLoc(receiver, LCtx)
.getAsLocSymbol() == Sym) {
if (const Expr *R = ME->getInstanceReceiver()) {
if (CurrSt->getSValAsScalarOrLoc(R, SF).getAsLocSymbol() == Sym) {
// The symbol we are tracking is the receiver.
DeallocSent = true;
}
@ -532,15 +530,14 @@ RefCountReportVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC,
return nullptr; // We have nothing to say!
const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
N->getLocationContext());
PathDiagnosticLocation Pos(S, BRC.getSourceManager(), N->getStackFrame());
auto P = std::make_shared<PathDiagnosticEventPiece>(Pos, sbuf);
// Add the range by scanning the children of the statement for any bindings
// to Sym.
for (const Stmt *Child : S->children())
if (const Expr *Exp = dyn_cast_or_null<Expr>(Child))
if (CurrSt->getSValAsScalarOrLoc(Exp, LCtx).getAsLocSymbol() == Sym) {
if (CurrSt->getSValAsScalarOrLoc(Exp, SF).getAsLocSymbol() == Sym) {
P->addRange(Exp->getSourceRange());
break;
}
@ -598,16 +595,16 @@ namespace {
// Find the first node in the current function context that referred to the
// tracked symbol and the memory location that value was stored to. Note, the
// value is only reported if the allocation occurred in the same function as
// the leak. The function can also return a location context, which should be
// the leak. The function can also return a stack frame, which should be
// treated as interesting.
struct AllocationInfo {
const ExplodedNode* N;
const MemRegion *R;
const LocationContext *InterestingMethodContext;
AllocationInfo(const ExplodedNode *InN,
const MemRegion *InR,
const LocationContext *InInterestingMethodContext) :
N(InN), R(InR), InterestingMethodContext(InInterestingMethodContext) {}
const StackFrame *InterestingMethodStackFrame;
AllocationInfo(const ExplodedNode *InN, const MemRegion *InR,
const StackFrame *InterestingMethodStackFrame)
: N(InN), R(InR),
InterestingMethodStackFrame(InterestingMethodStackFrame) {}
};
} // end anonymous namespace
@ -616,15 +613,15 @@ static AllocationInfo GetAllocationSite(ProgramStateManager &StateMgr,
const ExplodedNode *AllocationNode = N;
const ExplodedNode *AllocationNodeInCurrentOrParentContext = N;
const MemRegion *FirstBinding = nullptr;
const LocationContext *LeakContext = N->getLocationContext();
const StackFrame *LeakStackFrame = N->getStackFrame();
// The location context of the init method called on the leaked object, if
// The stack frame of the init method called on the leaked object, if
// available.
const LocationContext *InitMethodContext = nullptr;
const StackFrame *InitMethodStackFrame = nullptr;
while (N) {
ProgramStateRef St = N->getState();
const LocationContext *NContext = N->getLocationContext();
const StackFrame *NStackFrame = N->getStackFrame();
if (!getRefBinding(St, Sym))
break;
@ -637,7 +634,7 @@ static AllocationInfo GetAllocationSite(ProgramStateManager &StateMgr,
// Do not show local variables belonging to a function other than
// where the error is reported.
if (const auto *MR = R->getMemorySpaceAs<StackSpaceRegion>(St))
if (MR->getStackFrame() == LeakContext->getStackFrame())
if (MR->getStackFrame() == LeakStackFrame)
FirstBinding = R;
}
@ -651,19 +648,20 @@ static AllocationInfo GetAllocationSite(ProgramStateManager &StateMgr,
// the case where an allocation happens in a block that captures a reference
// to it and that reference is overwritten/dropped by another call to
// the block.
if (NContext == LeakContext || NContext->isParentOf(LeakContext))
if (NStackFrame == LeakStackFrame ||
NStackFrame->isParentOf(LeakStackFrame))
AllocationNodeInCurrentOrParentContext = N;
// Find the last init that was called on the given symbol and store the
// init method's location context.
if (!InitMethodContext)
// init method's stack frame.
if (!InitMethodStackFrame)
if (auto CEP = N->getLocation().getAs<CallEnter>()) {
const Stmt *CE = CEP->getCallExpr();
if (const auto *ME = dyn_cast_or_null<ObjCMessageExpr>(CE)) {
if (const Expr *RecExpr = ME->getInstanceReceiver()) {
SVal RecV = St->getSVal(RecExpr, NContext);
SVal RecV = St->getSVal(RecExpr, NStackFrame);
if (ME->getMethodFamily() == OMF_init && RecV.getAsSymbol() == Sym)
InitMethodContext = CEP->getCalleeContext();
InitMethodStackFrame = CEP->getCalleeStackFrame();
}
}
}
@ -673,13 +671,13 @@ static AllocationInfo GetAllocationSite(ProgramStateManager &StateMgr,
// If we are reporting a leak of the object that was allocated with alloc,
// mark its init method as interesting.
const LocationContext *InterestingMethodContext = nullptr;
if (InitMethodContext) {
const StackFrame *InterestingMethodStackFrame = nullptr;
if (InitMethodStackFrame) {
const ProgramPoint AllocPP = AllocationNode->getLocation();
if (std::optional<StmtPoint> SP = AllocPP.getAs<StmtPoint>())
if (const ObjCMessageExpr *ME = SP->getStmtAs<ObjCMessageExpr>())
if (ME->getMethodFamily() == OMF_alloc)
InterestingMethodContext = InitMethodContext;
InterestingMethodStackFrame = InitMethodStackFrame;
}
// If allocation happened in a function different from the leak node context,
@ -687,12 +685,11 @@ static AllocationInfo GetAllocationSite(ProgramStateManager &StateMgr,
assert(N && "Could not find allocation node");
if (AllocationNodeInCurrentOrParentContext &&
AllocationNodeInCurrentOrParentContext->getLocationContext() !=
LeakContext)
AllocationNodeInCurrentOrParentContext->getStackFrame() != LeakStackFrame)
FirstBinding = nullptr;
return AllocationInfo(AllocationNodeInCurrentOrParentContext, FirstBinding,
InterestingMethodContext);
InterestingMethodStackFrame);
}
PathDiagnosticPieceRef
@ -809,7 +806,7 @@ void RefLeakReport::deriveParamLocation(CheckerContext &Ctx) {
PathDiagnosticLocation::create(PDecl, SMgr);
Location = ParamLocation;
UniqueingLocation = ParamLocation;
UniqueingDecl = Ctx.getLocationContext()->getDecl();
UniqueingDecl = Ctx.getStackFrame()->getDecl();
}
}
}
@ -832,7 +829,7 @@ void RefLeakReport::deriveAllocLocation(CheckerContext &Ctx) {
AllocNode = AllocI.N;
AllocFirstBinding = AllocI.R;
markInteresting(AllocI.InterestingMethodContext);
markInteresting(AllocI.InterestingMethodStackFrame);
// Get the SourceLocation for the allocation site.
// FIXME: This will crash the analyzer if an allocation comes from an
@ -846,13 +843,13 @@ void RefLeakReport::deriveAllocLocation(CheckerContext &Ctx) {
}
PathDiagnosticLocation AllocLocation = PathDiagnosticLocation::createBegin(
AllocStmt, SMgr, AllocNode->getLocationContext());
AllocStmt, SMgr, AllocNode->getStackFrame());
Location = AllocLocation;
// Set uniqieing info, which will be used for unique the bug reports. The
// leaks should be uniqued on the allocation site.
UniqueingLocation = AllocLocation;
UniqueingDecl = AllocNode->getLocationContext()->getDecl();
UniqueingDecl = AllocNode->getStackFrame()->getDecl();
}
void RefLeakReport::createDescription(CheckerContext &Ctx) {

View file

@ -112,8 +112,7 @@ void ReturnPointerRangeChecker::checkPreStmt(const ReturnStmt *RS,
OS << ", returned pointer points at index " << ConcreteIdx->getValue();
}
Report->addNote(SBuf,
{RetE, C.getSourceManager(), C.getLocationContext()});
Report->addNote(SBuf, {RetE, C.getSourceManager(), C.getStackFrame()});
}
bugreporter::trackExpressionValue(N, RetE, *Report);

View file

@ -133,12 +133,12 @@ void STLAlgorithmModeling::Find(CheckerContext &C, const CallEvent &Call,
const auto &Elem = Call.getCFGElementRef();
auto State = C.getState();
auto &SVB = C.getSValBuilder();
const auto *LCtx = C.getLocationContext();
const auto *SF = C.getStackFrame();
SVal RetVal = SVB.conjureSymbolVal(nullptr, Elem, LCtx, C.blockCount());
SVal Param = State->getSVal(CE->getArg(paramNum), LCtx);
SVal RetVal = SVB.conjureSymbolVal(nullptr, Elem, SF, C.blockCount());
SVal Param = State->getSVal(CE->getArg(paramNum), SF);
auto StateFound = State->BindExpr(CE, LCtx, RetVal);
auto StateFound = State->BindExpr(CE, SF, RetVal);
// If we have an iterator position for the range-begin argument then we can
// assume that in case of successful search the position of the found element
@ -147,7 +147,7 @@ void STLAlgorithmModeling::Find(CheckerContext &C, const CallEvent &Call,
const auto *Pos = getIteratorPosition(State, Param);
if (Pos) {
StateFound = createIteratorPosition(StateFound, RetVal, Pos->getContainer(),
Elem, LCtx, C.blockCount());
Elem, SF, C.blockCount());
const auto *NewPos = getIteratorPosition(StateFound, RetVal);
assert(NewPos && "Failed to create new iterator position.");
@ -160,7 +160,7 @@ void STLAlgorithmModeling::Find(CheckerContext &C, const CallEvent &Call,
StateFound = StateFound->assume(GreaterOrEqual.castAs<DefinedSVal>(), true);
}
Param = State->getSVal(CE->getArg(paramNum + 1), LCtx);
Param = State->getSVal(CE->getArg(paramNum + 1), SF);
// If we have an iterator position for the range-end argument then we can
// assume that in case of successful search the position of the found element
@ -169,7 +169,7 @@ void STLAlgorithmModeling::Find(CheckerContext &C, const CallEvent &Call,
Pos = getIteratorPosition(State, Param);
if (Pos) {
StateFound = createIteratorPosition(StateFound, RetVal, Pos->getContainer(),
Elem, LCtx, C.blockCount());
Elem, SF, C.blockCount());
const auto *NewPos = getIteratorPosition(StateFound, RetVal);
assert(NewPos && "Failed to create new iterator position.");
@ -185,7 +185,7 @@ void STLAlgorithmModeling::Find(CheckerContext &C, const CallEvent &Call,
C.addTransition(StateFound);
if (AggressiveStdFindModeling) {
auto StateNotFound = State->BindExpr(CE, LCtx, Param);
auto StateNotFound = State->BindExpr(CE, SF, Param);
C.addTransition(StateNotFound);
}
}

View file

@ -54,8 +54,8 @@ public:
checkRegionChanges(ProgramStateRef State,
const InvalidatedSymbols *Invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const LocationContext *LCtx, const CallEvent *Call) const;
ArrayRef<const MemRegion *> Regions, const StackFrame *SF,
const CallEvent *Call) const;
void printState(raw_ostream &Out, ProgramStateRef State, const char *NL,
const char *Sep) const override;
void checkLiveSymbols(ProgramStateRef State, SymbolReaper &SR) const;
@ -303,7 +303,7 @@ bool SmartPtrModeling::evalCall(const CallEvent &Call,
return false;
const auto PtrVal = C.getSValBuilder().getConjuredHeapSymbolVal(
Call.getCFGElementRef(), C.getLocationContext(),
Call.getCFGElementRef(), C.getStackFrame(),
getPointerTypeFromTemplateArg(Call, C), C.blockCount());
const MemRegion *ThisRegion = ThisRegionOpt->getAsRegion();
@ -328,7 +328,7 @@ bool SmartPtrModeling::evalCall(const CallEvent &Call,
// automatically deduced).
auto &Engine = State->getStateManager().getOwningEngine();
State = Engine.updateObjectsUnderConstruction(
*ThisRegionOpt, nullptr, State, C.getLocationContext(),
*ThisRegionOpt, nullptr, State, C.getStackFrame(),
Call.getConstructionContext(), {});
// We don't leave a note here since it is guaranteed the
@ -360,7 +360,7 @@ bool SmartPtrModeling::evalCall(const CallEvent &Call,
// TODO: Add a note to bug reports describing this decision.
C.addTransition(State->BindExpr(
Call.getOriginExpr(), C.getLocationContext(),
Call.getOriginExpr(), C.getStackFrame(),
C.getSValBuilder().makeZeroVal(Call.getResultType())));
return true;
@ -439,8 +439,8 @@ std::pair<SVal, ProgramStateRef> SmartPtrModeling::retrieveOrConjureInnerPtrVal(
const auto *Ptr = State->get<TrackedRegionMap>(ThisRegion);
if (Ptr)
return {*Ptr, State};
auto Val = C.getSValBuilder().conjureSymbolVal(Elem, C.getLocationContext(),
Type, C.blockCount());
auto Val = C.getSValBuilder().conjureSymbolVal(Elem, C.getStackFrame(), Type,
C.blockCount());
State = State->set<TrackedRegionMap>(ThisRegion, Val);
return {Val, State};
}
@ -484,7 +484,7 @@ bool SmartPtrModeling::handleComparisionOp(const CallEvent &Call,
const auto *SecondExpr = Call.getArgExpr(1);
const auto *ResultExpr = Call.getOriginExpr();
const auto *LCtx = C.getLocationContext();
const auto *SF = C.getStackFrame();
auto &Bldr = C.getSValBuilder();
ProgramStateRef State = C.getState();
@ -504,12 +504,12 @@ bool SmartPtrModeling::handleComparisionOp(const CallEvent &Call,
State->assume(*RetVal.getAs<DefinedOrUnknownSVal>());
if (TrueState)
C.addTransition(
TrueState->BindExpr(ResultExpr, LCtx, Bldr.makeTruthVal(true)));
TrueState->BindExpr(ResultExpr, SF, Bldr.makeTruthVal(true)));
if (FalseState)
C.addTransition(
FalseState->BindExpr(ResultExpr, LCtx, Bldr.makeTruthVal(false)));
FalseState->BindExpr(ResultExpr, SF, Bldr.makeTruthVal(false)));
} else {
C.addTransition(State->BindExpr(ResultExpr, LCtx, RetVal));
C.addTransition(State->BindExpr(ResultExpr, SF, RetVal));
}
return true;
}
@ -529,11 +529,9 @@ bool SmartPtrModeling::handleOstreamOperator(const CallEvent &Call,
const MemRegion *StreamThisRegion = StreamVal.getAsRegion();
if (!StreamThisRegion)
return false;
State =
State->invalidateRegions({StreamThisRegion}, Call.getCFGElementRef(),
C.blockCount(), C.getLocationContext(), false);
State =
State->BindExpr(Call.getOriginExpr(), C.getLocationContext(), StreamVal);
State = State->invalidateRegions({StreamThisRegion}, Call.getCFGElementRef(),
C.blockCount(), C.getStackFrame(), false);
State = State->BindExpr(Call.getOriginExpr(), C.getStackFrame(), StreamVal);
C.addTransition(State);
return true;
}
@ -573,7 +571,7 @@ void SmartPtrModeling::printState(raw_ostream &Out, ProgramStateRef State,
ProgramStateRef SmartPtrModeling::checkRegionChanges(
ProgramStateRef State, const InvalidatedSymbols *Invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions, const LocationContext *LCtx,
ArrayRef<const MemRegion *> Regions, const StackFrame *SF,
const CallEvent *Call) const {
TrackedRegionMapTy RegionMap = State->get<TrackedRegionMap>();
TrackedRegionMapTy::Factory &RegionMapFactory =
@ -639,7 +637,7 @@ void SmartPtrModeling::handleRelease(const CallEvent &Call,
const auto *InnerPointVal = State->get<TrackedRegionMap>(ThisRegion);
if (InnerPointVal) {
State = State->BindExpr(Call.getOriginExpr(), C.getLocationContext(),
State = State->BindExpr(Call.getOriginExpr(), C.getStackFrame(),
*InnerPointVal);
}
@ -723,8 +721,8 @@ void SmartPtrModeling::handleGet(const CallEvent &Call,
SVal InnerPointerVal;
std::tie(InnerPointerVal, State) = retrieveOrConjureInnerPtrVal(
State, ThisRegion, Call.getCFGElementRef(), Call.getResultType(), C);
State = State->BindExpr(Call.getOriginExpr(), C.getLocationContext(),
InnerPointerVal);
State =
State->BindExpr(Call.getOriginExpr(), C.getStackFrame(), InnerPointerVal);
// TODO: Add NoteTag, for how the raw pointer got using 'get' method.
C.addTransition(State);
}
@ -857,20 +855,20 @@ void SmartPtrModeling::handleBoolConversion(const CallEvent &Call,
}
if (State->isNull(InnerPointerVal).isConstrainedTrue()) {
State = State->BindExpr(CallExpr, C.getLocationContext(),
State = State->BindExpr(CallExpr, C.getStackFrame(),
C.getSValBuilder().makeTruthVal(false));
C.addTransition(State);
return;
} else if (State->isNonNull(InnerPointerVal).isConstrainedTrue()) {
State = State->BindExpr(CallExpr, C.getLocationContext(),
State = State->BindExpr(CallExpr, C.getStackFrame(),
C.getSValBuilder().makeTruthVal(true));
C.addTransition(State);
return;
} else if (move::isMovedFrom(State, ThisRegion)) {
C.addTransition(
State->BindExpr(CallExpr, C.getLocationContext(),
State->BindExpr(CallExpr, C.getStackFrame(),
C.getSValBuilder().makeZeroVal(Call.getResultType())));
return;
} else {
@ -882,7 +880,7 @@ void SmartPtrModeling::handleBoolConversion(const CallEvent &Call,
// Explicitly tracking the region as null.
NullState = NullState->set<TrackedRegionMap>(ThisRegion, NullVal);
NullState = NullState->BindExpr(CallExpr, C.getLocationContext(),
NullState = NullState->BindExpr(CallExpr, C.getStackFrame(),
C.getSValBuilder().makeTruthVal(false));
C.addTransition(NullState, C.getNoteTag(
[ThisRegion](PathSensitiveBugReport &BR,
@ -892,9 +890,8 @@ void SmartPtrModeling::handleBoolConversion(const CallEvent &Call,
OS << " is null";
},
/*IsPrunable=*/true));
NotNullState =
NotNullState->BindExpr(CallExpr, C.getLocationContext(),
C.getSValBuilder().makeTruthVal(true));
NotNullState = NotNullState->BindExpr(
CallExpr, C.getStackFrame(), C.getSValBuilder().makeTruthVal(true));
C.addTransition(
NotNullState,
C.getNoteTag(

View file

@ -457,8 +457,7 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
ExplodedNode *Node = Ctx.getPredecessor();
bool ExitingTopFrame =
Ctx.getPredecessor()->getLocationContext()->inTopFrame();
bool ExitingTopFrame = Ctx.getPredecessor()->getStackFrame()->inTopFrame();
if (ExitingTopFrame &&
Node->getLocation().getTag() == ExprEngine::cleanupNodeTag() &&

View file

@ -1477,10 +1477,9 @@ bool StdLibraryFunctionsChecker::evalCall(const CallEvent &Call,
switch (Summary.getInvalidationKd()) {
case EvalCallAsPure: {
ProgramStateRef State = C.getState();
const LocationContext *LC = C.getLocationContext();
const auto *CE = cast<CallExpr>(Call.getOriginExpr());
SVal V = C.getSValBuilder().conjureSymbolVal(Call, C.blockCount());
State = State->BindExpr(CE, LC, V);
State = State->BindExpr(CE, C.getStackFrame(), V);
C.addTransition(State);

View file

@ -143,7 +143,7 @@ public:
const InvalidatedSymbols *,
ArrayRef<const MemRegion *>,
ArrayRef<const MemRegion *> Regions,
const LocationContext *,
const StackFrame *,
const CallEvent *Call) const {
if (!Call)
return State;

View file

@ -226,7 +226,7 @@ SVal getStreamArg(const FnDescription *Desc, const CallEvent &Call) {
/// Create a conjured symbol return value for a call expression.
DefinedSVal makeRetVal(CheckerContext &C, ConstCFGElementRef Elem) {
return C.getSValBuilder()
.conjureSymbolVal(/*symbolTag=*/nullptr, Elem, C.getLocationContext(),
.conjureSymbolVal(/*symbolTag=*/nullptr, Elem, C.getStackFrame(),
C.blockCount())
.castAs<DefinedSVal>();
}
@ -234,7 +234,7 @@ DefinedSVal makeRetVal(CheckerContext &C, ConstCFGElementRef Elem) {
ProgramStateRef bindAndAssumeTrue(ProgramStateRef State, CheckerContext &C,
const CallExpr *CE, ConstCFGElementRef Elem) {
DefinedSVal RetVal = makeRetVal(C, Elem);
State = State->BindExpr(CE, C.getLocationContext(), RetVal);
State = State->BindExpr(CE, C.getStackFrame(), RetVal);
State = State->assume(RetVal, true);
assert(State && "Assumption on new value should not fail.");
return State;
@ -242,7 +242,7 @@ ProgramStateRef bindAndAssumeTrue(ProgramStateRef State, CheckerContext &C,
ProgramStateRef bindInt(uint64_t Value, ProgramStateRef State,
CheckerContext &C, const CallExpr *CE) {
State = State->BindExpr(CE, C.getLocationContext(),
State = State->BindExpr(CE, C.getStackFrame(),
C.getSValBuilder().makeIntVal(Value, CE->getType()));
return State;
}
@ -684,23 +684,23 @@ struct StreamOperationEvaluator {
ProgramStateRef makeAndBindRetVal(ProgramStateRef State, CheckerContext &C) {
NonLoc RetVal = makeRetVal(C, Elem.value()).castAs<NonLoc>();
return State->BindExpr(CE, C.getLocationContext(), RetVal);
return State->BindExpr(CE, C.getStackFrame(), RetVal);
}
ProgramStateRef bindReturnValue(ProgramStateRef State, CheckerContext &C,
uint64_t Val) {
return State->BindExpr(CE, C.getLocationContext(),
return State->BindExpr(CE, C.getStackFrame(),
SVB.makeIntVal(Val, CE->getCallReturnType(ACtx)));
}
ProgramStateRef bindReturnValue(ProgramStateRef State, CheckerContext &C,
SVal Val) {
return State->BindExpr(CE, C.getLocationContext(), Val);
return State->BindExpr(CE, C.getStackFrame(), Val);
}
ProgramStateRef bindNullReturnValue(ProgramStateRef State,
CheckerContext &C) {
return State->BindExpr(CE, C.getLocationContext(),
return State->BindExpr(CE, C.getStackFrame(),
C.getSValBuilder().makeNullWithType(CE->getType()));
}
@ -717,7 +717,7 @@ struct StreamOperationEvaluator {
ConstraintManager::ProgramStatePair
makeRetValAndAssumeDual(ProgramStateRef State, CheckerContext &C) {
DefinedSVal RetVal = makeRetVal(C, Elem.value());
State = State->BindExpr(CE, C.getLocationContext(), RetVal);
State = State->BindExpr(CE, C.getStackFrame(), RetVal);
return C.getConstraintManager().assumeDual(State, RetVal);
}
@ -841,7 +841,7 @@ escapeByStartIndexAndCount(ProgramStateRef State, const CallEvent &Call,
RegionAndSymbolInvalidationTraits::InvalidationKinds::
TK_DoNotInvalidateSuperRegion;
const LocationContext *LCtx = Call.getLocationContext();
const StackFrame *SF = Call.getStackFrame();
const ASTContext &Ctx = State->getStateManager().getContext();
SValBuilder &SVB = State->getStateManager().getSValBuilder();
auto &RegionManager = Buffer->getMemRegionManager();
@ -858,7 +858,7 @@ escapeByStartIndexAndCount(ProgramStateRef State, const CallEvent &Call,
ITraits.setTrait(Element, DoNotInvalidateSuperRegion);
}
return State->invalidateRegions(
EscapingVals, Call.getCFGElementRef(), BlockCount, LCtx,
EscapingVals, Call.getCFGElementRef(), BlockCount, SF,
/*CausesPointerEscape=*/false,
/*InvalidatedSymbols=*/nullptr, &Call, &ITraits);
}
@ -869,7 +869,7 @@ static ProgramStateRef escapeArgs(ProgramStateRef State, CheckerContext &C,
auto GetArgSVal = [&Call](int Idx) { return Call.getArgSVal(Idx); };
auto EscapingVals = to_vector(map_range(EscapingArgs, GetArgSVal));
State = State->invalidateRegions(EscapingVals, Call.getCFGElementRef(),
C.blockCount(), C.getLocationContext(),
C.blockCount(), C.getStackFrame(),
/*CausesPointerEscape=*/false,
/*InvalidatedSymbols=*/nullptr);
return State;
@ -906,10 +906,10 @@ ProgramStateRef StreamChecker::assumeNoAliasingWithStdStreams(
const VarDecl *Var) -> ProgramStateRef {
if (!Var)
return State;
const auto *LCtx = C.getLocationContext();
const auto *SF = C.getStackFrame();
auto &StoreMgr = C.getStoreManager();
auto &SVB = C.getSValBuilder();
SVal VarValue = State->getSVal(StoreMgr.getLValueVar(Var, LCtx));
SVal VarValue = State->getSVal(StoreMgr.getLValueVar(Var, SF));
auto NoAliasState =
SVB.evalBinOp(State, BO_NE, RetVal, VarValue, SVB.getConditionType())
.castAs<DefinedOrUnknownSVal>();
@ -935,7 +935,7 @@ void StreamChecker::evalFopen(const FnDescription *Desc, const CallEvent &Call,
SymbolRef RetSym = RetVal.getAsSymbol();
assert(RetSym && "RetVal must be a symbol here.");
State = State->BindExpr(CE, C.getLocationContext(), RetVal);
State = State->BindExpr(CE, C.getStackFrame(), RetVal);
// Bifurcate the state into two: one with a valid FILE* pointer, the other
// with a NULL.
@ -996,11 +996,11 @@ void StreamChecker::evalFreopen(const FnDescription *Desc,
// According to the documentations, the stream is closed first
// but any close error is ignored. The state changes to (or remains) opened.
ProgramStateRef StateRetNotNull =
State->BindExpr(CE, C.getLocationContext(), *StreamVal);
State->BindExpr(CE, C.getStackFrame(), *StreamVal);
// Generate state for NULL return value.
// Stream switches to OpenFailed state.
ProgramStateRef StateRetNull =
State->BindExpr(CE, C.getLocationContext(),
State->BindExpr(CE, C.getStackFrame(),
C.getSValBuilder().makeNullWithType(CE->getType()));
StateRetNotNull =
@ -1189,7 +1189,7 @@ void StreamChecker::evalFreadFwrite(const FnDescription *Desc,
// If we know the state to be FEOF at fread, do not add a success state.
if (!IsFread || !E.isStreamEof()) {
ProgramStateRef StateNotFailed =
State->BindExpr(E.CE, C.getLocationContext(), *NMembVal);
State->BindExpr(E.CE, C.getStackFrame(), *NMembVal);
StateNotFailed =
E.setStreamState(StateNotFailed, StreamState::getOpened(Desc));
C.addTransition(StateNotFailed);
@ -1202,7 +1202,7 @@ void StreamChecker::evalFreadFwrite(const FnDescription *Desc,
NonLoc RetVal = makeRetVal(C, E.Elem.value()).castAs<NonLoc>();
ProgramStateRef StateFailed =
State->BindExpr(E.CE, C.getLocationContext(), RetVal);
State->BindExpr(E.CE, C.getStackFrame(), RetVal);
StateFailed = E.assumeBinOpNN(StateFailed, BO_LT, RetVal, *NMembVal);
if (!StateFailed)
return;
@ -1237,7 +1237,7 @@ void StreamChecker::evalFgetx(const FnDescription *Desc, const CallEvent &Call,
// Generate a transition for the success state of `fgetc`.
NonLoc RetVal = makeRetVal(C, E.Elem.value()).castAs<NonLoc>();
ProgramStateRef StateNotFailed =
State->BindExpr(E.CE, C.getLocationContext(), RetVal);
State->BindExpr(E.CE, C.getStackFrame(), RetVal);
// The returned 'unsigned char' of `fgetc` is converted to 'int',
// so we need to check if it is in range [0, 255].
StateNotFailed = StateNotFailed->assumeInclusiveRange(
@ -1255,7 +1255,7 @@ void StreamChecker::evalFgetx(const FnDescription *Desc, const CallEvent &Call,
if (!GetBuf)
return;
ProgramStateRef StateNotFailed =
State->BindExpr(E.CE, C.getLocationContext(), *GetBuf);
State->BindExpr(E.CE, C.getStackFrame(), *GetBuf);
StateNotFailed =
E.setStreamState(StateNotFailed, StreamState::getOpened(Desc));
C.addTransition(StateNotFailed);
@ -1294,7 +1294,7 @@ void StreamChecker::evalFputx(const FnDescription *Desc, const CallEvent &Call,
if (!PutVal)
return;
ProgramStateRef StateNotFailed =
State->BindExpr(E.CE, C.getLocationContext(), *PutVal);
State->BindExpr(E.CE, C.getStackFrame(), *PutVal);
StateNotFailed =
E.setStreamState(StateNotFailed, StreamState::getOpened(Desc));
C.addTransition(StateNotFailed);
@ -1302,7 +1302,7 @@ void StreamChecker::evalFputx(const FnDescription *Desc, const CallEvent &Call,
// Generate a transition for the success state of `fputs`.
NonLoc RetVal = makeRetVal(C, E.Elem.value()).castAs<NonLoc>();
ProgramStateRef StateNotFailed =
State->BindExpr(E.CE, C.getLocationContext(), RetVal);
State->BindExpr(E.CE, C.getStackFrame(), RetVal);
StateNotFailed =
E.assumeBinOpNN(StateNotFailed, BO_GE, RetVal, E.getZeroVal(Call));
if (!StateNotFailed)
@ -1335,7 +1335,7 @@ void StreamChecker::evalFprintf(const FnDescription *Desc,
return;
NonLoc RetVal = makeRetVal(C, E.Elem.value()).castAs<NonLoc>();
State = State->BindExpr(E.CE, C.getLocationContext(), RetVal);
State = State->BindExpr(E.CE, C.getStackFrame(), RetVal);
auto Cond =
E.SVB
.evalBinOp(State, BO_GE, RetVal, E.SVB.makeZeroVal(E.ACtx.IntTy),
@ -1381,7 +1381,7 @@ void StreamChecker::evalFscanf(const FnDescription *Desc, const CallEvent &Call,
if (!E.isStreamEof()) {
NonLoc RetVal = makeRetVal(C, E.Elem.value()).castAs<NonLoc>();
ProgramStateRef StateNotFailed =
State->BindExpr(E.CE, C.getLocationContext(), RetVal);
State->BindExpr(E.CE, C.getStackFrame(), RetVal);
StateNotFailed =
E.assumeBinOpNN(StateNotFailed, BO_GE, RetVal, E.getZeroVal(Call));
if (!StateNotFailed)
@ -1495,8 +1495,8 @@ void StreamChecker::evalGetdelim(const FnDescription *Desc,
StateFailed, StreamState::getOpened(Desc, NewES, !NewES.isFEof()));
// On failure, the content of the buffer is undefined.
if (auto NewLinePtr = getPointeeVal(Call.getArgSVal(0), State))
StateFailed = StateFailed->bindLoc(*NewLinePtr, UndefinedVal(),
C.getLocationContext());
StateFailed =
StateFailed->bindLoc(*NewLinePtr, UndefinedVal(), C.getStackFrame());
C.addTransition(StateFailed, E.getFailureNoteTag(this, C));
}
@ -1603,7 +1603,7 @@ void StreamChecker::evalFtell(const FnDescription *Desc, const CallEvent &Call,
NonLoc RetVal = makeRetVal(C, E.Elem.value()).castAs<NonLoc>();
ProgramStateRef StateNotFailed =
State->BindExpr(E.CE, C.getLocationContext(), RetVal);
State->BindExpr(E.CE, C.getStackFrame(), RetVal);
StateNotFailed =
E.assumeBinOpNN(StateNotFailed, BO_GE, RetVal, E.getZeroVal(Call));
if (!StateNotFailed)
@ -1771,7 +1771,7 @@ void StreamChecker::evalFileno(const FnDescription *Desc, const CallEvent &Call,
return;
NonLoc RetVal = makeRetVal(C, E.Elem.value()).castAs<NonLoc>();
State = State->BindExpr(E.CE, C.getLocationContext(), RetVal);
State = State->BindExpr(E.CE, C.getStackFrame(), RetVal);
State = E.assumeBinOpNN(State, BO_GE, RetVal, E.getZeroVal(Call));
if (!State)
return;
@ -1868,8 +1868,7 @@ public:
if (!S)
return nullptr;
Satisfied = true;
PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
N->getLocationContext());
PathDiagnosticLocation Pos(S, BRC.getSourceManager(), N->getStackFrame());
llvm::StringLiteral Msg = "Stream is closed here";
return std::make_shared<PathDiagnosticEventPiece>(Pos, Msg);
}
@ -2034,15 +2033,13 @@ StreamChecker::reportLeaks(const SmallVector<SymbolRef, 2> &LeakedSyms,
PathDiagnosticLocation LocUsedForUniqueing;
if (const Stmt *StreamStmt = StreamOpenNode->getStmtForDiagnostics())
LocUsedForUniqueing = PathDiagnosticLocation::createBegin(
StreamStmt, C.getSourceManager(),
StreamOpenNode->getLocationContext());
StreamStmt, C.getSourceManager(), StreamOpenNode->getStackFrame());
std::unique_ptr<PathSensitiveBugReport> R =
std::make_unique<PathSensitiveBugReport>(
BT_ResourceLeak,
"Opened stream never closed. Potential resource leak.", Err,
LocUsedForUniqueing,
StreamOpenNode->getLocationContext()->getDecl());
LocUsedForUniqueing, StreamOpenNode->getStackFrame()->getDecl());
R->markInteresting(LeakSym);
R->addVisitor<NoStreamStateChangeVisitor>(LeakSym, this);
C.emitReport(std::move(R));

View file

@ -44,9 +44,8 @@ void taint::dumpTaint(ProgramStateRef State) {
}
ProgramStateRef taint::addTaint(ProgramStateRef State, const Expr *E,
const LocationContext *LCtx,
TaintTagType Kind) {
return addTaint(State, State->getSVal(E, LCtx), Kind);
const StackFrame *SF, TaintTagType Kind) {
return addTaint(State, State->getSVal(E, SF), Kind);
}
ProgramStateRef taint::addTaint(ProgramStateRef State, SVal V,
@ -146,8 +145,8 @@ ProgramStateRef taint::addPartialTaint(ProgramStateRef State,
}
bool taint::isTainted(ProgramStateRef State, const Expr *E,
const LocationContext *LCtx, TaintTagType Kind) {
return !getTaintedSymbolsImpl(State, E, LCtx, Kind, /*ReturnFirstOnly=*/true)
const StackFrame *SF, TaintTagType Kind) {
return !getTaintedSymbolsImpl(State, E, SF, Kind, /*ReturnFirstOnly=*/true)
.empty();
}
@ -169,9 +168,9 @@ bool taint::isTainted(ProgramStateRef State, SymbolRef Sym, TaintTagType Kind) {
std::vector<SymbolRef> taint::getTaintedSymbols(ProgramStateRef State,
const Expr *E,
const LocationContext *LCtx,
const StackFrame *SF,
TaintTagType Kind) {
return getTaintedSymbolsImpl(State, E, LCtx, Kind,
return getTaintedSymbolsImpl(State, E, SF, Kind,
/*ReturnFirstOnly=*/false);
}
@ -194,10 +193,10 @@ std::vector<SymbolRef> taint::getTaintedSymbols(ProgramStateRef State,
std::vector<SymbolRef> taint::getTaintedSymbolsImpl(ProgramStateRef State,
const Expr *E,
const LocationContext *LCtx,
const StackFrame *SF,
TaintTagType Kind,
bool returnFirstOnly) {
SVal val = State->getSVal(E, LCtx);
SVal val = State->getSVal(E, SF);
return getTaintedSymbolsImpl(State, val, Kind, returnFirstOnly);
}

View file

@ -36,7 +36,7 @@ void TaintTesterChecker::checkPostStmt(const Expr *E,
if (!State)
return;
if (isTainted(State, E, C.getLocationContext())) {
if (isTainted(State, E, C.getStackFrame())) {
if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
auto report = std::make_unique<PathSensitiveBugReport>(BT, "tainted", N);
report->addRange(E->getSourceRange());

View file

@ -67,8 +67,8 @@ public:
void CallDumper::checkPreCall(const CallEvent &Call, CheckerContext &C) const {
unsigned Indentation = 0;
for (const LocationContext *LC = C.getLocationContext()->getParent();
LC != nullptr; LC = LC->getParent())
for (const StackFrame *SF = C.getStackFrame()->getParent(); SF != nullptr;
SF = SF->getParent())
++Indentation;
// It is mildly evil to print directly to llvm::outs() rather than emitting
@ -84,8 +84,8 @@ void CallDumper::checkPostCall(const CallEvent &Call, CheckerContext &C) const {
return;
unsigned Indentation = 0;
for (const LocationContext *LC = C.getLocationContext()->getParent();
LC != nullptr; LC = LC->getParent())
for (const StackFrame *SF = C.getStackFrame()->getParent(); SF != nullptr;
SF = SF->getParent())
++Indentation;
// It is mildly evil to print directly to llvm::outs() rather than emitting

View file

@ -60,7 +60,7 @@ public:
const FunctionDecl *
UnconditionalVAArgChecker::getCurrentFunction(CheckerContext &C) {
const Decl *FD = C.getLocationContext()->getDecl();
const Decl *FD = C.getStackFrame()->getDecl();
return dyn_cast_if_present<FunctionDecl>(FD);
}

View file

@ -31,10 +31,10 @@ class UndefBranchChecker : public Checker<check::BranchCondition> {
struct FindUndefExpr {
ProgramStateRef St;
const LocationContext *LCtx;
const StackFrame *SF;
FindUndefExpr(ProgramStateRef S, const LocationContext *L)
: St(std::move(S)), LCtx(L) {}
FindUndefExpr(ProgramStateRef S, const StackFrame *SF)
: St(std::move(S)), SF(SF) {}
const Expr *FindExpr(const Expr *Ex) {
if (!MatchesCriteria(Ex))
@ -49,7 +49,7 @@ class UndefBranchChecker : public Checker<check::BranchCondition> {
}
bool MatchesCriteria(const Expr *Ex) {
return St->getSVal(Ex, LCtx).isUndef();
return St->getSVal(Ex, SF).isUndef();
}
};
@ -97,7 +97,7 @@ void UndefBranchChecker::checkBranchCondition(const Stmt *Condition,
if (PS->getStmt() == Ex)
St = PrevN->getState();
FindUndefExpr FindIt(St, Ctx.getLocationContext());
FindUndefExpr FindIt(St, Ctx.getStackFrame());
Ex = FindIt.FindExpr(Ex);
// Emit the bug report.

View file

@ -40,7 +40,7 @@ UndefinedArraySubscriptChecker::checkPreStmt(const ArraySubscriptExpr *A,
// Sema generates anonymous array variables for copying array struct fields.
// Don't warn if we're in an implicitly-generated constructor.
const Decl *D = C.getLocationContext()->getDecl();
const Decl *D = C.getStackFrame()->getDecl();
if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D))
if (Ctor->isDefaulted())
return;

View file

@ -133,8 +133,8 @@ static bool hasUnguardedAccess(const FieldDecl *FD, ProgramStateRef State);
void UninitializedObjectChecker::checkEndFunction(
const ReturnStmt *RS, CheckerContext &Context) const {
const auto *CtorDecl = dyn_cast_or_null<CXXConstructorDecl>(
Context.getLocationContext()->getDecl());
const auto *CtorDecl =
dyn_cast_or_null<CXXConstructorDecl>(Context.getStackFrame()->getDecl());
if (!CtorDecl)
return;
@ -175,7 +175,7 @@ void UninitializedObjectChecker::checkEndFunction(
const Expr *CallSite = Context.getStackFrame()->getCallSite();
if (CallSite)
LocUsedForUniqueing = PathDiagnosticLocation::createBegin(
CallSite, Context.getSourceManager(), Node->getLocationContext());
CallSite, Context.getSourceManager(), Node->getStackFrame());
// For Plist consumers that don't support notes just yet, we'll convert notes
// to warnings.
@ -184,7 +184,7 @@ void UninitializedObjectChecker::checkEndFunction(
auto Report = std::make_unique<PathSensitiveBugReport>(
BT_uninitField, Pair.second, Node, LocUsedForUniqueing,
Node->getLocationContext()->getDecl());
Node->getStackFrame()->getDecl());
Context.emitReport(std::move(Report));
}
return;
@ -198,7 +198,7 @@ void UninitializedObjectChecker::checkEndFunction(
auto Report = std::make_unique<PathSensitiveBugReport>(
BT_uninitField, WarningOS.str(), Node, LocUsedForUniqueing,
Node->getLocationContext()->getDecl());
Node->getStackFrame()->getDecl());
for (const auto &Pair : UninitFields) {
Report->addNote(Pair.second,
@ -492,11 +492,11 @@ static bool willObjectBeAnalyzedLater(const CXXConstructorDecl *Ctor,
if (!CurrRegion)
return false;
const LocationContext *LC = Context.getLocationContext();
while ((LC = LC->getParent())) {
const StackFrame *SF = Context.getStackFrame();
while ((SF = SF->getParent())) {
// If \p Ctor was called by another constructor.
const auto *OtherCtor = dyn_cast<CXXConstructorDecl>(LC->getDecl());
const auto *OtherCtor = dyn_cast<CXXConstructorDecl>(SF->getDecl());
if (!OtherCtor)
continue;

View file

@ -57,22 +57,22 @@ void UnreachableCodeChecker::checkEndAnalysis(ExplodedGraph &G,
const Decl *D = nullptr;
CFG *C = nullptr;
const ParentMap *PM = nullptr;
const LocationContext *LC = nullptr;
const StackFrame *SF = nullptr;
// Iterate over ExplodedGraph
for (const ExplodedNode &N : G.nodes()) {
const ProgramPoint &P = N.getLocation();
LC = P.getLocationContext();
if (!LC->inTopFrame())
SF = P.getStackFrame();
if (!SF->inTopFrame())
continue;
if (!D)
D = LC->getAnalysisDeclContext()->getDecl();
D = SF->getAnalysisDeclContext()->getDecl();
// Save the CFG if we don't have it already
if (!C)
C = LC->getAnalysisDeclContext()->getUnoptimizedCFG();
C = SF->getAnalysisDeclContext()->getUnoptimizedCFG();
if (!PM)
PM = &LC->getParentMap();
PM = &SF->getParentMap();
if (std::optional<BlockEntrance> BE = P.getAs<BlockEntrance>()) {
const CFGBlock *CB = BE->getBlock();
@ -155,7 +155,7 @@ void UnreachableCodeChecker::checkEndAnalysis(ExplodedGraph &G,
if (isa<DoStmt>(Parent))
continue;
SR = S->getSourceRange();
DL = PathDiagnosticLocation::createBegin(S, B.getSourceManager(), LC);
DL = PathDiagnosticLocation::createBegin(S, B.getSourceManager(), SF);
SL = DL.asLocation();
if (SR.isInvalid() || !SL.isValid())
continue;

View file

@ -235,7 +235,7 @@ void VAListChecker::checkDeadSymbols(SymbolReaper &SR,
const ExplodedNode *
VAListChecker::getStartCallSite(const ExplodedNode *N,
const MemRegion *Reg) const {
const LocationContext *LeakContext = N->getLocationContext();
const StackFrame *LeakSF = N->getStackFrame();
const ExplodedNode *StartCallNode = N;
bool SeenInitializedState = false;
@ -247,8 +247,7 @@ VAListChecker::getStartCallSite(const ExplodedNode *N,
} else if (SeenInitializedState) {
break;
}
const LocationContext *NContext = N->getLocationContext();
if (NContext == LeakContext || NContext->isParentOf(LeakContext))
if (N->getStackFrame() == LeakSF || N->getStackFrame()->isParentOf(LeakSF))
StartCallNode = N;
N = N->pred_empty() ? nullptr : *(N->pred_begin());
}
@ -276,7 +275,7 @@ void VAListChecker::reportLeaked(const RegionVector &Leaked, StringRef Msg1,
if (const Stmt *StartCallStmt = StartNode->getStmtForDiagnostics())
LocUsedForUniqueing = PathDiagnosticLocation::createBegin(
StartCallStmt, C.getSourceManager(), StartNode->getLocationContext());
StartCallStmt, C.getSourceManager(), StartNode->getStackFrame());
SmallString<100> Buf;
llvm::raw_svector_ostream OS(Buf);
@ -288,7 +287,7 @@ void VAListChecker::reportLeaked(const RegionVector &Leaked, StringRef Msg1,
auto R = std::make_unique<PathSensitiveBugReport>(
LeakBug, OS.str(), N, LocUsedForUniqueing,
StartNode->getLocationContext()->getDecl());
StartNode->getStackFrame()->getDecl());
R->markInteresting(Reg);
R->addVisitor(std::make_unique<VAListBugVisitor>(Reg, true));
C.emitReport(std::move(R));
@ -413,8 +412,7 @@ PathDiagnosticPieceRef VAListChecker::VAListBugVisitor::VisitNode(
if (Msg.empty())
return nullptr;
PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
N->getLocationContext());
PathDiagnosticLocation Pos(S, BRC.getSourceManager(), N->getStackFrame());
return std::make_shared<PathDiagnosticEventPiece>(Pos, Msg, true);
}

View file

@ -296,9 +296,8 @@ void VLASizeChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const {
// VLASizeChecker is responsible for defining the extent of the array.
if (VD) {
State =
setDynamicExtent(State, State->getRegion(VD, C.getLocationContext()),
ArraySize.castAs<NonLoc>());
State = setDynamicExtent(State, State->getRegion(VD, C.getStackFrame()),
ArraySize.castAs<NonLoc>());
}
// Remember our assumptions!

View file

@ -158,17 +158,16 @@ void VforkChecker::checkPostCall(const CallEvent &Call,
return;
// Get assigned variable.
const ParentMap &PM = C.getLocationContext()->getParentMap();
const ParentMap &PM = C.getStackFrame()->getParentMap();
const Stmt *P = PM.getParentIgnoreParenCasts(Call.getOriginExpr());
const VarDecl *LhsDecl;
std::tie(LhsDecl, std::ignore) = parseAssignment(P);
// Get assigned memory region.
MemRegionManager &M = C.getStoreManager().getRegionManager();
const MemRegion *LhsDeclReg =
LhsDecl
? M.getVarRegion(LhsDecl, C.getLocationContext())
: (const MemRegion *)VFORK_RESULT_NONE;
const MemRegion *LhsDeclReg = LhsDecl
? M.getVarRegion(LhsDecl, C.getStackFrame())
: (const MemRegion *)VFORK_RESULT_NONE;
// Parent branch gets nonzero return value (according to manpage).
ProgramStateRef ParentState, ChildState;

View file

@ -177,8 +177,8 @@ void VirtualCallChecker::checkPreCall(const CallEvent &Call,
void VirtualCallChecker::registerCtorDtorCallInState(bool IsBeginFunction,
CheckerContext &C) const {
const auto *LCtx = C.getLocationContext();
const auto *MD = dyn_cast_or_null<CXXMethodDecl>(LCtx->getDecl());
const auto *SF = C.getStackFrame();
const auto *MD = dyn_cast_or_null<CXXMethodDecl>(SF->getDecl());
if (!MD)
return;
@ -187,8 +187,7 @@ void VirtualCallChecker::registerCtorDtorCallInState(bool IsBeginFunction,
// Enter a constructor, set the corresponding memregion be true.
if (isa<CXXConstructorDecl>(MD)) {
auto ThiSVal =
State->getSVal(SVB.getCXXThis(MD, LCtx->getStackFrame()));
auto ThiSVal = State->getSVal(SVB.getCXXThis(MD, SF));
const MemRegion *Reg = ThiSVal.getAsRegion();
if (IsBeginFunction)
State = State->set<CtorDtorMap>(Reg, ObjectState::CtorCalled);
@ -201,8 +200,7 @@ void VirtualCallChecker::registerCtorDtorCallInState(bool IsBeginFunction,
// Enter a Destructor, set the corresponding memregion be true.
if (isa<CXXDestructorDecl>(MD)) {
auto ThiSVal =
State->getSVal(SVB.getCXXThis(MD, LCtx->getStackFrame()));
auto ThiSVal = State->getSVal(SVB.getCXXThis(MD, SF));
const MemRegion *Reg = ThiSVal.getAsRegion();
if (IsBeginFunction)
State = State->set<CtorDtorMap>(Reg, ObjectState::DtorCalled);

View file

@ -202,13 +202,13 @@ void InvalidPtrChecker::postPreviousReturnInvalidatingCall(
});
}
const LocationContext *LCtx = C.getLocationContext();
const StackFrame *SF = C.getStackFrame();
const auto *CE = cast<CallExpr>(Call.getOriginExpr());
// Function call will return a pointer to the new symbolic region.
DefinedOrUnknownSVal RetVal =
C.getSValBuilder().conjureSymbolVal(Call, C.blockCount());
State = State->BindExpr(CE, LCtx, RetVal);
State = State->BindExpr(CE, SF, RetVal);
const auto *SymRegOfRetVal =
dyn_cast_or_null<SymbolicRegion>(RetVal.getAsRegion());
@ -316,13 +316,13 @@ void InvalidPtrChecker::checkBeginFunction(CheckerContext &C) const {
if (!C.inTopFrame())
return;
const auto *FD = dyn_cast<FunctionDecl>(C.getLocationContext()->getDecl());
const auto *FD = dyn_cast<FunctionDecl>(C.getStackFrame()->getDecl());
if (!FD || FD->param_size() != 3 || !FD->isMain())
return;
ProgramStateRef State = C.getState();
const MemRegion *EnvpReg =
State->getRegion(FD->parameters()[2], C.getLocationContext());
State->getRegion(FD->parameters()[2], C.getStackFrame());
// Save the memory region pointed by the environment pointer parameter of
// 'main'.

View file

@ -107,10 +107,9 @@ using CallWithEntryStack = SmallVector<CallWithEntry, 6>;
using VisitorsDiagnosticsTy =
llvm::DenseMap<const ExplodedNode *, std::vector<PathDiagnosticPieceRef>>;
/// A map from PathDiagnosticPiece to the LocationContext of the inlined
/// A map from PathDiagnosticPiece to the StackFrame of the inlined
/// function call it represents.
using LocationContextMap =
llvm::DenseMap<const PathPieces *, const LocationContext *>;
using StackFrameMap = llvm::DenseMap<const PathPieces *, const StackFrame *>;
/// A helper class that contains everything needed to construct a
/// PathDiagnostic object. It does no much more then providing convenient
@ -123,8 +122,8 @@ class PathDiagnosticConstruct {
const ExplodedNode *CurrentNode;
/// A mapping from parts of the bug path (for example, a function call, which
/// would span backwards from a CallExit to a CallEnter with the nodes in
/// between them) with the location contexts it is associated with.
LocationContextMap LCM;
/// between them) with the stack frames it is associated with.
StackFrameMap SFM;
const SourceManager &SM;
public:
@ -143,18 +142,18 @@ public:
const PathSensitiveBugReport *R,
const Decl *AnalysisEntryPoint);
/// \returns the location context associated with the current position in the
/// \returns the stack frame associated with the current position in the
/// bug path.
const LocationContext *getCurrLocationContext() const {
const StackFrame *getCurrStackFrame() const {
assert(CurrentNode && "Already reached the root!");
return CurrentNode->getLocationContext();
return CurrentNode->getStackFrame();
}
/// Same as getCurrLocationContext (they should always return the same
/// location context), but works after reaching the root of the bug path as
/// Same as getCurrStackFrame (they should always return the same
/// stack frame), but works after reaching the root of the bug path as
/// well.
const LocationContext *getLocationContextForActivePath() const {
return LCM.find(&PD->getActivePath())->getSecond();
const StackFrame *getStackFrameForActivePath() const {
return SFM.find(&PD->getActivePath())->getSecond();
}
const ExplodedNode *getCurrentNode() const { return CurrentNode; }
@ -167,7 +166,7 @@ public:
}
const ParentMap &getParentMap() const {
return getCurrLocationContext()->getParentMap();
return getCurrStackFrame()->getParentMap();
}
const SourceManager &getSourceManager() const { return SM; }
@ -176,18 +175,20 @@ public:
return getParentMap().getParent(S);
}
void updateLocCtxMap(const PathPieces *Path, const LocationContext *LC) {
assert(Path && LC);
LCM[Path] = LC;
void updateStackFrameMap(const PathPieces *Path, const StackFrame *SF) {
assert(Path && SF);
SFM[Path] = SF;
}
const LocationContext *getLocationContextFor(const PathPieces *Path) const {
assert(LCM.count(Path) &&
"Failed to find the context associated with these pieces!");
return LCM.find(Path)->getSecond();
const StackFrame *getStackFrameFor(const PathPieces *Path) const {
assert(SFM.count(Path) &&
"Failed to find the stack frame associated with these pieces!");
return SFM.find(Path)->getSecond();
}
bool isInLocCtxMap(const PathPieces *Path) const { return LCM.count(Path); }
bool isInStackFrameMap(const PathPieces *Path) const {
return SFM.count(Path);
}
PathPieces &getActivePath() { return PD->getActivePath(); }
PathPieces &getMutablePieces() { return PD->getMutablePieces(); }
@ -323,7 +324,7 @@ std::string StackHintGeneratorForSymbol::getMessage(const ExplodedNode *N){
CallExitEnd CExit = P.castAs<CallExitEnd>();
// FIXME: Use CallEvent to abstract this over all calls.
const Expr *CallSite = CExit.getCalleeContext()->getCallSite();
const Expr *CallSite = CExit.getCalleeStackFrame()->getCallSite();
const auto *CE = dyn_cast_or_null<CallExpr>(CallSite);
if (!CE)
return {};
@ -467,10 +468,10 @@ static bool removeUnneededCalls(const PathDiagnosticConstruct &C,
switch (piece->getKind()) {
case PathDiagnosticPiece::Call: {
auto &call = cast<PathDiagnosticCallPiece>(*piece);
// Check if the location context is interesting.
// Check if the stack frame is interesting.
if (!removeUnneededCalls(
C, call.path, R,
R->isInteresting(C.getLocationContextFor(&call.path))))
R->isInteresting(C.getStackFrameFor(&call.path))))
continue;
containsSomethingInteresting = true;
@ -610,10 +611,9 @@ static void removePiecesWithInvalidLocations(PathPieces &Pieces) {
PathDiagnosticLocation PathDiagnosticBuilder::ExecutionContinues(
const PathDiagnosticConstruct &C) const {
if (const Stmt *S = C.getCurrentNode()->getNextStmtForDiagnostics())
return PathDiagnosticLocation(S, getSourceManager(),
C.getCurrLocationContext());
return PathDiagnosticLocation(S, getSourceManager(), C.getCurrStackFrame());
return PathDiagnosticLocation::createDeclEnd(C.getCurrLocationContext(),
return PathDiagnosticLocation::createDeclEnd(C.getCurrStackFrame(),
getSourceManager());
}
@ -631,7 +631,7 @@ PathDiagnosticLocation PathDiagnosticBuilder::ExecutionContinues(
<< '.';
else {
os << "Execution jumps to the end of the ";
const Decl *D = C.getCurrLocationContext()->getDecl();
const Decl *D = C.getCurrStackFrame()->getDecl();
if (isa<ObjCMethodDecl>(D))
os << "method";
else if (isa<FunctionDecl>(D))
@ -669,61 +669,61 @@ static const Stmt *getEnclosingParent(const Stmt *S, const ParentMap &PM) {
}
static PathDiagnosticLocation
getEnclosingStmtLocation(const Stmt *S, const LocationContext *LC,
getEnclosingStmtLocation(const Stmt *S, const StackFrame *SF,
bool allowNestedContexts = false) {
if (!S)
return {};
const SourceManager &SMgr = LC->getDecl()->getASTContext().getSourceManager();
const SourceManager &SMgr = SF->getDecl()->getASTContext().getSourceManager();
while (const Stmt *Parent = getEnclosingParent(S, LC->getParentMap())) {
while (const Stmt *Parent = getEnclosingParent(S, SF->getParentMap())) {
switch (Parent->getStmtClass()) {
case Stmt::BinaryOperatorClass: {
const auto *B = cast<BinaryOperator>(Parent);
if (B->isLogicalOp())
return PathDiagnosticLocation(allowNestedContexts ? B : S, SMgr, LC);
return PathDiagnosticLocation(allowNestedContexts ? B : S, SMgr, SF);
break;
}
case Stmt::CompoundStmtClass:
case Stmt::StmtExprClass:
return PathDiagnosticLocation(S, SMgr, LC);
return PathDiagnosticLocation(S, SMgr, SF);
case Stmt::ChooseExprClass:
// Similar to '?' if we are referring to condition, just have the edge
// point to the entire choose expression.
if (allowNestedContexts || cast<ChooseExpr>(Parent)->getCond() == S)
return PathDiagnosticLocation(Parent, SMgr, LC);
return PathDiagnosticLocation(Parent, SMgr, SF);
else
return PathDiagnosticLocation(S, SMgr, LC);
return PathDiagnosticLocation(S, SMgr, SF);
case Stmt::BinaryConditionalOperatorClass:
case Stmt::ConditionalOperatorClass:
// For '?', if we are referring to condition, just have the edge point
// to the entire '?' expression.
if (allowNestedContexts ||
cast<AbstractConditionalOperator>(Parent)->getCond() == S)
return PathDiagnosticLocation(Parent, SMgr, LC);
return PathDiagnosticLocation(Parent, SMgr, SF);
else
return PathDiagnosticLocation(S, SMgr, LC);
return PathDiagnosticLocation(S, SMgr, SF);
case Stmt::CXXForRangeStmtClass:
if (cast<CXXForRangeStmt>(Parent)->getBody() == S)
return PathDiagnosticLocation(S, SMgr, LC);
return PathDiagnosticLocation(S, SMgr, SF);
break;
case Stmt::DoStmtClass:
return PathDiagnosticLocation(S, SMgr, LC);
return PathDiagnosticLocation(S, SMgr, SF);
case Stmt::ForStmtClass:
if (cast<ForStmt>(Parent)->getBody() == S)
return PathDiagnosticLocation(S, SMgr, LC);
return PathDiagnosticLocation(S, SMgr, SF);
break;
case Stmt::IfStmtClass:
if (cast<IfStmt>(Parent)->getCond() != S)
return PathDiagnosticLocation(S, SMgr, LC);
return PathDiagnosticLocation(S, SMgr, SF);
break;
case Stmt::ObjCForCollectionStmtClass:
if (cast<ObjCForCollectionStmt>(Parent)->getBody() == S)
return PathDiagnosticLocation(S, SMgr, LC);
return PathDiagnosticLocation(S, SMgr, SF);
break;
case Stmt::WhileStmtClass:
if (cast<WhileStmt>(Parent)->getCond() != S)
return PathDiagnosticLocation(S, SMgr, LC);
return PathDiagnosticLocation(S, SMgr, SF);
break;
default:
break;
@ -734,7 +734,7 @@ getEnclosingStmtLocation(const Stmt *S, const LocationContext *LC,
assert(S && "Cannot have null Stmt for PathDiagnosticLocation");
return PathDiagnosticLocation(S, SMgr, LC);
return PathDiagnosticLocation(S, SMgr, SF);
}
//===----------------------------------------------------------------------===//
@ -781,7 +781,7 @@ PathDiagnosticPieceRef PathDiagnosticBuilder::generateDiagForSwitchOP(
PathDiagnosticLocation End;
if (const Stmt *S = Dst->getLabel()) {
End = PathDiagnosticLocation(S, SM, C.getCurrLocationContext());
End = PathDiagnosticLocation(S, SM, C.getCurrStackFrame());
switch (S->getStmtClass()) {
default:
@ -833,7 +833,7 @@ PathDiagnosticPieceRef PathDiagnosticBuilder::generateDiagForGotoOP(
std::string sbuf;
llvm::raw_string_ostream os(sbuf);
const PathDiagnosticLocation &End =
getEnclosingStmtLocation(S, C.getCurrLocationContext());
getEnclosingStmtLocation(S, C.getCurrStackFrame());
os << "Control jumps to line " << End.asLocation().getExpansionLineNumber();
return std::make_shared<PathDiagnosticControlFlowPiece>(Start, End, sbuf);
}
@ -856,13 +856,12 @@ PathDiagnosticPieceRef PathDiagnosticBuilder::generateDiagForBinaryOP(
if (*(Src->succ_begin() + 1) == Dst) {
os << "false";
End = PathDiagnosticLocation(B->getLHS(), SM, C.getCurrLocationContext());
End = PathDiagnosticLocation(B->getLHS(), SM, C.getCurrStackFrame());
Start =
PathDiagnosticLocation::createOperatorLoc(B, SM);
} else {
os << "true";
Start =
PathDiagnosticLocation(B->getLHS(), SM, C.getCurrLocationContext());
Start = PathDiagnosticLocation(B->getLHS(), SM, C.getCurrStackFrame());
End = ExecutionContinues(C);
}
} else {
@ -872,12 +871,11 @@ PathDiagnosticPieceRef PathDiagnosticBuilder::generateDiagForBinaryOP(
if (*(Src->succ_begin() + 1) == Dst) {
os << "false";
Start =
PathDiagnosticLocation(B->getLHS(), SM, C.getCurrLocationContext());
Start = PathDiagnosticLocation(B->getLHS(), SM, C.getCurrStackFrame());
End = ExecutionContinues(C);
} else {
os << "true";
End = PathDiagnosticLocation(B->getLHS(), SM, C.getCurrLocationContext());
End = PathDiagnosticLocation(B->getLHS(), SM, C.getCurrStackFrame());
Start =
PathDiagnosticLocation::createOperatorLoc(B, SM);
}
@ -888,14 +886,14 @@ PathDiagnosticPieceRef PathDiagnosticBuilder::generateDiagForBinaryOP(
void PathDiagnosticBuilder::generateMinimalDiagForBlockEdge(
PathDiagnosticConstruct &C, BlockEdge BE) const {
const SourceManager &SM = getSourceManager();
const LocationContext *LC = C.getCurrLocationContext();
const StackFrame *SF = C.getCurrStackFrame();
const CFGBlock *Src = BE.getSrc();
const CFGBlock *Dst = BE.getDst();
const Stmt *T = Src->getTerminatorStmt();
if (!T)
return;
auto Start = PathDiagnosticLocation::createBegin(T, SM, LC);
auto Start = PathDiagnosticLocation::createBegin(T, SM, SF);
switch (T->getStmtClass()) {
default:
break;
@ -937,7 +935,7 @@ void PathDiagnosticBuilder::generateMinimalDiagForBlockEdge(
PathDiagnosticLocation End = ExecutionContinues(C);
if (const Stmt *S = End.asStmt())
End = getEnclosingStmtLocation(S, C.getCurrLocationContext());
End = getEnclosingStmtLocation(S, C.getCurrStackFrame());
C.getActivePath().push_front(
std::make_shared<PathDiagnosticControlFlowPiece>(Start, End, sbuf));
@ -962,7 +960,7 @@ void PathDiagnosticBuilder::generateMinimalDiagForBlockEdge(
PathDiagnosticLocation End = ExecutionContinues(os, C);
if (const Stmt *S = End.asStmt())
End = getEnclosingStmtLocation(S, C.getCurrLocationContext());
End = getEnclosingStmtLocation(S, C.getCurrStackFrame());
C.getActivePath().push_front(
std::make_shared<PathDiagnosticControlFlowPiece>(Start, End, sbuf));
@ -970,7 +968,7 @@ void PathDiagnosticBuilder::generateMinimalDiagForBlockEdge(
PathDiagnosticLocation End = ExecutionContinues(C);
if (const Stmt *S = End.asStmt())
End = getEnclosingStmtLocation(S, C.getCurrLocationContext());
End = getEnclosingStmtLocation(S, C.getCurrStackFrame());
C.getActivePath().push_front(
std::make_shared<PathDiagnosticControlFlowPiece>(
@ -987,14 +985,14 @@ void PathDiagnosticBuilder::generateMinimalDiagForBlockEdge(
os << "Loop condition is false. ";
PathDiagnosticLocation End = ExecutionContinues(os, C);
if (const Stmt *S = End.asStmt())
End = getEnclosingStmtLocation(S, C.getCurrLocationContext());
End = getEnclosingStmtLocation(S, C.getCurrStackFrame());
C.getActivePath().push_front(
std::make_shared<PathDiagnosticControlFlowPiece>(Start, End, sbuf));
} else {
PathDiagnosticLocation End = ExecutionContinues(C);
if (const Stmt *S = End.asStmt())
End = getEnclosingStmtLocation(S, C.getCurrLocationContext());
End = getEnclosingStmtLocation(S, C.getCurrStackFrame());
C.getActivePath().push_front(
std::make_shared<PathDiagnosticControlFlowPiece>(
@ -1007,7 +1005,7 @@ void PathDiagnosticBuilder::generateMinimalDiagForBlockEdge(
PathDiagnosticLocation End = ExecutionContinues(C);
if (const Stmt *S = End.asStmt())
End = getEnclosingStmtLocation(S, C.getCurrLocationContext());
End = getEnclosingStmtLocation(S, C.getCurrStackFrame());
if (*(Src->succ_begin() + 1) == Dst)
C.getActivePath().push_front(
@ -1161,8 +1159,8 @@ void PathDiagnosticBuilder::generatePathDiagnosticsForNode(
if (C.shouldAddPathEdges()) {
// Add an edge to the start of the function.
const StackFrame *CalleeLC = CE->getCalleeContext();
const Decl *D = CalleeLC->getDecl();
const StackFrame *CalleeSF = CE->getCalleeStackFrame();
const Decl *D = CalleeSF->getDecl();
// Add the edge only when the callee has body. We jump to the beginning
// of the *declaration*, however we expect it to be followed by the
// body. This isn't the case for autosynthesized property accessors in
@ -1182,26 +1180,26 @@ void PathDiagnosticBuilder::generatePathDiagnosticsForNode(
if (VisitedEntireCall) {
Call = cast<PathDiagnosticCallPiece>(C.getActivePath().front().get());
} else {
// The path terminated within a nested location context, create a new
// The path terminated within a nested stack frame, create a new
// call piece to encapsulate the rest of the path pieces.
const Decl *Caller = CE->getLocationContext()->getDecl();
const Decl *Caller = CE->getStackFrame()->getDecl();
Call = PathDiagnosticCallPiece::construct(C.getActivePath(), Caller);
assert(C.getActivePath().size() == 1 &&
C.getActivePath().front().get() == Call);
// Since we just transferred the path over to the call piece, reset the
// mapping of the active path to the current location context.
assert(C.isInLocCtxMap(&C.getActivePath()) &&
// mapping of the active path to the current stack frame.
assert(C.isInStackFrameMap(&C.getActivePath()) &&
"When we ascend to a previously unvisited call, the active path's "
"address shouldn't change, but rather should be compacted into "
"a single CallEvent!");
C.updateLocCtxMap(&C.getActivePath(), C.getCurrLocationContext());
C.updateStackFrameMap(&C.getActivePath(), C.getCurrStackFrame());
// Record the location context mapping for the path within the call.
assert(!C.isInLocCtxMap(&Call->path) &&
// Record the stack frame mapping for the path within the call.
assert(!C.isInStackFrameMap(&Call->path) &&
"When we ascend to a previously unvisited call, this must be the "
"first time we encounter the caller context!");
C.updateLocCtxMap(&Call->path, CE->getCalleeContext());
"first time we encounter the caller stack frame!");
C.updateStackFrameMap(&Call->path, CE->getCalleeStackFrame());
}
Call->setCallee(*CE, SM);
@ -1215,9 +1213,9 @@ void PathDiagnosticBuilder::generatePathDiagnosticsForNode(
return;
}
assert(C.getCurrLocationContext() == C.getLocationContextForActivePath() &&
assert(C.getCurrStackFrame() == C.getStackFrameForActivePath() &&
"The current position in the bug path is out of sync with the "
"location context associated with the active path!");
"stack frame associated with the active path!");
// Have we encountered an exit from a function call?
if (std::optional<CallExitEnd> CE = P.getAs<CallExitEnd>()) {
@ -1225,11 +1223,11 @@ void PathDiagnosticBuilder::generatePathDiagnosticsForNode(
// We are descending into a call (backwards). Construct
// a new call piece to contain the path pieces for that call.
auto Call = PathDiagnosticCallPiece::construct(*CE, SM);
// Record the mapping from call piece to LocationContext.
assert(!C.isInLocCtxMap(&Call->path) &&
// Record the mapping from call piece to StackFrame.
assert(!C.isInStackFrameMap(&Call->path) &&
"We just entered a call, this must've been the first time we "
"encounter its context!");
C.updateLocCtxMap(&Call->path, CE->getCalleeContext());
"encounter its stack frame!");
C.updateStackFrameMap(&Call->path, CE->getCalleeStackFrame());
if (C.shouldAddPathEdges()) {
// Add the edge to the return site.
@ -1255,7 +1253,7 @@ void PathDiagnosticBuilder::generatePathDiagnosticsForNode(
// as a terminator and as a terminator condition.
if (!isa<ObjCForCollectionStmt>(PS->getStmt())) {
PathDiagnosticLocation L =
PathDiagnosticLocation(PS->getStmt(), SM, C.getCurrLocationContext());
PathDiagnosticLocation(PS->getStmt(), SM, C.getCurrStackFrame());
addEdgeToPath(C.getActivePath(), PrevLoc, L);
}
@ -1271,7 +1269,7 @@ void PathDiagnosticBuilder::generatePathDiagnosticsForNode(
// Are we jumping to the head of a loop? Add a special diagnostic.
if (const Stmt *Loop = BE->getSrc()->getLoopTarget()) {
PathDiagnosticLocation L(Loop, SM, C.getCurrLocationContext());
PathDiagnosticLocation L(Loop, SM, C.getCurrStackFrame());
const Stmt *Body = nullptr;
if (const auto *FS = dyn_cast<ForStmt>(Loop))
@ -1330,7 +1328,7 @@ void PathDiagnosticBuilder::generatePathDiagnosticsForNode(
if (!str.empty()) {
PathDiagnosticLocation L(TermCond ? TermCond : Term, SM,
C.getCurrLocationContext());
C.getCurrStackFrame());
auto PE = std::make_shared<PathDiagnosticEventPiece>(L, str);
PE->setPrunable(true);
addEdgeToPath(C.getActivePath(), PrevLoc, PE->getLocation());
@ -1341,7 +1339,7 @@ void PathDiagnosticBuilder::generatePathDiagnosticsForNode(
}
}
} else if (isa<BreakStmt, ContinueStmt, GotoStmt>(Term)) {
PathDiagnosticLocation L(Term, SM, C.getCurrLocationContext());
PathDiagnosticLocation L(Term, SM, C.getCurrStackFrame());
addEdgeToPath(C.getActivePath(), PrevLoc, L);
}
}
@ -1447,8 +1445,8 @@ using OptimizedCallsSet = llvm::DenseSet<const PathDiagnosticCallPiece *>;
/// This avoids a "swoosh" effect, where an edge from a top-level statement A
/// points to a sub-expression B.1 that's not at the start of B. In these cases,
/// we'd like to see an edge from A to B, then another one from B to B.1.
static void addContextEdges(PathPieces &pieces, const LocationContext *LC) {
const ParentMap &PM = LC->getParentMap();
static void addContextEdges(PathPieces &pieces, const StackFrame *SF) {
const ParentMap &PM = SF->getParentMap();
PathPieces::iterator Prev = pieces.end();
for (PathPieces::iterator I = pieces.begin(), E = Prev; I != E;
Prev = I, ++I) {
@ -1465,7 +1463,7 @@ static void addContextEdges(PathPieces &pieces, const LocationContext *LC) {
while (NextSrcContext.isValid() && NextSrcContext.asStmt() != InnerStmt) {
SrcContexts.push_back(NextSrcContext);
InnerStmt = NextSrcContext.asStmt();
NextSrcContext = getEnclosingStmtLocation(InnerStmt, LC,
NextSrcContext = getEnclosingStmtLocation(InnerStmt, SF,
/*allowNested=*/true);
}
@ -1478,7 +1476,7 @@ static void addContextEdges(PathPieces &pieces, const LocationContext *LC) {
// We are looking at an edge. Is the destination within a larger
// expression?
PathDiagnosticLocation DstContext =
getEnclosingStmtLocation(Dst, LC, /*allowNested=*/true);
getEnclosingStmtLocation(Dst, SF, /*allowNested=*/true);
if (!DstContext.isValid() || DstContext.asStmt() == Dst)
break;
@ -1792,9 +1790,9 @@ static void removeIdenticalEvents(PathPieces &path) {
static bool optimizeEdges(const PathDiagnosticConstruct &C, PathPieces &path,
OptimizedCallsSet &OCS) {
bool hasChanges = false;
const LocationContext *LC = C.getLocationContextFor(&path);
assert(LC);
const ParentMap &PM = LC->getParentMap();
const StackFrame *SF = C.getStackFrameFor(&path);
assert(SF);
const ParentMap &PM = SF->getParentMap();
const SourceManager &SM = C.getSourceManager();
for (PathPieces::iterator I = path.begin(), E = path.end(); I != E; ) {
@ -1950,7 +1948,7 @@ static bool optimizeEdges(const PathDiagnosticConstruct &C, PathPieces &path,
if (!hasChanges) {
// Adjust edges into subexpressions to make them more uniform
// and aesthetically pleasing.
addContextEdges(path, LC);
addContextEdges(path, SF);
// Remove "cyclical" edges that include one or more context edges.
removeContextCycles(path, SM);
// Hoist edges originating from branch conditions to branches
@ -1978,7 +1976,7 @@ static void dropFunctionEntryEdge(const PathDiagnosticConstruct &C,
if (!FirstEdge)
return;
const Decl *D = C.getLocationContextFor(&Path)->getDecl();
const Decl *D = C.getStackFrameFor(&Path)->getDecl();
PathDiagnosticLocation EntryLoc =
PathDiagnosticLocation::createBegin(D, C.getSourceManager());
if (FirstEdge->getStartLocation() != EntryLoc)
@ -2009,7 +2007,7 @@ PathDiagnosticConstruct::PathDiagnosticConstruct(
SM(CurrentNode->getCodeDecl().getASTContext().getSourceManager()),
PD(generateEmptyDiagnosticForReport(R, getSourceManager(),
AnalysisEntryPoint)) {
LCM[&PD->getActivePath()] = ErrorNode->getLocationContext();
SFM[&PD->getActivePath()] = ErrorNode->getStackFrame();
}
PathDiagnosticBuilder::PathDiagnosticBuilder(
@ -2074,9 +2072,8 @@ PathDiagnosticBuilder::generate(const PathDiagnosticConsumer *PDC) const {
if (PDC->shouldAddPathEdges()) {
// Add an edge to the start of the function.
// We'll prune it out later, but it helps make diagnostics more uniform.
const StackFrame *CalleeLC =
Construct.getLocationContextForActivePath()->getStackFrame();
const Decl *D = CalleeLC->getDecl();
const StackFrame *CalleeSF = Construct.getStackFrameForActivePath();
const Decl *D = CalleeSF->getDecl();
addEdgeToPath(Construct.getActivePath(), PrevLoc,
PathDiagnosticLocation::createBegin(D, SM));
}
@ -2207,9 +2204,7 @@ const Decl *PathSensitiveBugReport::getDeclWithIssue() const {
const ExplodedNode *N = getErrorNode();
if (!N)
return nullptr;
const LocationContext *LC = N->getLocationContext();
return LC->getStackFrame()->getDecl();
return N->getStackFrame()->getDecl();
}
void BasicBugReport::Profile(llvm::FoldingSetNodeID& hash) const {
@ -2333,10 +2328,10 @@ void PathSensitiveBugReport::markInteresting(SVal V,
markInteresting(V.getAsSymbol(), TKind);
}
void PathSensitiveBugReport::markInteresting(const LocationContext *LC) {
if (!LC)
void PathSensitiveBugReport::markInteresting(const StackFrame *SF) {
if (!SF)
return;
InterestingLocationContexts.insert(LC);
InterestingStackFrames.insert(SF);
}
std::optional<bugreporter::TrackingKind>
@ -2403,10 +2398,10 @@ bool PathSensitiveBugReport::isInteresting(const MemRegion *R) const {
return getInterestingnessKind(R).has_value();
}
bool PathSensitiveBugReport::isInteresting(const LocationContext *LC) const {
if (!LC)
bool PathSensitiveBugReport::isInteresting(const StackFrame *SF) const {
if (!SF)
return false;
return InterestingLocationContexts.count(LC);
return InterestingStackFrames.count(SF);
}
const Stmt *PathSensitiveBugReport::getStmt() const {
@ -2417,7 +2412,7 @@ const Stmt *PathSensitiveBugReport::getStmt() const {
const Stmt *S = nullptr;
if (std::optional<BlockEntrance> BE = ProgP.getAs<BlockEntrance>()) {
CFGBlock &Exit = ProgP.getLocationContext()->getCFG()->getExit();
CFGBlock &Exit = ProgP.getStackFrame()->getCFG()->getExit();
if (BE->getBlock() == &Exit)
S = ErrorNode->getPreviousStmtForDiagnostics();
}
@ -2443,7 +2438,7 @@ static bool exitingDestructor(const ExplodedNode *N) {
while (N && !N->getLocation().getAs<StmtPoint>()) {
N = N->getFirstPred();
}
return N && isa<CXXDestructorDecl>(N->getLocationContext()->getDecl());
return N && isa<CXXDestructorDecl>(N->getStackFrame()->getDecl());
}
static const Stmt *
@ -2464,23 +2459,25 @@ PathSensitiveBugReport::getLocation() const {
assert(ErrorNode && "Cannot create a location with a null node.");
const Stmt *S = ErrorNode->getStmtForDiagnostics();
ProgramPoint P = ErrorNode->getLocation();
const LocationContext *LC = P.getLocationContext();
SourceManager &SM =
ErrorNode->getState()->getStateManager().getContext().getSourceManager();
const StackFrame *SF = P.getStackFrame();
SourceManager &SM = ErrorNode->getState()
->getStateManager()
.getContext()
.getSourceManager();
if (!S) {
// If this is an implicit call, return the implicit call point location.
if (!S) {
// If this is an implicit call, return the implicit call point location.
if (std::optional<PreImplicitCall> PIE = P.getAs<PreImplicitCall>())
return PathDiagnosticLocation(PIE->getLocation(), SM);
if (auto FE = P.getAs<FunctionExitPoint>()) {
if (const ReturnStmt *RS = FE->getStmt())
return PathDiagnosticLocation::createBegin(RS, SM, LC);
return PathDiagnosticLocation::createBegin(RS, SM, SF);
S = findReasonableStmtCloseToFunctionExit(ErrorNode);
}
if (!S)
S = ErrorNode->getNextStmtForDiagnostics();
}
}
if (S) {
// Attributed statements usually have corrupted begin locations,
@ -2498,17 +2495,16 @@ PathSensitiveBugReport::getLocation() const {
return PathDiagnosticLocation::createOperatorLoc(B, SM);
if (P.getAs<PostStmtPurgeDeadSymbols>())
return PathDiagnosticLocation::createEnd(S, SM, LC);
return PathDiagnosticLocation::createEnd(S, SM, SF);
if (S->getBeginLoc().isValid())
return PathDiagnosticLocation(S, SM, LC);
return PathDiagnosticLocation(S, SM, SF);
return PathDiagnosticLocation(
PathDiagnosticLocation::getValidSourceLocation(S, LC), SM);
PathDiagnosticLocation::getValidSourceLocation(S, SF), SM);
}
return PathDiagnosticLocation::createDeclEnd(ErrorNode->getLocationContext(),
SM);
return PathDiagnosticLocation::createDeclEnd(ErrorNode->getStackFrame(), SM);
}
//===----------------------------------------------------------------------===//
@ -3009,7 +3005,7 @@ void PathSensitiveBugReporter::emitReport(std::unique_ptr<BugReport> R) {
"Error node must either be a sink or have a tag");
const AnalysisDeclContext *DeclCtx =
E->getLocationContext()->getAnalysisDeclContext();
E->getStackFrame()->getAnalysisDeclContext();
// The source of autosynthesized body can be handcrafted AST or a model
// file. The locations from handcrafted ASTs have no valid source
// locations and have to be discarded. Locations from model files should
@ -3261,11 +3257,11 @@ findExecutedLines(const SourceManager &SM, const ExplodedNode *N) {
while (N) {
if (N->getFirstPred() == nullptr) {
// First node: show signature of the entrance point.
const Decl *D = N->getLocationContext()->getDecl();
const Decl *D = N->getStackFrame()->getDecl();
populateExecutedLinesWithFunctionSignature(D, SM, *ExecutedLines);
} else if (auto CE = N->getLocationAs<CallEnter>()) {
// Inlined function: show signature.
const Decl* D = CE->getCalleeContext()->getDecl();
const Decl *D = CE->getCalleeStackFrame()->getDecl();
populateExecutedLinesWithFunctionSignature(D, SM, *ExecutedLines);
} else if (const Stmt *S = N->getStmtForDiagnostics()) {
populateExecutedLinesWithStmt(S, SM, *ExecutedLines);

View file

@ -191,7 +191,7 @@ getLocationRegionIfReference(const Expr *E, const ExplodedNode *N,
return nullptr;
if (FD->getType()->isReferenceType()) {
SVal StructSVal = N->getState()->getLValue(VD, N->getLocationContext());
SVal StructSVal = N->getState()->getLValue(VD, N->getStackFrame());
return N->getState()->getLValue(FD, StructSVal).getAsRegion();
}
return nullptr;
@ -202,7 +202,7 @@ getLocationRegionIfReference(const Expr *E, const ExplodedNode *N,
return nullptr;
if (LookingForReference && !VD->getType()->isReferenceType())
return nullptr;
return N->getState()->getLValue(VD, N->getLocationContext()).getAsRegion();
return N->getState()->getLValue(VD, N->getStackFrame()).getAsRegion();
}
/// Comparing internal representations of symbolic values (via
@ -234,7 +234,7 @@ static bool hasVisibleUpdate(const ExplodedNode *LeftNode, SVal LeftVal,
static std::optional<SVal> getSValForVar(const Expr *CondVarExpr,
const ExplodedNode *N) {
ProgramStateRef State = N->getState();
const LocationContext *LCtx = N->getLocationContext();
const StackFrame *SF = N->getStackFrame();
assert(CondVarExpr);
CondVarExpr = CondVarExpr->IgnoreImpCasts();
@ -245,11 +245,11 @@ static std::optional<SVal> getSValForVar(const Expr *CondVarExpr,
// capture variable. We most likely need to duplicate that logic here.
if (const auto *DRE = dyn_cast<DeclRefExpr>(CondVarExpr))
if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
return State->getSVal(State->getLValue(VD, LCtx));
return State->getSVal(State->getLValue(VD, SF));
if (const auto *ME = dyn_cast<MemberExpr>(CondVarExpr))
if (const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
if (auto FieldL = State->getSVal(ME, LCtx).getAs<Loc>())
if (auto FieldL = State->getSVal(ME, SF).getAs<Loc>())
return State->getRawSVal(*FieldL, FD->getType());
return std::nullopt;
@ -378,8 +378,7 @@ BugReporterVisitor::getDefaultEndPath(const BugReporterContext &BRC,
//===----------------------------------------------------------------------===//
bool NoStateChangeFuncVisitor::isModifiedInFrame(const ExplodedNode *N) {
const LocationContext *Ctx = N->getLocationContext();
const StackFrame *SF = Ctx->getStackFrame();
const StackFrame *SF = N->getStackFrame();
if (!FramesModifyingCalculated.count(SF))
findModifyingFrames(N);
return FramesModifying.count(SF);
@ -391,7 +390,7 @@ void NoStateChangeFuncVisitor::markFrameAsModifying(const StackFrame *SF) {
if (!p.second)
break; // Frame and all its parents already inserted.
SF = SF->getParent()->getStackFrame();
SF = SF->getParent();
}
}
@ -420,8 +419,7 @@ void NoStateChangeFuncVisitor::findModifyingFrames(
assert(CallExitBeginN->getLocationAs<CallExitBegin>());
const StackFrame *const OriginalSF =
CallExitBeginN->getLocationContext()->getStackFrame();
const StackFrame *const OriginalSF = CallExitBeginN->getStackFrame();
const ExplodedNode *CurrCallExitBeginN = CallExitBeginN;
const StackFrame *CurrentSF = OriginalSF;
@ -451,7 +449,7 @@ void NoStateChangeFuncVisitor::findModifyingFrames(
// F.field = 0; // note: 0 assigned to 'F.field'
// // note: returning without writing to 'F.field'
// }
if (CE->getCalleeContext() == OriginalSF) {
if (CE->getCalleeStackFrame() == OriginalSF) {
markFrameAsModifying(CurrentSF);
break;
}
@ -465,8 +463,7 @@ void NoStateChangeFuncVisitor::findModifyingFrames(
PathDiagnosticPieceRef NoStateChangeFuncVisitor::VisitNode(
const ExplodedNode *N, BugReporterContext &BR, PathSensitiveBugReport &R) {
const LocationContext *Ctx = N->getLocationContext();
const StackFrame *SF = Ctx->getStackFrame();
const StackFrame *SF = N->getStackFrame();
ProgramStateRef State = N->getState();
auto CallExitLoc = N->getLocationAs<CallExitBegin>();
@ -867,7 +864,6 @@ private:
std::optional<SourceLocation> matchAssignment(const ExplodedNode *N) {
const Stmt *S = N->getStmtForDiagnostics();
ProgramStateRef State = N->getState();
auto *LCtx = N->getLocationContext();
if (!S)
return std::nullopt;
@ -875,7 +871,7 @@ private:
if (const auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl()))
if (const Expr *RHS = VD->getInit())
if (RegionOfInterest->isSubRegionOf(
State->getLValue(VD, LCtx).getAsRegion()))
State->getLValue(VD, N->getStackFrame()).getAsRegion()))
return RHS->getBeginLoc();
} else if (const auto *BO = dyn_cast<BinaryOperator>(S)) {
const MemRegion *R = N->getSVal(BO->getLHS()).getAsRegion();
@ -934,7 +930,7 @@ public:
BugReporterContext &BRC,
PathSensitiveBugReport &BR) {
// Only print a message at the interesting return statement.
if (N->getLocationContext() != CalleeSF)
if (N->getStackFrame() != CalleeSF)
return nullptr;
std::optional<StmtPoint> SP = N->getLocationAs<StmtPoint>();
@ -1065,7 +1061,7 @@ public:
if (!CE)
return nullptr;
if (CE->getCalleeContext() != CalleeSF)
if (CE->getCalleeStackFrame() != CalleeSF)
return nullptr;
Mode = Satisfied;
@ -1205,8 +1201,7 @@ static bool isInitializationOfVar(const ExplodedNode *N, const VarRegion *VR) {
}
assert(VR->getDecl()->hasLocalStorage());
const LocationContext *LCtx = N->getLocationContext();
return FrameSpace->getStackFrame() == LCtx->getStackFrame();
return FrameSpace->getStackFrame() == N->getStackFrame();
}
static bool isObjCPointer(const MemRegion *R) {
@ -1568,7 +1563,7 @@ PathDiagnosticPieceRef StoreSiteFinder::VisitNode(const ExplodedNode *Succ,
// Get the region for the object we copied/moved from.
const auto *OriginEx = CE->getArg(0);
const auto OriginVal =
State->getSVal(OriginEx, Succ->getLocationContext());
State->getSVal(OriginEx, Succ->getStackFrame());
// Pop the stored field regions and apply them to the origin
// object in the same order we had them on the copy.
@ -1616,14 +1611,16 @@ PathDiagnosticPieceRef StoreSiteFinder::VisitNode(const ExplodedNode *Succ,
ProgramStateManager &StateMgr = BRC.getStateManager();
CallEventManager &CallMgr = StateMgr.getCallEventManager();
CallEventRef<> Call = CallMgr.getCaller(CE->getCalleeContext(),
Succ->getState());
CallEventRef<> Call =
CallMgr.getCaller(CE->getCalleeStackFrame(), Succ->getState());
InitE = Call->getArgExpr(Param->getFunctionScopeIndex());
} else {
// Handle Objective-C 'self'.
assert(isa<ImplicitParamDecl>(VR->getDecl()));
InitE = cast<ObjCMessageExpr>(CE->getCalleeContext()->getCallSite())
->getInstanceReceiver()->IgnoreParenCasts();
InitE =
cast<ObjCMessageExpr>(CE->getCalleeStackFrame()->getCallSite())
->getInstanceReceiver()
->IgnoreParenCasts();
}
IsParam = true;
}
@ -1883,10 +1880,10 @@ SuppressInlineDefensiveChecksVisitor::VisitNode(const ExplodedNode *Succ,
IsSatisfied = true;
// Check if this is inlined defensive checks.
const LocationContext *CurLC = Succ->getLocationContext();
const LocationContext *ReportLC = BR.getErrorNode()->getLocationContext();
if (CurLC != ReportLC && !CurLC->isParentOf(ReportLC)) {
BR.markInvalid("Suppress IDC", CurLC);
const StackFrame *CurSF = Succ->getStackFrame();
const StackFrame *ReportSF = BR.getErrorNode()->getStackFrame();
if (CurSF != ReportSF && !CurSF->isParentOf(ReportSF)) {
BR.markInvalid("Suppress IDC", CurSF);
return nullptr;
}
@ -1908,7 +1905,7 @@ SuppressInlineDefensiveChecksVisitor::VisitNode(const ExplodedNode *Succ,
if (!CurStmt->getBeginLoc().isMacroID())
return nullptr;
const CFGStmtMap *Map = CurLC->getAnalysisDeclContext()->getCFGStmtMap();
const CFGStmtMap *Map = CurSF->getAnalysisDeclContext()->getCFGStmtMap();
CurTerminatorStmt = Map->getBlock(CurStmt)->getTerminatorStmt();
} else {
return nullptr;
@ -1924,7 +1921,7 @@ SuppressInlineDefensiveChecksVisitor::VisitNode(const ExplodedNode *Succ,
// Suppress reports unless we are in that same macro.
if (!BugLoc.isMacroID() ||
getMacroName(BugLoc, BRC) != getMacroName(TerminatorLoc, BRC)) {
BR.markInvalid("Suppress Macro IDC", CurLC);
BR.markInvalid("Suppress Macro IDC", CurSF);
}
return nullptr;
}
@ -1985,9 +1982,9 @@ constructDebugPieceForTrackedCondition(const Expr *Cond,
BRC.getSourceManager(), BRC.getASTContext().getLangOpts()));
return std::make_shared<PathDiagnosticEventPiece>(
PathDiagnosticLocation::createBegin(
Cond, BRC.getSourceManager(), N->getLocationContext()),
(Twine() + "Tracking condition '" + ConditionText + "'").str());
PathDiagnosticLocation::createBegin(Cond, BRC.getSourceManager(),
N->getStackFrame()),
(Twine() + "Tracking condition '" + ConditionText + "'").str());
}
static bool isAssertlikeBlock(const CFGBlock *B, ASTContext &Context) {
@ -2181,7 +2178,7 @@ PathDiagnosticPieceRef StoreHandler::constructNote(StoreInfo SI,
PathDiagnosticLocation L;
if (P.getAs<CallEnter>() && SI.SourceOfTheValue)
L = PathDiagnosticLocation(SI.SourceOfTheValue, BRC.getSourceManager(),
P.getLocationContext());
P.getStackFrame());
if (!L.isValid() || !L.asLocation().isValid())
L = PathDiagnosticLocation::create(P, BRC.getSourceManager());
@ -2386,14 +2383,14 @@ class InlinedFunctionCallHandler final : public ExpressionHandler {
// as a 'StmtPoint' so we have to bypass it.
const bool BypassCXXNewExprEval = isa<CXXNewExpr>(E);
// This is moving forward when we enter into another context.
// This is moving forward when we enter into another stack frame.
const StackFrame *CurrentSF = ExprNode->getStackFrame();
do {
// If that is satisfied we found our statement as an inlined call.
if (std::optional<CallExitEnd> CEE =
ExprNode->getLocationAs<CallExitEnd>())
if (CEE->getCalleeContext()->getCallSite() == E)
if (CEE->getCalleeStackFrame()->getCallSite() == E)
break;
// Try to move forward to the end of the call-chain.
@ -2408,7 +2405,7 @@ class InlinedFunctionCallHandler final : public ExpressionHandler {
// conservatively evaluated allocator.
if (!BypassCXXNewExprEval)
if (std::optional<StmtPoint> SP = ExprNode->getLocationAs<StmtPoint>())
// See if we do not enter into another context.
// See if we do not enter into another stack frame.
if (SP->getStmt() == E && CurrentSF == PredSF)
break;
@ -2426,8 +2423,8 @@ class InlinedFunctionCallHandler final : public ExpressionHandler {
if (!CEE)
return {};
const StackFrame *CalleeContext = CEE->getCalleeContext();
if (CalleeContext->getCallSite() != E)
const StackFrame *CalleeSF = CEE->getCalleeStackFrame();
if (CalleeSF->getCallSite() != E)
return {};
// Check the return value.
@ -2448,7 +2445,7 @@ class InlinedFunctionCallHandler final : public ExpressionHandler {
EnableNullFPSuppression = State->isNull(*RetLoc).isConstrainedTrue();
PathSensitiveBugReport &Report = getParentTracker().getReport();
Report.addVisitor<ReturnVisitor>(&getParentTracker(), CalleeContext,
Report.addVisitor<ReturnVisitor>(&getParentTracker(), CalleeSF,
EnableNullFPSuppression, Options,
Opts.Kind);
return {true};
@ -2469,7 +2466,7 @@ public:
// If the expression is not an "lvalue expression", we can still
// track the constraints on its contents.
SVal V = LVState->getSValAsScalarOrLoc(Inner, LVNode->getLocationContext());
SVal V = LVState->getSValAsScalarOrLoc(Inner, LVNode->getStackFrame());
// Is it a symbolic value?
if (auto L = V.getAs<loc::MemRegionVal>()) {
@ -2556,14 +2553,14 @@ public:
}
ProgramStateRef RVState = RVNode->getState();
SVal V = RVState->getSValAsScalarOrLoc(E, RVNode->getLocationContext());
SVal V = RVState->getSValAsScalarOrLoc(E, RVNode->getStackFrame());
const auto *BO = dyn_cast<BinaryOperator>(E);
if (!BO || !BO->isMultiplicativeOp() || !V.isZeroConstant())
return {};
SVal RHSV = RVState->getSVal(BO->getRHS(), RVNode->getLocationContext());
SVal LHSV = RVState->getSVal(BO->getLHS(), RVNode->getLocationContext());
SVal RHSV = RVState->getSVal(BO->getRHS(), RVNode->getStackFrame());
SVal LHSV = RVState->getSVal(BO->getLHS(), RVNode->getStackFrame());
// Track both LHS and RHS of a multiplication.
if (BO->getOpcode() == BO_Mul) {
@ -2708,7 +2705,7 @@ NilReceiverBRVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC,
/*EnableNullFPSuppression*/ false});
// Issue a message saying that the method was skipped.
PathDiagnosticLocation L(Receiver, BRC.getSourceManager(),
N->getLocationContext());
N->getStackFrame());
return std::make_shared<PathDiagnosticEventPiece>(L, OS.str());
}
@ -2840,7 +2837,7 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond, BugReporterContext &BRC,
const ExplodedNode *N, bool TookTrue) {
ProgramStateRef CurrentState = N->getState();
ProgramStateRef PrevState = N->getFirstPred()->getState();
const LocationContext *LCtx = N->getLocationContext();
const StackFrame *SF = N->getStackFrame();
// If the constraint information is changed between the current and the
// previous program state we assuming the newly seen constraint information.
@ -2858,7 +2855,7 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond, BugReporterContext &BRC,
// this is not a "real" assumption.
bool IsAssuming =
!BRC.getStateManager().haveEqualConstraints(CurrentState, PrevState) ||
CurrentState->getSVal(Cond, LCtx).isUnknownOrUndef();
CurrentState->getSVal(Cond, SF).isUnknownOrUndef();
// These will be modified in code below, but we need to preserve the original
// values in case we want to throw the generic message.
@ -2905,7 +2902,7 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond, BugReporterContext &BRC,
if (!IsAssuming)
return nullptr;
PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), SF);
if (!Loc.isValid() || !Loc.asLocation().isValid())
return nullptr;
@ -2944,10 +2941,10 @@ bool ConditionBRVisitor::patternMatch(const Expr *Ex, const Expr *ParentEx,
const bool quotes = isa<VarDecl>(DR->getDecl());
if (quotes) {
Out << '\'';
const LocationContext *LCtx = N->getLocationContext();
const ProgramState *state = N->getState().get();
if (const MemRegion *R = state->getLValue(cast<VarDecl>(DR->getDecl()),
LCtx).getAsRegion()) {
if (const MemRegion *R =
state->getLValue(cast<VarDecl>(DR->getDecl()), N->getStackFrame())
.getAsRegion()) {
if (report.isInteresting(R))
prunable = false;
else {
@ -3082,7 +3079,7 @@ PathDiagnosticPieceRef ConditionBRVisitor::VisitTrueTest(
}
Out << (shouldInvert ? LhsString : RhsString);
const LocationContext *LCtx = N->getLocationContext();
const StackFrame *SF = N->getStackFrame();
const SourceManager &SM = BRC.getSourceManager();
if (isVarAnInterestingCondition(BExpr->getLHS(), N, &R) ||
@ -3100,18 +3097,18 @@ PathDiagnosticPieceRef ConditionBRVisitor::VisitTrueTest(
if (LhsME && LhsME->getMemberLoc().isValid())
Loc = PathDiagnosticLocation(LhsME->getMemberLoc(), SM);
else
Loc = PathDiagnosticLocation(BExpr->getLHS(), SM, LCtx);
Loc = PathDiagnosticLocation(BExpr->getLHS(), SM, SF);
} else {
if (RhsME && RhsME->getMemberLoc().isValid())
Loc = PathDiagnosticLocation(RhsME->getMemberLoc(), SM);
else
Loc = PathDiagnosticLocation(BExpr->getRHS(), SM, LCtx);
Loc = PathDiagnosticLocation(BExpr->getRHS(), SM, SF);
}
return std::make_shared<PathDiagnosticPopUpPiece>(Loc, Message);
}
PathDiagnosticLocation Loc(Cond, SM, LCtx);
PathDiagnosticLocation Loc(Cond, SM, SF);
auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Message);
if (shouldPrune)
event->setPrunable(*shouldPrune);
@ -3131,8 +3128,8 @@ PathDiagnosticPieceRef ConditionBRVisitor::VisitConditionVariable(
if (!printValue(CondVarExpr, Out, N, TookTrue, /*IsAssuming=*/true))
return nullptr;
const LocationContext *LCtx = N->getLocationContext();
PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx);
PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(),
N->getStackFrame());
if (isVarAnInterestingCondition(CondVarExpr, N, &report))
Out << WillBeUsedForACondition;
@ -3161,18 +3158,18 @@ PathDiagnosticPieceRef ConditionBRVisitor::VisitTrueTest(
if (!printValue(DRE, Out, N, TookTrue, IsAssuming))
return nullptr;
const LocationContext *LCtx = N->getLocationContext();
const StackFrame *SF = N->getStackFrame();
if (isVarAnInterestingCondition(DRE, N, &report))
Out << WillBeUsedForACondition;
// If we know the value create a pop-up note to the 'DRE'.
if (!IsAssuming) {
PathDiagnosticLocation Loc(DRE, BRC.getSourceManager(), LCtx);
PathDiagnosticLocation Loc(DRE, BRC.getSourceManager(), SF);
return std::make_shared<PathDiagnosticPopUpPiece>(Loc, Out.str());
}
PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), LCtx);
PathDiagnosticLocation Loc(Cond, BRC.getSourceManager(), SF);
auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str());
if (isInterestingExpr(DRE, N, &report))
@ -3194,14 +3191,14 @@ PathDiagnosticPieceRef ConditionBRVisitor::VisitTrueTest(
if (!printValue(ME, Out, N, TookTrue, IsAssuming))
return nullptr;
const LocationContext *LCtx = N->getLocationContext();
PathDiagnosticLocation Loc;
// If we know the value create a pop-up note to the member of the MemberExpr.
if (!IsAssuming && ME->getMemberLoc().isValid())
Loc = PathDiagnosticLocation(ME->getMemberLoc(), BRC.getSourceManager());
else
Loc = PathDiagnosticLocation(Cond, BRC.getSourceManager(), LCtx);
Loc = PathDiagnosticLocation(Cond, BRC.getSourceManager(),
N->getStackFrame());
if (!Loc.isValid() || !Loc.asLocation().isValid())
return nullptr;
@ -3272,7 +3269,7 @@ void LikelyFalsePositiveSuppressionBRVisitor::finalizeVisitor(
// Here we suppress false positives coming from system headers. This list is
// based on known issues.
const AnalyzerOptions &Options = BRC.getAnalyzerOptions();
const Decl *D = N->getLocationContext()->getDecl();
const Decl *D = N->getStackFrame()->getDecl();
if (AnalysisDeclContext::isInStdNamespace(D)) {
// Skip reports within the 'std' namespace. Although these can sometimes be
@ -3307,9 +3304,8 @@ void LikelyFalsePositiveSuppressionBRVisitor::finalizeVisitor(
}
}
for (const LocationContext *LCtx = N->getLocationContext(); LCtx;
LCtx = LCtx->getParent()) {
const auto *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl());
for (const auto *SF = N->getStackFrame(); SF; SF = SF->getParent()) {
const auto *MD = dyn_cast<CXXMethodDecl>(SF->getDecl());
if (!MD)
continue;
@ -3366,7 +3362,7 @@ UndefOrNullArgVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC,
// Check if one of the arguments is the region the visitor is tracking.
CallEventManager &CEMgr = BRC.getStateManager().getCallEventManager();
CallEventRef<> Call = CEMgr.getCaller(CEnter->getCalleeContext(), State);
CallEventRef<> Call = CEMgr.getCaller(CEnter->getCalleeStackFrame(), State);
unsigned Idx = 0;
ArrayRef<ParmVarDecl *> parms = Call->parameters();
@ -3392,11 +3388,11 @@ UndefOrNullArgVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC,
if (T->getPointeeType().isConstQualified())
continue;
// Mark the call site (LocationContext) as interesting if the value of the
// Mark the call site (StackFrame) as interesting if the value of the
// argument is undefined or '0'/'NULL'.
SVal BoundVal = State->getSVal(R);
if (BoundVal.isUndef() || BoundVal.isZeroConstant()) {
BR.markInteresting(CEnter->getCalleeContext());
BR.markInteresting(CEnter->getCalleeStackFrame());
return nullptr;
}
}

View file

@ -154,7 +154,7 @@ AnalysisDeclContext *CallEvent::getCalleeAnalysisDeclContext() const {
return nullptr;
AnalysisDeclContext *ADC =
LCtx->getAnalysisDeclContext()->getManager()->getContext(D);
SF->getAnalysisDeclContext()->getManager()->getContext(D);
return ADC;
}
@ -173,7 +173,7 @@ const StackFrame *CallEvent::getCalleeStackFrame(unsigned BlockCount) const {
// instead of doing this reverse lookup, we would be able to build the stack
// frame for non-expression-based calls, and also we wouldn't need the reverse
// lookup.
const CFGStmtMap *Map = LCtx->getAnalysisDeclContext()->getCFGStmtMap();
const CFGStmtMap *Map = SF->getAnalysisDeclContext()->getCFGStmtMap();
const CFGBlock *B = Map->getBlock(E);
assert(B);
@ -185,7 +185,7 @@ const StackFrame *CallEvent::getCalleeStackFrame(unsigned BlockCount) const {
break;
assert(Idx < Sz);
return ADC->getStackFrame(LCtx, nullptr, E, B, BlockCount, Idx);
return ADC->getStackFrame(SF, nullptr, E, B, BlockCount, Idx);
}
const ParamVarRegion
@ -296,7 +296,7 @@ ProgramStateRef CallEvent::invalidateRegions(unsigned BlockCount,
// NOTE: Even if RegionsToInvalidate is empty, we may still invalidate
// global variables.
return State->invalidateRegions(ValuesToInvalidate, getCFGElementRef(),
BlockCount, getLocationContext(),
BlockCount, getStackFrame(),
/*CausedByPointerEscape*/ true,
/*Symbols=*/nullptr, this, &ETraits);
}
@ -306,8 +306,8 @@ ProgramPoint CallEvent::getProgramPoint(bool IsPreVisit,
if (const Expr *E = getOriginExpr()) {
if (IsPreVisit)
return PreStmt(E, getLocationContext(), Tag);
return PostStmt(E, getLocationContext(), Tag);
return PreStmt(E, getStackFrame(), Tag);
return PostStmt(E, getStackFrame(), Tag);
}
const Decl *D = getDecl();
@ -317,8 +317,8 @@ ProgramPoint CallEvent::getProgramPoint(bool IsPreVisit,
SourceLocation Loc = getSourceRange().getBegin();
if (IsPreVisit)
return PreImplicitCall(D, Loc, getLocationContext(), ElemRef, Tag);
return PostImplicitCall(D, Loc, getLocationContext(), ElemRef, Tag);
return PreImplicitCall(D, Loc, getStackFrame(), ElemRef, Tag);
return PostImplicitCall(D, Loc, getStackFrame(), ElemRef, Tag);
}
SVal CallEvent::getArgSVal(unsigned Index) const {
@ -535,12 +535,8 @@ const ConstructionContext *CallEvent::getConstructionContext() const {
}
const CallEventRef<> CallEvent::getCaller() const {
const auto *CallLocationContext = this->getLocationContext();
if (!CallLocationContext || CallLocationContext->inTopFrame())
return nullptr;
const auto *CallSF = CallLocationContext->getStackFrame();
if (!CallSF)
const auto *CallSF = this->getStackFrame();
if (!CallSF || CallSF->inTopFrame())
return nullptr;
CallEventManager &CEMgr = State->getStateManager().getCallEventManager();
@ -561,10 +557,10 @@ std::optional<SVal> CallEvent::getReturnValueUnderConstruction() const {
EvalCallOptions CallOpts;
ExprEngine &Engine = getState()->getStateManager().getOwningEngine();
unsigned NumVisitedCall = Engine.getNumVisited(
getLocationContext(), getCFGElementRef().getParent());
unsigned NumVisitedCall =
Engine.getNumVisited(getStackFrame(), getCFGElementRef().getParent());
SVal RetVal = Engine.computeObjectUnderConstruction(
getOriginExpr(), getState(), NumVisitedCall, getLocationContext(), CC,
getOriginExpr(), getState(), NumVisitedCall, getStackFrame(), CC,
CallOpts);
return RetVal;
}
@ -584,8 +580,7 @@ RuntimeDefinition AnyFunctionCall::getRuntimeDefinition() const {
// Note that the AnalysisDeclContext will have the FunctionDecl with
// the definition (if one exists).
AnalysisDeclContext *AD =
getLocationContext()->getAnalysisDeclContext()->
getManager()->getContext(FD);
getStackFrame()->getAnalysisDeclContext()->getManager()->getContext(FD);
bool IsAutosynthesized;
Stmt* Body = AD->getBody(IsAutosynthesized);
LLVM_DEBUG({
@ -985,9 +980,9 @@ void AnyCXXConstructorCall::getInitialStackFrameContents(
}
const StackFrame *CXXInheritedConstructorCall::getInheritingStackFrame() const {
const StackFrame *SF = getLocationContext()->getStackFrame();
const StackFrame *SF = getStackFrame();
while (isa<CXXInheritedCtorInitExpr>(SF->getCallSite()))
SF = SF->getParent()->getStackFrame();
SF = SF->getParent();
return SF;
}
@ -1049,7 +1044,7 @@ SVal ObjCMethodCall::getReceiverSVal() const {
// An instance message with no expression means we are sending to super.
// In this case the object reference is the same as 'self'.
assert(getOriginExpr()->getReceiverKind() == ObjCMessageExpr::SuperInstance);
SVal SelfVal = getState()->getSelfSVal(getLocationContext());
SVal SelfVal = getState()->getSelfSVal(getStackFrame());
assert(SelfVal.isValid() && "Calling super but not in ObjC method");
return SelfVal;
}
@ -1063,7 +1058,7 @@ bool ObjCMethodCall::isReceiverSelfOrSuper() const {
return false;
SVal RecVal = getSVal(getOriginExpr()->getInstanceReceiver());
SVal SelfVal = getState()->getSelfSVal(getLocationContext());
SVal SelfVal = getState()->getSelfSVal(getStackFrame());
return (RecVal == SelfVal);
}
@ -1102,7 +1097,7 @@ getSyntacticFromForPseudoObjectExpr(const PseudoObjectExpr *POE) {
ObjCMessageKind ObjCMethodCall::getMessageKind() const {
if (!Data) {
// Find the parent, ignoring implicit casts.
const ParentMap &PM = getLocationContext()->getParentMap();
const ParentMap &PM = getStackFrame()->getParentMap();
const Stmt *S = PM.getParentIgnoreParenCasts(getOriginExpr());
// Check if parent is a PseudoObjectExpr.
@ -1345,7 +1340,7 @@ RuntimeDefinition ObjCMethodCall::getRuntimeDefinition() const {
// instance (not class).
if (ReceiverT->isObjCClass()) {
SVal SelfVal = getState()->getSelfSVal(getLocationContext());
SVal SelfVal = getState()->getSelfSVal(getStackFrame());
// For [self classMethod], return compiler visible declaration.
if (Receiver == SelfVal.getAsRegion()) {
return RuntimeDefinition(findDefiningRedecl(E->getMethodDecl()));
@ -1439,41 +1434,41 @@ CallEventManager::CallEventManager(llvm::BumpPtrAllocator &alloc)
CallEventRef<>
CallEventManager::getSimpleCall(const CallExpr *CE, ProgramStateRef State,
const LocationContext *LCtx,
const StackFrame *SF,
CFGBlock::ConstCFGElementRef ElemRef) {
if (const auto *MCE = dyn_cast<CXXMemberCallExpr>(CE))
return create<CXXMemberCall>(MCE, State, LCtx, ElemRef);
return create<CXXMemberCall>(MCE, State, SF, ElemRef);
if (const auto *OpCE = dyn_cast<CXXOperatorCallExpr>(CE)) {
const FunctionDecl *DirectCallee = OpCE->getDirectCallee();
if (const auto *MD = dyn_cast<CXXMethodDecl>(DirectCallee)) {
if (MD->isImplicitObjectMemberFunction())
return create<CXXMemberOperatorCall>(OpCE, State, LCtx, ElemRef);
return create<CXXMemberOperatorCall>(OpCE, State, SF, ElemRef);
if (MD->isStatic())
return create<CXXStaticOperatorCall>(OpCE, State, LCtx, ElemRef);
return create<CXXStaticOperatorCall>(OpCE, State, SF, ElemRef);
}
} else if (CE->getCallee()->getType()->isBlockPointerType()) {
return create<BlockCall>(CE, State, LCtx, ElemRef);
return create<BlockCall>(CE, State, SF, ElemRef);
}
// Otherwise, it's a normal function call, static member function call, or
// something we can't reason about.
return create<SimpleFunctionCall>(CE, State, LCtx, ElemRef);
return create<SimpleFunctionCall>(CE, State, SF, ElemRef);
}
CallEventRef<> CallEventManager::getCaller(const StackFrame *CalleeSF,
ProgramStateRef State) {
const LocationContext *ParentCtx = CalleeSF->getParent();
const LocationContext *CallerCtx = ParentCtx->getStackFrame();
const StackFrame *ParentSF = CalleeSF->getParent();
const StackFrame *CallerSF = ParentSF;
CFGBlock::ConstCFGElementRef ElemRef = {CalleeSF->getCallSiteBlock(),
CalleeSF->getIndex()};
assert(CallerCtx && "This should not be used for top-level stack frames");
assert(CallerSF && "This should not be used for top-level stack frames");
const Expr *CallSite = CalleeSF->getCallSite();
if (CallSite) {
if (CallEventRef<> Out = getCall(CallSite, State, CallerCtx, ElemRef))
if (CallEventRef<> Out = getCall(CallSite, State, CallerSF, ElemRef))
return Out;
SValBuilder &SVB = State->getStateManager().getSValBuilder();
@ -1482,11 +1477,11 @@ CallEventRef<> CallEventManager::getCaller(const StackFrame *CalleeSF,
SVal ThisVal = State->getSVal(ThisPtr);
if (const auto *CE = dyn_cast<CXXConstructExpr>(CallSite))
return getCXXConstructorCall(CE, ThisVal.getAsRegion(), State, CallerCtx,
return getCXXConstructorCall(CE, ThisVal.getAsRegion(), State, CallerSF,
ElemRef);
if (const auto *CIE = dyn_cast<CXXInheritedCtorInitExpr>(CallSite))
return getCXXInheritedConstructorCall(CIE, ThisVal.getAsRegion(), State,
CallerCtx, ElemRef);
CallerSF, ElemRef);
// All other cases are handled by getCall.
llvm_unreachable("This is not an inlineable statement");
}
@ -1514,20 +1509,20 @@ CallEventRef<> CallEventManager::getCaller(const StackFrame *CalleeSF,
return getCXXDestructorCall(Dtor, Trigger, ThisVal.getAsRegion(),
E.getAs<CFGBaseDtor>().has_value(), State,
CallerCtx, ElemRef);
CallerSF, ElemRef);
}
CallEventRef<> CallEventManager::getCall(const Stmt *S, ProgramStateRef State,
const LocationContext *LC,
const StackFrame *SF,
CFGBlock::ConstCFGElementRef ElemRef) {
if (const auto *CE = dyn_cast<CallExpr>(S)) {
return getSimpleCall(CE, State, LC, ElemRef);
return getSimpleCall(CE, State, SF, ElemRef);
} else if (const auto *NE = dyn_cast<CXXNewExpr>(S)) {
return getCXXAllocatorCall(NE, State, LC, ElemRef);
return getCXXAllocatorCall(NE, State, SF, ElemRef);
} else if (const auto *DE = dyn_cast<CXXDeleteExpr>(S)) {
return getCXXDeallocatorCall(DE, State, LC, ElemRef);
return getCXXDeallocatorCall(DE, State, SF, ElemRef);
} else if (const auto *ME = dyn_cast<ObjCMessageExpr>(S)) {
return getObjCMethodCall(ME, State, LC, ElemRef);
return getObjCMethodCall(ME, State, SF, ElemRef);
} else {
return nullptr;
}

View file

@ -164,8 +164,8 @@ std::string checkerScopeName(StringRef Name, const CheckerBackend *Checker) {
// FIXME: Remove respondsToCallback from CheckerContext;
ProgramPoint::Kind K = IsPreVisit ? ProgramPoint::PreStmtKind :
ProgramPoint::PostStmtKind;
const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
Pred->getLocationContext(), checkFn.Checker);
const ProgramPoint &L = ProgramPoint::getProgramPoint(
S, K, Pred->getStackFrame(), checkFn.Checker);
CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
checkFn(S, C);
}
@ -338,10 +338,8 @@ namespace {
llvm::TimeTraceScope TimeScope(checkerScopeName("Loc", checkFn.Checker));
ProgramPoint::Kind K = IsLoad ? ProgramPoint::PreLoadKind :
ProgramPoint::PreStoreKind;
const ProgramPoint &L =
ProgramPoint::getProgramPoint(NodeEx, K,
Pred->getLocationContext(),
checkFn.Checker);
const ProgramPoint &L = ProgramPoint::getProgramPoint(
NodeEx, K, Pred->getStackFrame(), checkFn.Checker);
CheckerContext C(Bldr, Eng, Pred, L);
checkFn(Loc, IsLoad, BoundEx, C);
}
@ -515,7 +513,7 @@ void CheckerManager::runCheckersForEndFunction(ExplodedNodeSet &Dst,
NodeBuilder Bldr(Pred, Dst, Eng.getBuilderContext());
for (const auto &checkFn : EndFunctionCheckers) {
const ProgramPoint &L =
FunctionExitPoint(RS, Pred->getLocationContext(), checkFn.Checker);
FunctionExitPoint(RS, Pred->getStackFrame(), checkFn.Checker);
CheckerContext C(Bldr, Eng, Pred, L);
llvm::TimeTraceScope TimeScope(checkerScopeName("End", checkFn.Checker));
checkFn(RS, C);
@ -542,8 +540,8 @@ namespace {
NodeBuilder &Bldr, ExplodedNode *Pred) {
llvm::TimeTraceScope TimeScope(
checkerScopeName("BranchCond", checkFn.Checker));
ProgramPoint L = PostCondition(Condition, Pred->getLocationContext(),
checkFn.Checker);
ProgramPoint L =
PostCondition(Condition, Pred->getStackFrame(), checkFn.Checker);
CheckerContext C(Bldr, Eng, Pred, L);
checkFn(Condition, C);
}
@ -587,7 +585,7 @@ namespace {
llvm::TimeTraceScope TimeScope(
checkerScopeName("Allocator", checkFn.Checker));
ProgramPoint L = PostAllocatorCall(
Call.getOriginExpr(), Pred->getLocationContext(), checkFn.Checker);
Call.getOriginExpr(), Pred->getStackFrame(), checkFn.Checker);
CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
checkFn(cast<CXXAllocatorCall>(*Call.cloneWithState(Pred->getState())),
C);
@ -638,8 +636,8 @@ namespace {
NodeBuilder &Bldr, ExplodedNode *Pred) {
llvm::TimeTraceScope TimeScope(
checkerScopeName("DeadSymbols", checkFn.Checker));
const ProgramPoint &L = ProgramPoint::getProgramPoint(S, ProgarmPointKind,
Pred->getLocationContext(), checkFn.Checker);
const ProgramPoint &L = ProgramPoint::getProgramPoint(
S, ProgarmPointKind, Pred->getStackFrame(), checkFn.Checker);
CheckerContext C(Bldr, Eng, Pred, L);
// Note, do not pass the statement to the checkers without letting them
@ -664,20 +662,18 @@ void CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
}
/// Run checkers for region changes.
ProgramStateRef
CheckerManager::runCheckersForRegionChanges(ProgramStateRef state,
const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const LocationContext *LCtx,
const CallEvent *Call) {
ProgramStateRef CheckerManager::runCheckersForRegionChanges(
ProgramStateRef state, const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions, const StackFrame *SF,
const CallEvent *Call) {
for (const auto &RegionChangesChecker : RegionChangesCheckers) {
// If any checker declares the state infeasible (or if it starts that way),
// bail out.
if (!state)
return nullptr;
state = RegionChangesChecker(state, invalidated, ExplicitRegions, Regions,
LCtx, Call);
SF, Call);
}
return state;
}
@ -739,7 +735,7 @@ void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst,
// to any Expr.
ProgramPoint L = ProgramPoint::getProgramPoint(
UpdatedCall->getOriginExpr(), ProgramPoint::PostStmtKind,
Pred->getLocationContext(), EvalCallChecker.Checker);
Pred->getStackFrame(), EvalCallChecker.Checker);
bool evaluated = false;
{ // CheckerContext generates transitions (populates checkDest) on
// destruction, so introduce the scope to make sure it gets properly

View file

@ -12,7 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
#include "PrettyStackTraceLocationContext.h"
#include "PrettyStackTraceStackFrame.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/Stmt.h"
@ -84,42 +84,41 @@ void CoreEngine::setBlockCounter(BlockCounter C) {
}
/// ExecuteWorkList - Run the worklist algorithm for a maximum number of steps.
bool CoreEngine::ExecuteWorkList(const LocationContext *L, unsigned MaxSteps,
bool CoreEngine::ExecuteWorkList(const StackFrame *SF, unsigned MaxSteps,
ProgramStateRef InitState) {
if (G.empty()) {
assert(!G.getRoot() && "empty graph must not have a root node");
// Initialize the analysis by constructing the root if there are no nodes.
const CFGBlock *Entry = &(L->getCFG()->getEntry());
const CFGBlock *Entry = &(SF->getCFG()->getEntry());
assert(Entry->empty() && "Entry block must be empty.");
assert(Entry->succ_size() == 1 && "Entry block must have 1 successor.");
// Mark the entry block as visited.
FunctionSummaries->markVisitedBasicBlock(Entry->getBlockID(),
L->getDecl(),
L->getCFG()->getNumBlockIDs());
FunctionSummaries->markVisitedBasicBlock(Entry->getBlockID(), SF->getDecl(),
SF->getCFG()->getNumBlockIDs());
// Get the solitary successor.
const CFGBlock *Succ = *(Entry->succ_begin());
// Construct an edge representing the
// starting location in the function.
BlockEdge StartLoc(Entry, Succ, L);
BlockEdge StartLoc(Entry, Succ, SF);
// Set the current block counter to being empty.
setBlockCounter(BCounterFactory.GetEmptyCounter());
if (!InitState)
InitState = ExprEng.getInitialState(L);
InitState = ExprEng.getInitialState(SF);
bool IsNew;
ExplodedNode *Node = G.getNode(StartLoc, InitState, false, &IsNew);
assert(IsNew);
G.designateAsRoot(Node);
ExprEng.setCurrLocationContextAndBlock(Node->getLocationContext(), Succ);
ExprEng.setCurrStackFrameAndBlock(Node->getStackFrame(), Succ);
ExplodedNodeSet DstBegin;
ExprEng.processBeginOfFunction(Node, DstBegin, StartLoc);
@ -201,7 +200,7 @@ static llvm::TimeTraceMetadata timeTraceMetadata(const ExplodedNode *Pred,
auto SLoc = Loc.getSourceLocation();
if (!SLoc)
return llvm::TimeTraceMetadata{std::move(Detail), ""};
const auto &SM = Pred->getLocationContext()
const auto &SM = Pred->getStackFrame()
->getAnalysisDeclContext()
->getASTContext()
.getSourceManager();
@ -216,14 +215,14 @@ void CoreEngine::dispatchWorkItem(ExplodedNode *Pred, ProgramPoint Loc,
llvm::TimeTraceScope tcs{timeTraceScopeName(Loc), [Loc, Pred]() {
return timeTraceMetadata(Pred, Loc);
}};
PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
PrettyStackTraceStackFrame CrashInfo(Pred->getStackFrame());
// This work item is not necessarily related to the previous one, so
// the old current LocationContext and Block is no longer relevant.
// The new current LocationContext and Block should be set soon, but this
// the old current StackFrame and Block is no longer relevant.
// The new current StackFrame and Block should be set soon, but this
// guarantees that buggy access before that will trigger loud crashes instead
// of silently using stale data.
ExprEng.resetCurrLocationContextAndBlock();
ExprEng.resetCurrStackFrameAndBlock();
// Dispatch on the location type.
switch (Loc.getKind()) {
@ -268,13 +267,12 @@ void CoreEngine::dispatchWorkItem(ExplodedNode *Pred, ProgramPoint Loc,
void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) {
const CFGBlock *Blk = L.getDst();
ExprEng.setCurrLocationContextAndBlock(Pred->getLocationContext(), Blk);
ExprEng.setCurrStackFrameAndBlock(Pred->getStackFrame(), Blk);
// Mark this block as visited.
const LocationContext *LC = Pred->getLocationContext();
FunctionSummaries->markVisitedBasicBlock(Blk->getBlockID(),
LC->getDecl(),
LC->getCFG()->getNumBlockIDs());
const StackFrame *SF = Pred->getStackFrame();
FunctionSummaries->markVisitedBasicBlock(Blk->getBlockID(), SF->getDecl(),
SF->getCFG()->getNumBlockIDs());
// Display a prunable path note to the user if it's a virtual bases branch
// and we're taking the path that skips virtual base constructors.
@ -295,7 +293,7 @@ void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) {
}
// Check if we are entering the EXIT block.
const CFGBlock &ExitBlk = L.getLocationContext()->getCFG()->getExit();
const CFGBlock &ExitBlk = L.getStackFrame()->getCFG()->getExit();
if (Blk == &ExitBlk) {
assert(ExitBlk.empty() && "EXIT block cannot contain Stmts.");
@ -312,7 +310,7 @@ void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) {
}
ExplodedNodeSet CheckerNodes;
BlockEntrance BE(L.getSrc(), L.getDst(), Pred->getLocationContext());
BlockEntrance BE(L.getSrc(), L.getDst(), Pred->getStackFrame());
ExprEng.runCheckersForBlockEntrance(BE, Pred, CheckerNodes);
// Process the final state transition.
@ -325,7 +323,7 @@ void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) {
}
// Call into the ExprEngine to process entering the CFGBlock.
BlockEntrance BE(L.getSrc(), L.getDst(), Pred->getLocationContext());
BlockEntrance BE(L.getSrc(), L.getDst(), Pred->getStackFrame());
ExplodedNodeSet DstNodes;
NodeBuilder Builder(Pred, DstNodes, ExprEng.getBuilderContext());
ExprEng.processCFGBlockEntrance(L, BE, Builder, Pred);
@ -347,17 +345,15 @@ void CoreEngine::HandleBlockEdge(const BlockEdge &L, ExplodedNode *Pred) {
void CoreEngine::HandleBlockEntrance(const BlockEntrance &L,
ExplodedNode *Pred) {
// Increment the block counter.
const LocationContext *LC = Pred->getLocationContext();
const StackFrame *SF = Pred->getStackFrame();
unsigned BlockId = L.getBlock()->getBlockID();
BlockCounter Counter = WList->getBlockCounter();
Counter = BCounterFactory.IncrementCount(Counter, LC->getStackFrame(),
BlockId);
Counter = BCounterFactory.IncrementCount(Counter, SF, BlockId);
setBlockCounter(Counter);
// Process the entrance of the block.
if (std::optional<CFGElement> E = L.getFirstElement()) {
ExprEng.setCurrLocationContextAndBlock(Pred->getLocationContext(),
L.getBlock());
ExprEng.setCurrStackFrameAndBlock(Pred->getStackFrame(), L.getBlock());
ExprEng.processCFGElement(*E, Pred, 0);
} else
HandleBlockExit(L.getBlock(), Pred);
@ -365,7 +361,7 @@ void CoreEngine::HandleBlockEntrance(const BlockEntrance &L,
void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode *Pred) {
if (const Stmt *Term = B->getTerminatorStmt()) {
ExprEng.setCurrLocationContextAndBlock(Pred->getLocationContext(), B);
ExprEng.setCurrStackFrameAndBlock(Pred->getStackFrame(), B);
switch (Term->getStmtClass()) {
default:
@ -403,7 +399,7 @@ void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode *Pred) {
// Our logic for EH analysis can certainly be improved.
for (const CFGBlock *Succ : B->succs()) {
if (Succ) {
BlockEdge BE(B, Succ, Pred->getLocationContext());
BlockEdge BE(B, Succ, Pred->getStackFrame());
if (ExplodedNode *N = makeNode(BE, Pred->State, Pred))
WList->enqueue(N);
}
@ -484,14 +480,13 @@ void CoreEngine::HandleBlockExit(const CFGBlock * B, ExplodedNode *Pred) {
assert(B->succ_size() == 1 &&
"Blocks with no terminator should have at most 1 successor.");
BlockEdge BE(B, *(B->succ_begin()), Pred->getLocationContext());
BlockEdge BE(B, *(B->succ_begin()), Pred->getStackFrame());
if (ExplodedNode *N = makeNode(BE, Pred->State, Pred))
WList->enqueue(N);
}
void CoreEngine::HandleCallEnter(const CallEnter &CE, ExplodedNode *Pred) {
ExprEng.setCurrLocationContextAndBlock(Pred->getLocationContext(),
CE.getEntry());
ExprEng.setCurrStackFrameAndBlock(Pred->getStackFrame(), CE.getEntry());
ExprEng.processCallEnter(CE, Pred);
}
@ -541,20 +536,20 @@ void CoreEngine::HandlePostStmt(const CFGBlock *B, unsigned StmtIdx,
if (StmtIdx == B->size())
HandleBlockExit(B, Pred);
else {
ExprEng.setCurrLocationContextAndBlock(Pred->getLocationContext(), B);
ExprEng.setCurrStackFrameAndBlock(Pred->getStackFrame(), B);
ExprEng.processCFGElement((*B)[StmtIdx], Pred, StmtIdx);
}
}
void CoreEngine::HandleVirtualBaseBranch(const CFGBlock *B,
ExplodedNode *Pred) {
const LocationContext *LCtx = Pred->getLocationContext();
if (const auto *CallerCtor = dyn_cast_or_null<CXXConstructExpr>(
LCtx->getStackFrame()->getCallSite())) {
const StackFrame *SF = Pred->getStackFrame();
if (const auto *CallerCtor =
dyn_cast_or_null<CXXConstructExpr>(SF->getCallSite())) {
switch (CallerCtor->getConstructionKind()) {
case CXXConstructionKind::NonVirtualBase:
case CXXConstructionKind::VirtualBase: {
BlockEdge Loc(B, *B->succ_begin(), LCtx);
BlockEdge Loc(B, *B->succ_begin(), SF);
HandleBlockEdge(Loc, Pred);
return;
}
@ -565,7 +560,7 @@ void CoreEngine::HandleVirtualBaseBranch(const CFGBlock *B,
// We either don't see a parent stack frame because we're in the top frame,
// or the parent stack frame doesn't initialize our virtual bases.
BlockEdge Loc(B, *(B->succ_begin() + 1), LCtx);
BlockEdge Loc(B, *(B->succ_begin() + 1), SF);
HandleBlockEdge(Loc, Pred);
}
@ -614,7 +609,7 @@ void CoreEngine::enqueueStmtNode(ExplodedNode *N,
// At this point, we know we're processing a normal statement.
CFGStmt CS = (*Block)[Idx].castAs<CFGStmt>();
PostStmt Loc(CS.getStmt(), N->getLocationContext());
PostStmt Loc(CS.getStmt(), N->getStackFrame());
if (Loc == N->getLocation().withTag(nullptr)) {
// Note: 'N' should be a fresh node because otherwise it shouldn't be
@ -632,10 +627,9 @@ void CoreEngine::enqueueStmtNode(ExplodedNode *N,
std::optional<unsigned>
CoreEngine::getCompletedIterationCount(const CFGBlock *B,
ExplodedNode *Pred) const {
const LocationContext *LC = Pred->getLocationContext();
const StackFrame *SF = Pred->getStackFrame();
BlockCounter Counter = WList->getBlockCounter();
unsigned BlockCount =
Counter.getNumVisited(LC->getStackFrame(), B->getBlockID());
unsigned BlockCount = Counter.getNumVisited(SF, B->getBlockID());
const Stmt *Term = B->getTerminatorStmt();
if (isa<ForStmt, WhileStmt, CXXForRangeStmt>(Term)) {
@ -666,12 +660,12 @@ void CoreEngine::enqueueStmtNodes(ExplodedNodeSet &Set, const CFGBlock *Block,
void CoreEngine::enqueueEndOfFunction(ExplodedNodeSet &Set, const ReturnStmt *RS) {
for (ExplodedNode *Node : Set) {
const LocationContext *LocCtx = Node->getLocationContext();
const StackFrame *SF = Node->getStackFrame();
// If we are in an inlined call, generate CallExitBegin node.
if (LocCtx->getParent()) {
// Use the callee location context.
CallExitBegin Loc(cast<StackFrame>(LocCtx), RS);
if (SF->getParent()) {
// Use the callee stack frame.
CallExitBegin Loc(SF, RS);
if (ExplodedNode *Succ = makeNode(Loc, Node->getState(), Node))
WList->enqueue(Succ);
} else {

View file

@ -63,9 +63,9 @@ static const Expr *ignoreTransparentExprs(const Expr *E) {
return ignoreTransparentExprs(E);
}
EnvironmentEntry::EnvironmentEntry(const Expr *E, const LocationContext *L)
: std::pair<const Expr *, const StackFrame *>(
ignoreTransparentExprs(E), L ? L->getStackFrame() : nullptr) {}
EnvironmentEntry::EnvironmentEntry(const Expr *E, const StackFrame *SF)
: std::pair<const Expr *, const StackFrame *>(ignoreTransparentExprs(E),
SF) {}
SVal Environment::lookupExpr(const EnvironmentEntry &E) const {
const SVal* X = ExprBindings.lookup(E);
@ -79,7 +79,7 @@ SVal Environment::lookupExpr(const EnvironmentEntry &E) const {
SVal Environment::getSVal(const EnvironmentEntry &Entry,
SValBuilder& svalBuilder) const {
const Expr *Ex = Entry.getExpr();
const LocationContext *LCtx = Entry.getLocationContext();
const StackFrame *SF = Entry.getStackFrame();
switch (Ex->getStmtClass()) {
case Stmt::CXXBindTemporaryExprClass:
@ -108,7 +108,7 @@ SVal Environment::getSVal(const EnvironmentEntry &Entry,
// Handle all other Expr* using a lookup.
default:
return lookupExpr(EnvironmentEntry(Ex, LCtx));
return lookupExpr(EnvironmentEntry(Ex, SF));
}
}
@ -174,7 +174,7 @@ EnvironmentManager::removeDeadBindings(Environment Env,
const EnvironmentEntry &BlkExpr = I.getKey();
SVal X = I.getData();
if (SymReaper.isLive(BlkExpr.getExpr(), BlkExpr.getLocationContext())) {
if (SymReaper.isLive(BlkExpr.getExpr(), BlkExpr.getStackFrame())) {
// Copy the binding to the new map.
EBMapRef = EBMapRef.add(BlkExpr, X);
@ -188,7 +188,7 @@ EnvironmentManager::removeDeadBindings(Environment Env,
}
void Environment::printJson(raw_ostream &Out, const ASTContext &Ctx,
const LocationContext *LCtx, const char *NL,
const StackFrame *SF, const char *NL,
unsigned int Space, bool IsDot) const {
Indent(Out, Space, IsDot) << "\"environment\": ";
@ -198,28 +198,27 @@ void Environment::printJson(raw_ostream &Out, const ASTContext &Ctx,
}
++Space;
if (!LCtx) {
// Find the freshest location context.
llvm::SmallPtrSet<const LocationContext *, 16> FoundContexts;
if (!SF) {
// Find the freshest stack frame.
llvm::SmallPtrSet<const StackFrame *, 16> FoundStackFrames;
for (const auto &I : *this) {
const LocationContext *LC = I.first.getLocationContext();
if (FoundContexts.count(LC) == 0) {
// This context is fresher than all other contexts so far.
LCtx = LC;
for (const LocationContext *LCI = LC; LCI; LCI = LCI->getParent())
FoundContexts.insert(LCI);
const StackFrame *CurrentSF = I.first.getStackFrame();
if (FoundStackFrames.count(CurrentSF) == 0) {
// This stack frame is fresher than all other stack frames so far.
SF = CurrentSF;
for (const StackFrame *SFI = CurrentSF; SFI; SFI = SFI->getParent())
FoundStackFrames.insert(SFI);
}
}
}
assert(LCtx);
assert(SF);
Out << "{ \"pointer\": \"" << (const void *)LCtx->getStackFrame()
<< "\", \"items\": [" << NL;
Out << "{ \"pointer\": \"" << (const void *)SF << "\", \"items\": [" << NL;
PrintingPolicy PP = Ctx.getPrintingPolicy();
LCtx->printJson(Out, NL, Space, IsDot, [&](const LocationContext *LC) {
// LCtx items begin
SF->printJson(Out, NL, Space, IsDot, [&](const StackFrame *SF) {
// SF items begin
bool HasItem = false;
unsigned int InnerSpace = Space + 1;
@ -227,7 +226,7 @@ void Environment::printJson(raw_ostream &Out, const ASTContext &Ctx,
BindingsTy::iterator LastI = ExprBindings.end();
for (BindingsTy::iterator I = ExprBindings.begin(); I != ExprBindings.end();
++I) {
if (I->first.getLocationContext() != LC)
if (I->first.getStackFrame() != SF)
continue;
if (!HasItem) {
@ -244,7 +243,7 @@ void Environment::printJson(raw_ostream &Out, const ASTContext &Ctx,
for (BindingsTy::iterator I = ExprBindings.begin(); I != ExprBindings.end();
++I) {
if (I->first.getLocationContext() != LC)
if (I->first.getStackFrame() != SF)
continue;
const Expr *Ex = I->first.getExpr();

View file

@ -73,7 +73,7 @@ bool ExplodedGraph::shouldCollect(const ExplodedNode *node) {
// (4) There is no 'tag' for the ProgramPoint.
// (5) The 'store' is the same as the predecessor.
// (6) The 'GDM' is the same as the predecessor.
// (7) The LocationContext is the same as the predecessor.
// (7) The StackFrame is the same as the predecessor.
// (8) Expressions that are *not* lvalue expressions.
// (9) The PostStmt isn't for a non-consumed Stmt or Expr.
// (10) The successor is neither a CallExpr StmtPoint nor a CallEnter or
@ -111,7 +111,7 @@ bool ExplodedGraph::shouldCollect(const ExplodedNode *node) {
ProgramStateRef state = node->getState();
ProgramStateRef pred_state = pred->getState();
if (state->store != pred_state->store || state->GDM != pred_state->GDM ||
progPoint.getLocationContext() != pred->getLocationContext())
progPoint.getStackFrame() != pred->getStackFrame())
return false;
// All further checks require expressions. As per #3, we know that we have
@ -130,7 +130,7 @@ bool ExplodedGraph::shouldCollect(const ExplodedNode *node) {
// Do not collect nodes for non-consumed Stmt or Expr to ensure precise
// diagnostic generation; specifically, so that we could anchor arrows
// pointing to the beginning of statements (as written in code).
const ParentMap &PM = progPoint.getLocationContext()->getParentMap();
const ParentMap &PM = progPoint.getStackFrame()->getParentMap();
if (!PM.isConsumedExpr(Ex))
return false;
@ -292,36 +292,33 @@ const CFGBlock *ExplodedNode::getCFGBlock() const {
// FIXME: getStmtForDiagnostics() does nasty things in order to provide
// a valid statement for body farms, do we need this behavior here?
if (const Stmt *S = getStmtForDiagnostics())
return getLocationContext()
->getAnalysisDeclContext()
->getCFGStmtMap()
->getBlock(S);
return getStackFrame()->getAnalysisDeclContext()->getCFGStmtMap()->getBlock(
S);
return nullptr;
}
static const LocationContext *
findTopAutosynthesizedParentContext(const LocationContext *LC) {
assert(LC->getAnalysisDeclContext()->isBodyAutosynthesized());
const LocationContext *ParentLC = LC->getParent();
assert(ParentLC && "We don't start analysis from autosynthesized code");
while (ParentLC->getAnalysisDeclContext()->isBodyAutosynthesized()) {
LC = ParentLC;
ParentLC = LC->getParent();
assert(ParentLC && "We don't start analysis from autosynthesized code");
static const StackFrame *
findTopAutosynthesizedParentStackFrame(const StackFrame *SF) {
assert(SF->getAnalysisDeclContext()->isBodyAutosynthesized());
const StackFrame *ParentSF = SF->getParent();
assert(ParentSF && "We don't start analysis from autosynthesized code");
while (ParentSF->getAnalysisDeclContext()->isBodyAutosynthesized()) {
SF = ParentSF;
ParentSF = SF->getParent();
assert(ParentSF && "We don't start analysis from autosynthesized code");
}
return LC;
return SF;
}
const Stmt *ExplodedNode::getStmtForDiagnostics() const {
// We cannot place diagnostics on autosynthesized code.
// Put them onto the call site through which we jumped into autosynthesized
// code for the first time.
const LocationContext *LC = getLocationContext();
if (LC->getAnalysisDeclContext()->isBodyAutosynthesized()) {
const StackFrame *SF = getStackFrame();
if (SF->getAnalysisDeclContext()->isBodyAutosynthesized()) {
// It must be a stack frame because we only autosynthesize functions.
return cast<StackFrame>(findTopAutosynthesizedParentContext(LC))
->getCallSite();
return findTopAutosynthesizedParentStackFrame(SF)->getCallSite();
}
// Otherwise, see if the node's program point directly points to a statement.
// FIXME: Refactor into a ProgramPoint method?
@ -333,7 +330,7 @@ const Stmt *ExplodedNode::getStmtForDiagnostics() const {
if (auto CE = P.getAs<CallEnter>())
return CE->getCallExpr();
if (auto CEE = P.getAs<CallExitEnd>())
return CEE->getCalleeContext()->getCallSite();
return CEE->getCalleeStackFrame()->getCallSite();
if (auto PIPP = P.getAs<PostInitializer>())
return PIPP->getInitializer()->getInit();
if (auto CEB = P.getAs<CallExitBegin>())

File diff suppressed because it is too large Load diff

View file

@ -30,10 +30,10 @@ static SVal conjureOffsetSymbolOnLocation(SVal Symbol, SVal Other,
ConstCFGElementRef Elem, QualType Ty,
SValBuilder &svalBuilder,
unsigned Count,
const LocationContext *LCtx) {
const StackFrame *SF) {
if (isa<Loc>(Other) && Ty->isIntegralOrEnumerationType() &&
Symbol.isUnknown()) {
return svalBuilder.conjureSymbolVal(Elem, LCtx, Ty, Count);
return svalBuilder.conjureSymbolVal(Elem, SF, Ty, Count);
}
return Symbol;
}
@ -55,9 +55,9 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
it != ei; ++it) {
ProgramStateRef state = (*it)->getState();
const LocationContext *LCtx = (*it)->getLocationContext();
SVal LeftV = state->getSVal(LHS, LCtx);
SVal RightV = state->getSVal(RHS, LCtx);
const StackFrame *SF = (*it)->getStackFrame();
SVal LeftV = state->getSVal(LHS, SF);
SVal RightV = state->getSVal(RHS, SF);
BinaryOperator::Opcode Op = B->getOpcode();
@ -66,14 +66,14 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
// FIXME: Handle structs.
if (RightV.isUnknown()) {
unsigned Count = getNumVisitedCurrent();
RightV = svalBuilder.conjureSymbolVal(nullptr, getCFGElementRef(), LCtx,
RightV = svalBuilder.conjureSymbolVal(nullptr, getCFGElementRef(), SF,
Count);
}
// Simulate the effects of a "store": bind the value of the RHS
// to the L-Value represented by the LHS.
SVal ExprVal = B->isGLValue() ? LeftV : RightV;
evalStore(Tmp2, B, LHS, *it, state->BindExpr(B, LCtx, ExprVal),
LeftV, RightV);
evalStore(Tmp2, B, LHS, *it, state->BindExpr(B, SF, ExprVal), LeftV,
RightV);
continue;
}
@ -86,23 +86,23 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
unsigned Count = getNumVisitedCurrent();
RightV = conjureOffsetSymbolOnLocation(
RightV, LeftV, getCFGElementRef(), RHS->getType(), svalBuilder,
Count, LCtx);
Count, SF);
LeftV = conjureOffsetSymbolOnLocation(LeftV, RightV, getCFGElementRef(),
LHS->getType(), svalBuilder,
Count, LCtx);
Count, SF);
}
// Although we don't yet model pointers-to-members, we do need to make
// sure that the members of temporaries have a valid 'this' pointer for
// other checks.
if (B->getOpcode() == BO_PtrMemD)
state = createTemporaryRegionIfNeeded(state, LCtx, LHS);
state = createTemporaryRegionIfNeeded(state, SF, LHS);
// Process non-assignments except commas or short-circuited
// logical expressions (LAnd and LOr).
SVal Result = evalBinOp(state, Op, LeftV, RightV, B->getType());
if (!Result.isUnknown()) {
state = state->BindExpr(B, LCtx, Result);
state = state->BindExpr(B, SF, Result);
} else {
// If we cannot evaluate the operation escape the operands.
state = escapeValues(state, LeftV, PSK_EscapeOther);
@ -138,8 +138,8 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
for (ExplodedNode *N : Tmp) {
state = N->getState();
const LocationContext *LCtx = N->getLocationContext();
SVal V = state->getSVal(LHS, LCtx);
const StackFrame *SF = N->getStackFrame();
SVal V = state->getSVal(LHS, SF);
// Get the computation type.
QualType CTy =
@ -169,7 +169,7 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
// expression, not the computation type, as this is the value the
// LValue on the LHS will bind to.
LHSVal = svalBuilder.conjureSymbolVal(/*symbolTag=*/nullptr,
getCFGElementRef(), LCtx, LTy,
getCFGElementRef(), SF, LTy,
getNumVisitedCurrent());
// However, we need to convert the symbol to the computation type.
Result = svalBuilder.evalCast(LHSVal, CTy, LTy);
@ -182,9 +182,9 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B,
// In C++, assignment and compound assignment operators return an
// lvalue.
if (B->isGLValue())
state = state->BindExpr(B, LCtx, location);
state = state->BindExpr(B, SF, location);
else
state = state->BindExpr(B, LCtx, Result);
state = state->BindExpr(B, SF, Result);
evalStore(Tmp2, B, LHS, N, state, location, LHSVal);
}
@ -201,7 +201,7 @@ void ExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
const BlockDecl *BD = BE->getBlockDecl();
// Get the value of the block itself.
SVal V = svalBuilder.getBlockPointer(BD, T, Pred->getLocationContext(),
SVal V = svalBuilder.getBlockPointer(BD, T, Pred->getStackFrame(),
getNumVisitedCurrent());
ProgramStateRef State = Pred->getState();
@ -233,21 +233,20 @@ void ExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
if (capturedR != originalR) {
SVal originalV;
const LocationContext *LCtx = Pred->getLocationContext();
const StackFrame *SF = Pred->getStackFrame();
if (copyExpr) {
originalV = State->getSVal(copyExpr, LCtx);
originalV = State->getSVal(copyExpr, SF);
} else {
originalV = State->getSVal(loc::MemRegionVal(originalR));
}
State = State->bindLoc(loc::MemRegionVal(capturedR), originalV, LCtx);
State = State->bindLoc(loc::MemRegionVal(capturedR), originalV, SF);
}
}
}
ExplodedNodeSet Tmp;
NodeBuilder Bldr(Pred, Tmp, *currBldrCtx);
Bldr.generateNode(BE, Pred,
State->BindExpr(BE, Pred->getLocationContext(), V),
Bldr.generateNode(BE, Pred, State->BindExpr(BE, Pred->getStackFrame(), V),
nullptr, ProgramPoint::PostLValueKind);
// FIXME: Move all post/pre visits to ::Visit().
@ -256,9 +255,9 @@ void ExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
ProgramStateRef
ExprEngine::handleLValueBitCast(ProgramStateRef state, const Expr *Ex,
const LocationContext *LCtx, QualType T,
QualType ExTy, const CastExpr *CastE,
NodeBuilder &Bldr, ExplodedNode *Pred) {
const StackFrame *SF, QualType T, QualType ExTy,
const CastExpr *CastE, NodeBuilder &Bldr,
ExplodedNode *Pred) {
if (T->isLValueReferenceType()) {
assert(!CastE->getType()->isLValueReferenceType());
ExTy = getContext().getLValueReferenceType(ExTy);
@ -267,14 +266,14 @@ ExprEngine::handleLValueBitCast(ProgramStateRef state, const Expr *Ex,
ExTy = getContext().getRValueReferenceType(ExTy);
}
// Delegate to SValBuilder to process.
SVal OrigV = state->getSVal(Ex, LCtx);
SVal OrigV = state->getSVal(Ex, SF);
SVal SimplifiedOrigV = svalBuilder.simplifySVal(state, OrigV);
SVal V = svalBuilder.evalCast(SimplifiedOrigV, T, ExTy);
// Negate the result if we're treating the boolean as a signed i1
if (CastE->getCastKind() == CK_BooleanToSignedIntegral && V.isValid())
V = svalBuilder.evalMinus(V.castAs<NonLoc>());
state = state->BindExpr(CastE, LCtx, V);
state = state->BindExpr(CastE, SF, V);
if (V.isUnknown() && !OrigV.isUnknown()) {
state = escapeValues(state, OrigV, PSK_EscapeOther);
}
@ -292,8 +291,8 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
if (CastE->getCastKind() == CK_LValueToRValue) {
for (ExplodedNode *Node : DstPreStmt) {
ProgramStateRef State = Node->getState();
const LocationContext *LCtx = Node->getLocationContext();
evalLoad(Dst, CastE, CastE, Node, State, State->getSVal(Ex, LCtx));
const StackFrame *SF = Node->getStackFrame();
evalLoad(Dst, CastE, CastE, Node, State, State->getSVal(Ex, SF));
}
return;
}
@ -304,8 +303,8 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
// Simulate the lvalue-to-rvalue conversion on `Ex`:
for (ExplodedNode *Node : DstPreStmt) {
ProgramStateRef State = Node->getState();
const LocationContext *LCtx = Node->getLocationContext();
evalLocation(DstEvalLoc, CastE, Ex, Node, State, State->getSVal(Ex, LCtx),
const StackFrame *SF = Node->getStackFrame();
evalLocation(DstEvalLoc, CastE, Ex, Node, State, State->getSVal(Ex, SF),
true);
}
// Simulate the operation that actually casts the original value to a new
@ -314,18 +313,18 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
for (ExplodedNode *Node : DstEvalLoc) {
ProgramStateRef State = Node->getState();
const LocationContext *LCtx = Node->getLocationContext();
const StackFrame *SF = Node->getStackFrame();
// Although `Ex` is an lvalue, it could have `Loc::ConcreteInt` kind
// (e.g., `(int *)123456`). In such cases, there is no MemRegion
// available and we can't get the value to be casted.
SVal CastedV = UnknownVal();
if (const MemRegion *MR = State->getSVal(Ex, LCtx).getAsRegion()) {
if (const MemRegion *MR = State->getSVal(Ex, SF).getAsRegion()) {
SVal OrigV = State->getSVal(MR);
CastedV = svalBuilder.evalCast(svalBuilder.simplifySVal(State, OrigV),
CastE->getType(), Ex->getType());
}
State = State->BindExpr(CastE, LCtx, CastedV);
State = State->BindExpr(CastE, SF, CastedV);
Bldr.generateNode(CastE, Node, State);
}
return;
@ -341,7 +340,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
NodeBuilder Bldr(DstPreStmt, Dst, *currBldrCtx);
for (ExplodedNode *Pred : DstPreStmt) {
ProgramStateRef state = Pred->getState();
const LocationContext *LCtx = Pred->getLocationContext();
const StackFrame *SF = Pred->getStackFrame();
switch (CastE->getCastKind()) {
case CK_LValueToRValue:
@ -370,26 +369,25 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
case CK_HLSLArrayRValue: {
// Copy the SVal of Ex to CastE.
ProgramStateRef state = Pred->getState();
const LocationContext *LCtx = Pred->getLocationContext();
SVal V = state->getSVal(Ex, LCtx);
state = state->BindExpr(CastE, LCtx, V);
const StackFrame *SF = Pred->getStackFrame();
SVal V = state->getSVal(Ex, SF);
state = state->BindExpr(CastE, SF, V);
Bldr.generateNode(CastE, Pred, state);
continue;
}
case CK_MemberPointerToBoolean:
case CK_PointerToBoolean: {
SVal V = state->getSVal(Ex, LCtx);
SVal V = state->getSVal(Ex, SF);
auto PTMSV = V.getAs<nonloc::PointerToMember>();
if (PTMSV)
V = svalBuilder.makeTruthVal(!PTMSV->isNullMemberPointer(), ExTy);
if (V.isUndef() || PTMSV) {
state = state->BindExpr(CastE, LCtx, V);
state = state->BindExpr(CastE, SF, V);
Bldr.generateNode(CastE, Pred, state);
continue;
}
// Explicitly proceed with default handler for this case cascade.
state =
handleLValueBitCast(state, Ex, LCtx, T, ExTy, CastE, Bldr, Pred);
state = handleLValueBitCast(state, Ex, SF, T, ExTy, CastE, Bldr, Pred);
continue;
}
case CK_Dependent:
@ -399,15 +397,14 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
case CK_BooleanToSignedIntegral:
case CK_IntegralToPointer:
case CK_PointerToIntegral: {
SVal V = state->getSVal(Ex, LCtx);
SVal V = state->getSVal(Ex, SF);
if (isa<nonloc::PointerToMember>(V)) {
state = state->BindExpr(CastE, LCtx, UnknownVal());
state = state->BindExpr(CastE, SF, UnknownVal());
Bldr.generateNode(CastE, Pred, state);
continue;
}
// Explicitly proceed with default handler for this case cascade.
state =
handleLValueBitCast(state, Ex, LCtx, T, ExTy, CastE, Bldr, Pred);
state = handleLValueBitCast(state, Ex, SF, T, ExTy, CastE, Bldr, Pred);
continue;
}
case CK_IntegralToBoolean:
@ -438,33 +435,32 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
case CK_FixedPointToBoolean:
case CK_FixedPointToIntegral:
case CK_IntegralToFixedPoint: {
state =
handleLValueBitCast(state, Ex, LCtx, T, ExTy, CastE, Bldr, Pred);
state = handleLValueBitCast(state, Ex, SF, T, ExTy, CastE, Bldr, Pred);
continue;
}
case CK_IntegralCast: {
// Delegate to SValBuilder to process.
SVal V = state->getSVal(Ex, LCtx);
SVal V = state->getSVal(Ex, SF);
if (AMgr.options.ShouldSupportSymbolicIntegerCasts)
V = svalBuilder.evalCast(V, T, ExTy);
else
V = svalBuilder.evalIntegralCast(state, V, T, ExTy);
state = state->BindExpr(CastE, LCtx, V);
state = state->BindExpr(CastE, SF, V);
Bldr.generateNode(CastE, Pred, state);
continue;
}
case CK_DerivedToBase:
case CK_UncheckedDerivedToBase: {
// For DerivedToBase cast, delegate to the store manager.
SVal val = state->getSVal(Ex, LCtx);
SVal val = state->getSVal(Ex, SF);
val = getStoreManager().evalDerivedToBase(val, CastE);
state = state->BindExpr(CastE, LCtx, val);
state = state->BindExpr(CastE, SF, val);
Bldr.generateNode(CastE, Pred, state);
continue;
}
// Handle C++ dyn_cast.
case CK_Dynamic: {
SVal val = state->getSVal(Ex, LCtx);
SVal val = state->getSVal(Ex, SF);
// Compute the type of the result.
QualType resultType = CastE->getType();
@ -489,25 +485,25 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
continue;
} else {
// If the cast fails on a pointer, bind to 0.
state = state->BindExpr(CastE, LCtx,
state = state->BindExpr(CastE, SF,
svalBuilder.makeNullWithType(resultType));
}
} else {
// If we don't know if the cast succeeded, conjure a new symbol.
if (val.isUnknown()) {
DefinedOrUnknownSVal NewSym = svalBuilder.conjureSymbolVal(
/*symbolTag=*/nullptr, getCFGElementRef(), LCtx, resultType,
/*symbolTag=*/nullptr, getCFGElementRef(), SF, resultType,
getNumVisitedCurrent());
state = state->BindExpr(CastE, LCtx, NewSym);
state = state->BindExpr(CastE, SF, NewSym);
} else
// Else, bind to the derived region value.
state = state->BindExpr(CastE, LCtx, val);
state = state->BindExpr(CastE, SF, val);
}
Bldr.generateNode(CastE, Pred, state);
continue;
}
case CK_BaseToDerived: {
SVal val = state->getSVal(Ex, LCtx);
SVal val = state->getSVal(Ex, SF);
QualType resultType = CastE->getType();
if (CastE->isGLValue())
resultType = getContext().getPointerType(resultType);
@ -520,34 +516,34 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
// Failed to cast or the result is unknown, fall back to conservative.
if (val.isUnknown()) {
val = svalBuilder.conjureSymbolVal(
/*symbolTag=*/nullptr, getCFGElementRef(), LCtx, resultType,
/*symbolTag=*/nullptr, getCFGElementRef(), SF, resultType,
getNumVisitedCurrent());
}
state = state->BindExpr(CastE, LCtx, val);
state = state->BindExpr(CastE, SF, val);
Bldr.generateNode(CastE, Pred, state);
continue;
}
case CK_NullToPointer: {
SVal V = svalBuilder.makeNullWithType(CastE->getType());
state = state->BindExpr(CastE, LCtx, V);
state = state->BindExpr(CastE, SF, V);
Bldr.generateNode(CastE, Pred, state);
continue;
}
case CK_NullToMemberPointer: {
SVal V = svalBuilder.getMemberPointer(nullptr);
state = state->BindExpr(CastE, LCtx, V);
state = state->BindExpr(CastE, SF, V);
Bldr.generateNode(CastE, Pred, state);
continue;
}
case CK_DerivedToBaseMemberPointer:
case CK_BaseToDerivedMemberPointer:
case CK_ReinterpretMemberPointer: {
SVal V = state->getSVal(Ex, LCtx);
SVal V = state->getSVal(Ex, SF);
if (auto PTMSV = V.getAs<nonloc::PointerToMember>()) {
SVal CastedPTMSV =
svalBuilder.makePointerToMember(getBasicVals().accumCXXBase(
CastE->path(), *PTMSV, CastE->getCastKind()));
state = state->BindExpr(CastE, LCtx, CastedPTMSV);
state = state->BindExpr(CastE, SF, CastedPTMSV);
Bldr.generateNode(CastE, Pred, state);
continue;
}
@ -566,9 +562,9 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
if (CastE->isGLValue())
resultType = getContext().getPointerType(resultType);
SVal result = svalBuilder.conjureSymbolVal(
/*symbolTag=*/nullptr, getCFGElementRef(), LCtx, resultType,
/*symbolTag=*/nullptr, getCFGElementRef(), SF, resultType,
getNumVisitedCurrent());
state = state->BindExpr(CastE, LCtx, result);
state = state->BindExpr(CastE, SF, result);
Bldr.generateNode(CastE, Pred, state);
continue;
}
@ -582,23 +578,23 @@ void ExprEngine::VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL,
NodeBuilder B(Pred, Dst, *currBldrCtx);
ProgramStateRef State = Pred->getState();
const LocationContext *LCtx = Pred->getLocationContext();
const StackFrame *SF = Pred->getStackFrame();
const Expr *Init = CL->getInitializer();
SVal V = State->getSVal(CL->getInitializer(), LCtx);
SVal V = State->getSVal(CL->getInitializer(), SF);
if (isa<CXXConstructExpr, CXXStdInitializerListExpr>(Init)) {
// No work needed. Just pass the value up to this expression.
} else {
assert(isa<InitListExpr>(Init));
Loc CLLoc = State->getLValue(CL, LCtx);
State = State->bindLoc(CLLoc, V, LCtx);
Loc CLLoc = State->getLValue(CL, SF);
State = State->bindLoc(CLLoc, V, SF);
if (CL->isGLValue())
V = CLLoc;
}
B.generateNode(CL, Pred, State->BindExpr(CL, LCtx, V));
B.generateNode(CL, Pred, State->BindExpr(CL, SF, V));
}
void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
@ -634,18 +630,18 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
I!=E; ++I) {
ExplodedNode *N = *I;
ProgramStateRef state = N->getState();
const LocationContext *LC = N->getLocationContext();
const StackFrame *SF = N->getStackFrame();
// Decls without InitExpr are not initialized explicitly.
if (const Expr *InitEx = VD->getInit()) {
// Note in the state that the initialization has occurred.
ExplodedNode *UpdatedN = N;
SVal InitVal = state->getSVal(InitEx, LC);
SVal InitVal = state->getSVal(InitEx, SF);
assert(DS->isSingleDecl());
if (getObjectUnderConstruction(state, DS, LC)) {
state = finishObjectConstruction(state, DS, LC);
if (getObjectUnderConstruction(state, DS, SF)) {
state = finishObjectConstruction(state, DS, SF);
// We constructed the object directly in the variable.
// No need to bind anything.
B.generateNode(DS, UpdatedN, state);
@ -659,14 +655,14 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
}
InitVal = svalBuilder.conjureSymbolVal(
/*symbolTag=*/nullptr, getCFGElementRef(), LC, Ty,
/*symbolTag=*/nullptr, getCFGElementRef(), SF, Ty,
getNumVisitedCurrent());
}
B.takeNodes(UpdatedN);
ExplodedNodeSet Dst2;
evalBind(Dst2, DS, UpdatedN, state->getLValue(VD, LC), InitVal, true);
evalBind(Dst2, DS, UpdatedN, state->getLValue(VD, SF), InitVal, true);
B.addNodes(Dst2);
}
}
@ -755,7 +751,7 @@ void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred,
assert(!SrcBlock->empty());
CFGStmt Elem = SrcBlock->rbegin()->castAs<CFGStmt>();
const Expr *RHS = cast<Expr>(Elem.getStmt());
SVal RHSVal = N->getState()->getSVal(RHS, Pred->getLocationContext());
SVal RHSVal = N->getState()->getSVal(RHS, Pred->getStackFrame());
if (RHSVal.isUndef()) {
X = RHSVal;
@ -769,7 +765,7 @@ void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred,
Zero, B->getType());
}
}
Bldr.generateNode(B, Pred, state->BindExpr(B, Pred->getLocationContext(), X));
Bldr.generateNode(B, Pred, state->BindExpr(B, Pred->getStackFrame(), X));
}
void ExprEngine::VisitGuardedExpr(const Expr *Ex,
@ -781,7 +777,7 @@ void ExprEngine::VisitGuardedExpr(const Expr *Ex,
NodeBuilder B(Pred, Dst, *currBldrCtx);
ProgramStateRef state = Pred->getState();
const LocationContext *LCtx = Pred->getLocationContext();
const StackFrame *SF = Pred->getStackFrame();
const CFGBlock *SrcBlock = nullptr;
// Find the predecessor block.
@ -822,18 +818,18 @@ void ExprEngine::VisitGuardedExpr(const Expr *Ex,
// subexpression, get its the value.
if (ValEx == L->IgnoreParens() || ValEx == R->IgnoreParens()) {
hasValue = true;
V = SrcState->getSVal(ValEx, LCtx);
V = SrcState->getSVal(ValEx, SF);
}
break;
}
}
if (!hasValue)
V = svalBuilder.conjureSymbolVal(nullptr, getCFGElementRef(), LCtx,
V = svalBuilder.conjureSymbolVal(nullptr, getCFGElementRef(), SF,
getNumVisitedCurrent());
// Generate a new node with the binding from the appropriate path.
B.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V, true));
B.generateNode(Ex, Pred, state->BindExpr(Ex, SF, V, true));
}
void ExprEngine::
@ -848,8 +844,7 @@ VisitOffsetOfExpr(const OffsetOfExpr *OOE,
assert(IV.isSigned() == OOE->getType()->isSignedIntegerType());
SVal X = svalBuilder.makeIntVal(IV);
B.generateNode(OOE, Pred,
Pred->getState()->BindExpr(OOE, Pred->getLocationContext(),
X));
Pred->getState()->BindExpr(OOE, Pred->getStackFrame(), X));
}
// FIXME: Handle the case where __builtin_offsetof is not a constant.
}
@ -890,7 +885,7 @@ VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex,
ProgramStateRef state = N->getState();
state = state->BindExpr(
Ex, N->getLocationContext(),
Ex, N->getStackFrame(),
svalBuilder.makeIntVal(amt.getQuantity(), Ex->getType()));
Bldr.generateNode(Ex, N, state);
}
@ -909,8 +904,8 @@ void ExprEngine::handleUOExtension(ExplodedNode *N, const UnaryOperator *U,
// subexpression.
const Expr *Ex = U->getSubExpr()->IgnoreParens();
ProgramStateRef state = N->getState();
const LocationContext *LCtx = N->getLocationContext();
Bldr.generateNode(U, N, state->BindExpr(U, LCtx, state->getSVal(Ex, LCtx)));
const StackFrame *SF = N->getStackFrame();
Bldr.generateNode(U, N, state->BindExpr(U, SF, state->getSVal(Ex, SF)));
}
void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, ExplodedNode *Pred,
@ -943,9 +938,8 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, ExplodedNode *Pred,
// For all other types, UO_Real is an identity operation.
assert (U->getType() == Ex->getType());
ProgramStateRef state = N->getState();
const LocationContext *LCtx = N->getLocationContext();
Bldr.generateNode(U, N,
state->BindExpr(U, LCtx, state->getSVal(Ex, LCtx)));
const StackFrame *SF = N->getStackFrame();
Bldr.generateNode(U, N, state->BindExpr(U, SF, state->getSVal(Ex, SF)));
break;
}
@ -958,9 +952,9 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, ExplodedNode *Pred,
}
// For all other types, UO_Imag returns 0.
ProgramStateRef state = N->getState();
const LocationContext *LCtx = N->getLocationContext();
const StackFrame *SF = N->getStackFrame();
SVal X = svalBuilder.makeZeroVal(Ex->getType());
Bldr.generateNode(U, N, state->BindExpr(U, LCtx, X));
Bldr.generateNode(U, N, state->BindExpr(U, SF, X));
break;
}
@ -972,9 +966,9 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, ExplodedNode *Pred,
if (isa<CXXMethodDecl, FieldDecl, IndirectFieldDecl>(VD)) {
ProgramStateRef State = N->getState();
const LocationContext *LCtx = N->getLocationContext();
const StackFrame *SF = N->getStackFrame();
SVal SV = svalBuilder.getMemberPointer(cast<NamedDecl>(VD));
Bldr.generateNode(U, N, State->BindExpr(U, LCtx, SV));
Bldr.generateNode(U, N, State->BindExpr(U, SF, SV));
break;
}
}
@ -997,13 +991,13 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, ExplodedNode *Pred,
assert (!U->isGLValue());
const Expr *Ex = U->getSubExpr()->IgnoreParens();
ProgramStateRef state = N->getState();
const LocationContext *LCtx = N->getLocationContext();
const StackFrame *SF = N->getStackFrame();
// Get the value of the subexpression.
SVal V = state->getSVal(Ex, LCtx);
SVal V = state->getSVal(Ex, SF);
if (V.isUnknownOrUndef()) {
Bldr.generateNode(U, N, state->BindExpr(U, LCtx, V));
Bldr.generateNode(U, N, state->BindExpr(U, SF, V));
break;
}
@ -1013,12 +1007,12 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, ExplodedNode *Pred,
case UO_Not:
// FIXME: Do we need to handle promotions?
state = state->BindExpr(
U, LCtx, svalBuilder.evalComplement(V.castAs<NonLoc>()));
U, SF, svalBuilder.evalComplement(V.castAs<NonLoc>()));
break;
case UO_Minus:
// FIXME: Do we need to handle promotions?
state = state->BindExpr(U, LCtx,
svalBuilder.evalMinus(V.castAs<NonLoc>()));
state =
state->BindExpr(U, SF, svalBuilder.evalMinus(V.castAs<NonLoc>()));
break;
case UO_LNot:
// C99 6.5.3.3: "The expression !E is equivalent to (0==E)."
@ -1037,7 +1031,7 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, ExplodedNode *Pred,
Result = evalBinOp(state, BO_EQ, V.castAs<NonLoc>(), X, U->getType());
}
state = state->BindExpr(U, LCtx, Result);
state = state->BindExpr(U, SF, Result);
break;
}
Bldr.generateNode(U, N, state);
@ -1056,9 +1050,9 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U,
assert (U->isIncrementDecrementOp());
const Expr *Ex = U->getSubExpr()->IgnoreParens();
const LocationContext *LCtx = Pred->getLocationContext();
const StackFrame *SF = Pred->getStackFrame();
ProgramStateRef state = Pred->getState();
SVal loc = state->getSVal(Ex, LCtx);
SVal loc = state->getSVal(Ex, SF);
// Perform a load.
ExplodedNodeSet Tmp;
@ -1068,12 +1062,12 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U,
NodeBuilder Bldr(Tmp, Dst2, *currBldrCtx);
for (ExplodedNode *N : Tmp) {
state = N->getState();
assert(LCtx == N->getLocationContext());
SVal V2_untested = state->getSVal(Ex, LCtx);
assert(SF == N->getStackFrame());
SVal V2_untested = state->getSVal(Ex, SF);
// Propagate unknown and undefined values.
if (V2_untested.isUnknownOrUndef()) {
state = state->BindExpr(U, LCtx, V2_untested);
state = state->BindExpr(U, SF, V2_untested);
// Perform the store, so that the uninitialized value detection happens.
Bldr.takeNodes(N);
@ -1113,7 +1107,7 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U,
// Conjure a new symbol if necessary to recover precision.
if (Result.isUnknown()){
DefinedOrUnknownSVal SymVal = svalBuilder.conjureSymbolVal(
/*symbolTag=*/nullptr, getCFGElementRef(), LCtx,
/*symbolTag=*/nullptr, getCFGElementRef(), SF,
getNumVisitedCurrent());
Result = SymVal;
@ -1139,9 +1133,9 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U,
// Since the lvalue-to-rvalue conversion is explicit in the AST,
// we bind an l-value if the operator is prefix and an lvalue (in C++).
if (U->isGLValue())
state = state->BindExpr(U, LCtx, loc);
state = state->BindExpr(U, SF, loc);
else
state = state->BindExpr(U, LCtx, U->isPostfix() ? V2 : Result);
state = state->BindExpr(U, SF, U->isPostfix() ? V2 : Result);
// Perform the store.
Bldr.takeNodes(N);

Some files were not shown because too many files have changed in this diff Show more