Skip to content

[Clang][analyzer] replace Stmt* with ConstCFGElementRef in SymbolConjured #128251

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion clang/include/clang/Analysis/CFG.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ class CFGElement {
return (Kind) x;
}

void dumpToStream(llvm::raw_ostream &OS) const;
void dumpToStream(llvm::raw_ostream &OS,
bool TerminateWithNewLine = true) const;

void dump() const {
dumpToStream(llvm::errs());
Expand Down Expand Up @@ -695,6 +696,11 @@ class CFGBlock {
void dump() const {
dumpToStream(llvm::errs());
}

void Profile(llvm::FoldingSetNodeID &ID) const {
ID.AddPointer(Parent);
ID.AddInteger(Index);
}
};

template <bool IsReverse, bool IsConst> class ElementRefIterator {
Expand Down Expand Up @@ -1190,6 +1196,8 @@ class CFGBlock {
}
};

using ConstCFGElementRef = CFGBlock::ConstCFGElementRef;

/// CFGCallback defines methods that should be called when a logical
/// operator error is found when building the CFG.
class CFGCallback {
Expand Down
11 changes: 10 additions & 1 deletion clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/raw_ostream.h"

namespace clang {

Expand All @@ -29,6 +30,13 @@ class SValExplainer : public FullSValVisitor<SValExplainer, std::string> {
ASTContext &ACtx;
ProgramStateRef State;

std::string printCFGElementRef(ConstCFGElementRef Elem) {
std::string Str;
llvm::raw_string_ostream OS(Str);
Elem->dumpToStream(OS, /*TerminateWithNewLine=*/false);
return Str;
}

std::string printStmt(const Stmt *S) {
std::string Str;
llvm::raw_string_ostream OS(Str);
Expand Down Expand Up @@ -114,7 +122,8 @@ class SValExplainer : public FullSValVisitor<SValExplainer, std::string> {

std::string VisitSymbolConjured(const SymbolConjured *S) {
return "symbol of type '" + S->getType().getAsString() +
"' conjured at statement '" + printStmt(S->getStmt()) + "'";
"' conjured at CFG element '" +
printCFGElementRef(S->getCFGElementRef()) + "'";
}

std::string VisitSymbolDerived(const SymbolDerived *S) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ class CheckerContext {
return Pred->getSVal(S);
}

ConstCFGElementRef getCFGElementRef() const { return Eng.getCFGElementRef(); }

/// Returns true if the value of \p E is greater than or equal to \p
/// Val under unsigned comparison.
bool isGreaterOrEqual(const Expr *E, unsigned long long Val);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ class ExprEngine {
return (*G.roots_begin())->getLocation().getLocationContext();
}

CFGBlock::ConstCFGElementRef getCFGElementRef() const {
ConstCFGElementRef getCFGElementRef() const {
const CFGBlock *blockPtr = currBldrCtx ? currBldrCtx->getBlock() : nullptr;
return {blockPtr, currStmtIdx};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ namespace ento {
/// by the loop body in any iteration.
ProgramStateRef getWidenedLoopState(ProgramStateRef PrevState,
const LocationContext *LCtx,
unsigned BlockCount, const Stmt *LoopStmt);
unsigned BlockCount,
ConstCFGElementRef Elem);

} // end namespace ento
} // end namespace clang
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ class ProgramState : public llvm::FoldingSetNode {
/// be triggered by this event.
///
/// \param Regions the set of regions to be invalidated.
/// \param E the expression that caused the invalidation.
/// \param Elem The CFG Element that caused the invalidation.
/// \param BlockCount The number of times the current basic block has been
/// visited.
/// \param CausesPointerEscape the flag is set to true when the invalidation
Expand All @@ -325,16 +325,17 @@ class ProgramState : public llvm::FoldingSetNode {
/// \param ITraits information about special handling for particular regions
/// or symbols.
[[nodiscard]] ProgramStateRef
invalidateRegions(ArrayRef<const MemRegion *> Regions, const Stmt *S,
unsigned BlockCount, const LocationContext *LCtx,
bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr,
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<SVal> Values, const Stmt *S, unsigned BlockCount,
const LocationContext *LCtx, bool CausesPointerEscape,
InvalidatedSymbols *IS = nullptr,
invalidateRegions(ArrayRef<SVal> Values, ConstCFGElementRef Elem,
unsigned BlockCount, const LocationContext *LCtx,
bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr,
const CallEvent *Call = nullptr,
RegionAndSymbolInvalidationTraits *ITraits = nullptr) const;

Expand Down
37 changes: 10 additions & 27 deletions clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/Type.h"
#include "clang/Analysis/CFG.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
Expand Down Expand Up @@ -171,19 +172,11 @@ class SValBuilder {

// Forwarding methods to SymbolManager.

const SymbolConjured* conjureSymbol(const Stmt *stmt,
const SymbolConjured *conjureSymbol(ConstCFGElementRef Elem,
const LocationContext *LCtx,
QualType type,
unsigned visitCount,
QualType type, unsigned visitCount,
const void *symbolTag = nullptr) {
return SymMgr.conjureSymbol(stmt, LCtx, type, visitCount, symbolTag);
}

const SymbolConjured* conjureSymbol(const Expr *expr,
const LocationContext *LCtx,
unsigned visitCount,
const void *symbolTag = nullptr) {
return SymMgr.conjureSymbol(expr, LCtx, visitCount, symbolTag);
return SymMgr.conjureSymbol(Elem, LCtx, type, visitCount, symbolTag);
}

/// Construct an SVal representing '0' for the specified type.
Expand All @@ -199,29 +192,19 @@ class SValBuilder {
/// preserve the relation between related(or even equivalent) expressions, so
/// conjured symbols should be used sparingly.
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag,
const Expr *expr,
ConstCFGElementRef elem,
const LocationContext *LCtx,
unsigned count);
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, const Stmt *S,
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag,
ConstCFGElementRef elem,
const LocationContext *LCtx,
QualType type, unsigned count);
DefinedOrUnknownSVal conjureSymbolVal(const Stmt *stmt,
DefinedOrUnknownSVal conjureSymbolVal(ConstCFGElementRef elem,
const LocationContext *LCtx,
QualType type,
unsigned visitCount);
QualType type, unsigned visitCount);

/// Conjure a symbol representing heap allocated memory region.
///
/// Note, the expression should represent a location.
DefinedSVal getConjuredHeapSymbolVal(const Expr *E,
const LocationContext *LCtx,
unsigned Count);

/// Conjure a symbol representing heap allocated memory region.
///
/// Note, now, the expression *doesn't* need to represent a location.
/// But the type need to!
DefinedSVal getConjuredHeapSymbolVal(const Expr *E,
DefinedSVal getConjuredHeapSymbolVal(ConstCFGElementRef elem,
const LocationContext *LCtx,
QualType type, unsigned Count);

Expand Down
8 changes: 4 additions & 4 deletions clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_STORE_H

#include "clang/AST/Type.h"
#include "clang/Basic/LLVM.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallVector.h"
Expand Down Expand Up @@ -223,7 +223,7 @@ class StoreManager {
///
/// \param[in] store The initial store.
/// \param[in] Values The values to invalidate.
/// \param[in] S The current statement being evaluated. Used to conjure
/// \param[in] Elem The current CFG Element being evaluated. Used to conjure
/// symbols to mark the values of invalidated regions.
/// \param[in] Count The current block count. Used to conjure
/// symbols to mark the values of invalidated regions.
Expand All @@ -241,8 +241,8 @@ class StoreManager {
/// even if they do not currently have bindings. Pass \c NULL if this
/// information will not be used.
virtual StoreRef invalidateRegions(
Store store, ArrayRef<SVal> Values, const Stmt *S, unsigned Count,
const LocationContext *LCtx, const CallEvent *Call,
Store store, ArrayRef<SVal> Values, ConstCFGElementRef Elem,
unsigned Count, const LocationContext *LCtx, const CallEvent *Call,
InvalidatedSymbols &IS, RegionAndSymbolInvalidationTraits &ITraits,
InvalidatedRegions *TopLevelRegions, InvalidatedRegions *Invalidated) = 0;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,29 +80,62 @@ class SymbolRegionValue : public SymbolData {
/// A symbol representing the result of an expression in the case when we do
/// not know anything about what the expression is.
class SymbolConjured : public SymbolData {
const Stmt *S;
ConstCFGElementRef Elem;
QualType T;
unsigned Count;
const LocationContext *LCtx;
const void *SymbolTag;

friend class SymExprAllocator;
SymbolConjured(SymbolID sym, const Stmt *s, const LocationContext *lctx,
QualType t, unsigned count, const void *symbolTag)
: SymbolData(SymbolConjuredKind, sym), S(s), T(t), Count(count),
SymbolConjured(SymbolID sym, ConstCFGElementRef elem,
const LocationContext *lctx, QualType t, unsigned count,
const void *symbolTag)
: SymbolData(SymbolConjuredKind, sym), Elem(elem), T(t), Count(count),
LCtx(lctx), SymbolTag(symbolTag) {
// FIXME: 's' might be a nullptr if we're conducting invalidation
// that was caused by a destructor call on a temporary object,
// which has no statement associated with it.
// Due to this, we might be creating the same invalidation symbol for
// two different invalidation passes (for two different temporaries).
assert(lctx);
assert(isValidTypeForSymbol(t));
}

public:
/// It might return null.
const Stmt *getStmt() const { return S; }
ConstCFGElementRef getCFGElementRef() const { return Elem; }

// It might return null.
const Stmt *getStmt() const {
switch (Elem->getKind()) {
case CFGElement::Initializer:
return Elem->castAs<CFGInitializer>().getInitializer()->getInit();
case CFGElement::ScopeBegin:
return Elem->castAs<CFGScopeBegin>().getTriggerStmt();
case CFGElement::ScopeEnd:
return Elem->castAs<CFGScopeEnd>().getTriggerStmt();
case CFGElement::NewAllocator:
return Elem->castAs<CFGNewAllocator>().getAllocatorExpr();
case CFGElement::LifetimeEnds:
return Elem->castAs<CFGLifetimeEnds>().getTriggerStmt();
case CFGElement::LoopExit:
return Elem->castAs<CFGLoopExit>().getLoopStmt();
case CFGElement::Statement:
return Elem->castAs<CFGStmt>().getStmt();
case CFGElement::Constructor:
return Elem->castAs<CFGConstructor>().getStmt();
case CFGElement::CXXRecordTypedCall:
return Elem->castAs<CFGCXXRecordTypedCall>().getStmt();
case CFGElement::AutomaticObjectDtor:
return Elem->castAs<CFGAutomaticObjDtor>().getTriggerStmt();
case CFGElement::DeleteDtor:
return Elem->castAs<CFGDeleteDtor>().getDeleteExpr();
case CFGElement::BaseDtor:
return nullptr;
case CFGElement::MemberDtor:
return nullptr;
case CFGElement::TemporaryDtor:
return Elem->castAs<CFGTemporaryDtor>().getBindTemporaryExpr();
case CFGElement::CleanupFunction:
return nullptr;
}
return nullptr;
}

unsigned getCount() const { return Count; }
/// It might return null.
const void *getTag() const { return SymbolTag; }
Expand All @@ -113,19 +146,19 @@ class SymbolConjured : public SymbolData {

void dumpToStream(raw_ostream &os) const override;

static void Profile(llvm::FoldingSetNodeID &profile, const Stmt *S,
static void Profile(llvm::FoldingSetNodeID &profile, ConstCFGElementRef Elem,
const LocationContext *LCtx, QualType T, unsigned Count,
const void *SymbolTag) {
profile.AddInteger((unsigned)SymbolConjuredKind);
profile.AddPointer(S);
profile.Add(Elem);
profile.AddPointer(LCtx);
profile.Add(T);
profile.AddInteger(Count);
profile.AddPointer(SymbolTag);
}

void Profile(llvm::FoldingSetNodeID& profile) override {
Profile(profile, S, LCtx, T, Count, SymbolTag);
Profile(profile, Elem, LCtx, T, Count, SymbolTag);
}

// Implement isa<T> support.
Expand Down Expand Up @@ -533,18 +566,12 @@ class SymbolManager {
template <typename SymExprT, typename... Args>
const SymExprT *acquire(Args &&...args);

const SymbolConjured *conjureSymbol(const Stmt *E,
const SymbolConjured *conjureSymbol(ConstCFGElementRef Elem,
const LocationContext *LCtx, QualType T,
unsigned VisitCount,
const void *SymbolTag = nullptr) {
return acquire<SymbolConjured>(E, LCtx, T, VisitCount, SymbolTag);
}

const SymbolConjured* conjureSymbol(const Expr *E,
const LocationContext *LCtx,
unsigned VisitCount,
const void *SymbolTag = nullptr) {
return conjureSymbol(E, LCtx, E->getType(), VisitCount, SymbolTag);
return acquire<SymbolConjured>(Elem, LCtx, T, VisitCount, SymbolTag);
}

QualType getType(const SymExpr *SE) const {
Expand Down
Loading
Loading