Skip to content

[analyzer][NFC] Rework SVal kind representation #71039

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
merged 1 commit into from
Nov 4, 2023
Merged
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
10 changes: 5 additions & 5 deletions clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class SValExplainer : public FullSValVisitor<SValExplainer, std::string> {
return "undefined value";
}

std::string VisitLocMemRegionVal(loc::MemRegionVal V) {
std::string VisitMemRegionVal(loc::MemRegionVal V) {
const MemRegion *R = V.getRegion();
// Avoid the weird "pointer to pointee of ...".
if (auto SR = dyn_cast<SymbolicRegion>(R)) {
Expand All @@ -76,19 +76,19 @@ class SValExplainer : public FullSValVisitor<SValExplainer, std::string> {
return "pointer to " + Visit(R);
}

std::string VisitLocConcreteInt(loc::ConcreteInt V) {
std::string VisitConcreteInt(loc::ConcreteInt V) {
const llvm::APSInt &I = V.getValue();
std::string Str;
llvm::raw_string_ostream OS(Str);
OS << "concrete memory address '" << I << "'";
return Str;
}

std::string VisitNonLocSymbolVal(nonloc::SymbolVal V) {
std::string VisitSymbolVal(nonloc::SymbolVal V) {
return Visit(V.getSymbol());
}

std::string VisitNonLocConcreteInt(nonloc::ConcreteInt V) {
std::string VisitConcreteInt(nonloc::ConcreteInt V) {
const llvm::APSInt &I = V.getValue();
std::string Str;
llvm::raw_string_ostream OS(Str);
Expand All @@ -97,7 +97,7 @@ class SValExplainer : public FullSValVisitor<SValExplainer, std::string> {
return Str;
}

std::string VisitNonLocLazyCompoundVal(nonloc::LazyCompoundVal V) {
std::string VisitLazyCompoundVal(nonloc::LazyCompoundVal V) {
return "lazily frozen compound value of " + Visit(V.getRegion());
}

Expand Down
55 changes: 23 additions & 32 deletions clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALVISITOR_H
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALVISITOR_H

#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"

namespace clang {

Expand All @@ -25,49 +25,40 @@ namespace ento {
/// SValVisitor - this class implements a simple visitor for SVal
/// subclasses.
template <typename ImplClass, typename RetTy = void> class SValVisitor {
public:

#define DISPATCH(NAME, CLASS) \
return static_cast<ImplClass *>(this)->Visit ## NAME(V.castAs<CLASS>())
ImplClass &derived() { return *static_cast<ImplClass *>(this); }

public:
RetTy Visit(SVal V) {
// Dispatch to VisitFooVal for each FooVal.
// Take namespaces (loc:: and nonloc::) into account.
switch (V.getBaseKind()) {
#define BASIC_SVAL(Id, Parent) case SVal::Id ## Kind: DISPATCH(Id, Id);
switch (V.getKind()) {
#define BASIC_SVAL(Id, Parent) \
case SVal::Id##Kind: \
return derived().Visit##Id(V.castAs<Id>());
#define LOC_SVAL(Id, Parent) \
case SVal::Loc##Id##Kind: \
return derived().Visit##Id(V.castAs<loc::Id>());
#define NONLOC_SVAL(Id, Parent) \
case SVal::NonLoc##Id##Kind: \
return derived().Visit##Id(V.castAs<nonloc::Id>());
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def"
case SVal::LocKind:
switch (V.getSubKind()) {
#define LOC_SVAL(Id, Parent) \
case loc::Id ## Kind: DISPATCH(Loc ## Id, loc :: Id);
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def"
}
llvm_unreachable("Unknown Loc sub-kind!");
case SVal::NonLocKind:
switch (V.getSubKind()) {
#define NONLOC_SVAL(Id, Parent) \
case nonloc::Id ## Kind: DISPATCH(NonLoc ## Id, nonloc :: Id);
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def"
}
llvm_unreachable("Unknown NonLoc sub-kind!");
}
llvm_unreachable("Unknown SVal kind!");
}

#define BASIC_SVAL(Id, Parent) \
RetTy Visit ## Id(Id V) { DISPATCH(Parent, Id); }
#define ABSTRACT_SVAL(Id, Parent) \
BASIC_SVAL(Id, Parent)
#define LOC_SVAL(Id, Parent) \
RetTy VisitLoc ## Id(loc::Id V) { DISPATCH(Parent, Parent); }
#define NONLOC_SVAL(Id, Parent) \
RetTy VisitNonLoc ## Id(nonloc::Id V) { DISPATCH(Parent, Parent); }
// Dispatch to the more generic handler as a default implementation.
#define BASIC_SVAL(Id, Parent) \
RetTy Visit##Id(Id V) { return derived().Visit##Parent(V.castAs<Id>()); }
#define ABSTRACT_SVAL(Id, Parent) BASIC_SVAL(Id, Parent)
#define LOC_SVAL(Id, Parent) \
RetTy Visit##Id(loc::Id V) { return derived().VisitLoc(V.castAs<Loc>()); }
#define NONLOC_SVAL(Id, Parent) \
RetTy Visit##Id(nonloc::Id V) { \
return derived().VisitNonLoc(V.castAs<NonLoc>()); \
}
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def"

// Base case, ignore it. :)
RetTy VisitSVal(SVal V) { return RetTy(); }

#undef DISPATCH
};

/// SymExprVisitor - this class implements a simple visitor for SymExpr
Expand Down
38 changes: 18 additions & 20 deletions clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.def
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,24 @@
//
//===----------------------------------------------------------------------===//
//
// The list of symbolic values (SVal kinds and sub-kinds) used in the Static
// Analyzer. The distinction between loc:: and nonloc:: SVal namespaces is
// The list of symbolic values (SVal kinds) used in the Static Analyzer.
// The distinction between `loc::` and `nonloc::` SVal namespaces is
// currently hardcoded, because it is too peculiar and explicit to be handled
// uniformly. In order to use this information, users of this file must define
// one or more of the following macros:
//
// BASIC_SVAL(Id, Parent) - for specific SVal sub-kinds, which are
// neither in loc:: nor in nonloc:: namespace; these classes occupy
// their own base kind IdKind.
// BASIC_SVAL(Id, Parent) - for specific SVal kinds, which are
// neither in `loc::` nor in `nonloc::` namespace.
//
// ABSTRACT_SVAL(Id, Parent) - for abstract SVal classes which are
// neither in loc:: nor in nonloc:: namespace,
// neither in `loc::` nor in `nonloc::` namespace,
//
// ABSTRACT_SVAL_WITH_KIND(Id, Parent) - for SVal classes which are also
// neither in loc:: nor in nonloc:: namespace, but occupy a whole base kind
// identifier IdKind, much like BASIC_SVALs.
// LOC_SVAL(Id, Parent) - for values in `loc::` namespace.
//
// LOC_SVAL(Id, Parent) - for values in loc:: namespace, which occupy a sub-kind
// loc::IdKind.
// NONLOC_SVAL(Id, Parent) - for values in `nonloc::` namespace.
//
// NONLOC_SVAL(Id, Parent) - for values in nonloc:: namespace, which occupy a
// sub-kind nonloc::IdKind.
// SVAL_RANGE(Id, First, Last) - for defining range of subtypes of
// the abstract class `Id`.
//
//===----------------------------------------------------------------------===//

Expand All @@ -39,10 +35,6 @@
#define ABSTRACT_SVAL(Id, Parent)
#endif

#ifndef ABSTRACT_SVAL_WITH_KIND
#define ABSTRACT_SVAL_WITH_KIND(Id, Parent) ABSTRACT_SVAL(Id, Parent)
#endif

#ifndef LOC_SVAL
#define LOC_SVAL(Id, Parent)
#endif
Expand All @@ -51,24 +43,30 @@
#define NONLOC_SVAL(Id, Parent)
#endif

#ifndef SVAL_RANGE
#define SVAL_RANGE(Id, First, Last)
#endif

BASIC_SVAL(UndefinedVal, SVal)
ABSTRACT_SVAL(DefinedOrUnknownSVal, SVal)
BASIC_SVAL(UnknownVal, DefinedOrUnknownSVal)
ABSTRACT_SVAL(DefinedSVal, DefinedOrUnknownSVal)
ABSTRACT_SVAL_WITH_KIND(Loc, DefinedSVal)
ABSTRACT_SVAL(Loc, DefinedSVal)
LOC_SVAL(ConcreteInt, Loc)
LOC_SVAL(GotoLabel, Loc)
LOC_SVAL(MemRegionVal, Loc)
ABSTRACT_SVAL_WITH_KIND(NonLoc, DefinedSVal)
SVAL_RANGE(Loc, ConcreteInt, MemRegionVal)
ABSTRACT_SVAL(NonLoc, DefinedSVal)
NONLOC_SVAL(CompoundVal, NonLoc)
NONLOC_SVAL(ConcreteInt, NonLoc)
NONLOC_SVAL(LazyCompoundVal, NonLoc)
NONLOC_SVAL(LocAsInteger, NonLoc)
NONLOC_SVAL(SymbolVal, NonLoc)
NONLOC_SVAL(PointerToMember, NonLoc)
SVAL_RANGE(NonLoc, CompoundVal, PointerToMember)

#undef SVAL_RANGE
#undef NONLOC_SVAL
#undef LOC_SVAL
#undef ABSTRACT_SVAL_WITH_KIND
#undef ABSTRACT_SVAL
#undef BASIC_SVAL
Loading