Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
5 changes: 5 additions & 0 deletions clang/include/clang/Analysis/CFG.h
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,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
17 changes: 16 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,9 @@
#include "clang/AST/DeclCXX.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
#include <cctype>

namespace clang {

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

std::string printCFGElementRef(CFGBlock::ConstCFGElementRef ElemRef) {
Comment thread
steakhal marked this conversation as resolved.
Outdated
std::string Str;
llvm::raw_string_ostream OS(Str);
ElemRef->dumpToStream(OS);
// HACK: `CFGBlock::ConstCFGElementRef::dumpToStream` contains a new line
// character in the end of the string, we don't want it so we remove it
// here.
llvm::StringRef StrRef(Str);
return StrRef.rtrim().str();
Comment thread
steakhal marked this conversation as resolved.
Outdated
}

std::string printStmt(const Stmt *S) {
std::string Str;
llvm::raw_string_ostream OS(Str);
Expand Down Expand Up @@ -114,7 +128,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 statement '" +
Comment thread
steakhal marked this conversation as resolved.
Outdated
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,10 @@ class CheckerContext {
return Pred->getSVal(S);
}

CFGBlock::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 @@ -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,
CFGBlock::ConstCFGElementRef ElemRef);

} // end namespace ento
} // end namespace clang
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,8 @@ 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 ElemRef \p CFGBlock::ConstCFGElementRef that caused the

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// \param ElemRef \p CFGBlock::ConstCFGElementRef that caused the
/// \param ElemRef 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 +326,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,
CFGBlock::ConstCFGElementRef ElemRef, 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, CFGBlock::ConstCFGElementRef ElemRef,
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(CFGBlock::ConstCFGElementRef ElemRef,
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(ElemRef, 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,
CFGBlock::ConstCFGElementRef elemRef,
const LocationContext *LCtx,
unsigned count);
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, const Stmt *S,
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag,
CFGBlock::ConstCFGElementRef elemRef,
const LocationContext *LCtx,
QualType type, unsigned count);
DefinedOrUnknownSVal conjureSymbolVal(const Stmt *stmt,
DefinedOrUnknownSVal conjureSymbolVal(CFGBlock::ConstCFGElementRef elemRef,
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(CFGBlock::ConstCFGElementRef elemRef,
const LocationContext *LCtx,
QualType type, unsigned Count);

Expand Down
11 changes: 6 additions & 5 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,8 +223,9 @@ 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
/// symbols to mark the values of invalidated regions.
/// \param[in] ElemRef The current \p CFGBlock::ConstCFGElementRef 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.
/// \param[in] Call The call expression which will be used to determine which
Expand All @@ -241,8 +242,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, CFGBlock::ConstCFGElementRef ElemRef,
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,64 @@ 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;
CFGBlock::ConstCFGElementRef ElemRef;
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),
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).
SymbolConjured(SymbolID sym, CFGBlock::ConstCFGElementRef elemRef,
const LocationContext *lctx, QualType t, unsigned count,
const void *symbolTag)
: SymbolData(SymbolConjuredKind, sym), ElemRef(elemRef), T(t),
Count(count), LCtx(lctx), SymbolTag(symbolTag) {
assert(lctx);
assert(isValidTypeForSymbol(t));
}

public:
/// It might return null.
const Stmt *getStmt() const { return S; }
Comment thread
steakhal marked this conversation as resolved.
const CFGBlock::ConstCFGElementRef getCFGElementRef() const {
return ElemRef;
}
Comment thread
fangyi-zhou marked this conversation as resolved.

// It might return null.
const Stmt *getStmt() const {
switch (ElemRef->getKind()) {
case CFGElement::Initializer:
return ElemRef->castAs<CFGInitializer>().getInitializer()->getInit();
case CFGElement::ScopeBegin:
return ElemRef->castAs<CFGScopeBegin>().getTriggerStmt();
case CFGElement::ScopeEnd:
return ElemRef->castAs<CFGScopeEnd>().getTriggerStmt();
case CFGElement::NewAllocator:
return ElemRef->castAs<CFGNewAllocator>().getAllocatorExpr();
case CFGElement::LifetimeEnds:
return ElemRef->castAs<CFGLifetimeEnds>().getTriggerStmt();
case CFGElement::LoopExit:
return ElemRef->castAs<CFGLoopExit>().getLoopStmt();
case CFGElement::Statement:
return ElemRef->castAs<CFGStmt>().getStmt();
case CFGElement::Constructor:
return ElemRef->castAs<CFGConstructor>().getStmt();
case CFGElement::CXXRecordTypedCall:
return ElemRef->castAs<CFGCXXRecordTypedCall>().getStmt();
case CFGElement::AutomaticObjectDtor:
return ElemRef->castAs<CFGAutomaticObjDtor>().getTriggerStmt();
case CFGElement::DeleteDtor:
return ElemRef->castAs<CFGDeleteDtor>().getDeleteExpr();
case CFGElement::BaseDtor:
return nullptr;
case CFGElement::MemberDtor:
return nullptr;
case CFGElement::TemporaryDtor:
return ElemRef->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 +148,20 @@ 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,
CFGBlock::ConstCFGElementRef ElemRef,
const LocationContext *LCtx, QualType T, unsigned Count,
const void *SymbolTag) {
profile.AddInteger((unsigned)SymbolConjuredKind);
profile.AddPointer(S);
profile.Add(ElemRef);
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, ElemRef, LCtx, T, Count, SymbolTag);
}

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

const SymbolConjured *conjureSymbol(const Stmt *E,
const SymbolConjured *conjureSymbol(CFGBlock::ConstCFGElementRef ElemRef,
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>(ElemRef, LCtx, T, VisitCount, SymbolTag);
}

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