Skip to content

[analyzer] Enforce not making overly complicated symbols #144327

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

Closed
Show file tree
Hide file tree
Changes from all 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
41 changes: 21 additions & 20 deletions clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ class SValBuilder {
protected:
ASTContext &Context;

const AnalyzerOptions &AnOpts;

/// Manager of APSInt values.
BasicValueFactory BasicVals;

Expand All @@ -68,8 +70,6 @@ class SValBuilder {

ProgramStateManager &StateMgr;

const AnalyzerOptions &AnOpts;

/// The scalar type to use for array indices.
const QualType ArrayIndexTy;

Expand All @@ -91,22 +91,6 @@ class SValBuilder {
SVal evalMinus(NonLoc val);
SVal evalComplement(NonLoc val);

/// Create a new value which represents a binary expression with two non-
/// location operands.
virtual SVal evalBinOpNN(ProgramStateRef state, BinaryOperator::Opcode op,
NonLoc lhs, NonLoc rhs, QualType resultTy) = 0;

/// Create a new value which represents a binary expression with two memory
/// location operands.
virtual SVal evalBinOpLL(ProgramStateRef state, BinaryOperator::Opcode op,
Loc lhs, Loc rhs, QualType resultTy) = 0;

/// Create a new value which represents a binary expression with a memory
/// location and non-location operands. For example, this would be used to
/// evaluate a pointer arithmetic operation.
virtual SVal evalBinOpLN(ProgramStateRef state, BinaryOperator::Opcode op,
Loc lhs, NonLoc rhs, QualType resultTy) = 0;

/// Evaluates a given SVal. If the SVal has only one possible (integer) value,
/// that value is returned. Otherwise, returns NULL.
virtual const llvm::APSInt *getKnownValue(ProgramStateRef state, SVal val) = 0;
Expand Down Expand Up @@ -326,8 +310,8 @@ class SValBuilder {
nonloc::SymbolVal makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
const SymExpr *rhs, QualType type);

NonLoc makeNonLoc(const SymExpr *operand, UnaryOperator::Opcode op,
QualType type);
nonloc::SymbolVal makeNonLoc(const SymExpr *operand, UnaryOperator::Opcode op,
QualType type);

/// Create a NonLoc value for cast.
nonloc::SymbolVal makeNonLoc(const SymExpr *operand, QualType fromTy,
Expand Down Expand Up @@ -396,6 +380,23 @@ class SValBuilder {
/// Return a memory region for the 'this' object reference.
loc::MemRegionVal getCXXThis(const CXXRecordDecl *D,
const StackFrameContext *SFC);

protected:
/// Create a new value which represents a binary expression with two non-
/// location operands.
virtual SVal evalBinOpNN(ProgramStateRef state, BinaryOperator::Opcode op,
NonLoc lhs, NonLoc rhs, QualType resultTy) = 0;

/// Create a new value which represents a binary expression with two memory
/// location operands.
virtual SVal evalBinOpLL(ProgramStateRef state, BinaryOperator::Opcode op,
Loc lhs, Loc rhs, QualType resultTy) = 0;

/// Create a new value which represents a binary expression with a memory
/// location and non-location operands. For example, this would be used to
/// evaluate a pointer arithmetic operation.
virtual SVal evalBinOpLN(ProgramStateRef state, BinaryOperator::Opcode op,
Loc lhs, NonLoc rhs, QualType resultTy) = 0;
};

SValBuilder* createSimpleSValBuilder(llvm::BumpPtrAllocator &alloc,
Expand Down
19 changes: 10 additions & 9 deletions clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,18 @@ class SymExpr : public llvm::FoldingSetNode {
/// Note, however, that it can't be used in Profile because SymbolManager
/// needs to compute Profile before allocating SymExpr.
const SymbolID Sym;
const unsigned Complexity;

protected:
SymExpr(Kind k, SymbolID Sym) : K(k), Sym(Sym) {}
SymExpr(Kind k, SymbolID Sym, unsigned Complexity)
: K(k), Sym(Sym), Complexity(Complexity) {}

static bool isValidTypeForSymbol(QualType T) {
// FIXME: Depending on whether we choose to deprecate structural symbols,
// this may become much stricter.
return !T.isNull() && !T->isVoidType();
}

mutable unsigned Complexity = 0;

public:
virtual ~SymExpr() = default;

Expand Down Expand Up @@ -108,7 +108,7 @@ class SymExpr : public llvm::FoldingSetNode {
return llvm::make_range(symbol_iterator(this), symbol_iterator());
}

virtual unsigned computeComplexity() const = 0;
unsigned complexity() const { return Complexity; }

/// Find the region from which this symbol originates.
///
Expand Down Expand Up @@ -136,21 +136,22 @@ using SymbolRefSmallVectorTy = SmallVector<SymbolRef, 2>;
/// A symbol representing data which can be stored in a memory location
/// (region).
class SymbolData : public SymExpr {
friend class SymbolManager;
void anchor() override;

protected:
SymbolData(Kind k, SymbolID sym) : SymExpr(k, sym) { assert(classof(this)); }
SymbolData(Kind k, SymbolID sym) : SymExpr(k, sym, computeComplexity()) {
assert(classof(this));
}

static unsigned computeComplexity(...) { return 1; }

public:
~SymbolData() override = default;

/// Get a string representation of the kind of the region.
virtual StringRef getKindStr() const = 0;

unsigned computeComplexity() const override {
return 1;
};

// Implement isa<T> support.
static bool classof(const SymExpr *SE) { return classof(SE->getKind()); }
static constexpr bool classof(Kind K) {
Expand Down
Loading
Loading