llvm/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h

//===- SVals.h - Abstract Values for Static Analysis ------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//  This file defines SVal, Loc, and NonLoc, classes that represent
//  abstract r-values for use with path-sensitive value tracking.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H

#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
#include "clang/Basic/LLVM.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableList.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/STLForwardCompat.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Casting.h"
#include <cassert>
#include <cstdint>
#include <optional>
#include <utility>

//==------------------------------------------------------------------------==//
//  Base SVal types.
//==------------------------------------------------------------------------==//

namespace clang {

class CXXBaseSpecifier;
class FunctionDecl;
class LabelDecl;

namespace ento {

class CompoundValData;
class LazyCompoundValData;
class MemRegion;
class PointerToMemberData;
class SValBuilder;
class TypedValueRegion;

/// SVal - This represents a symbolic expression, which can be either
///  an L-value or an R-value.
///
class SVal {};

inline raw_ostream &operator<<(raw_ostream &os, clang::ento::SVal V) {}

namespace nonloc {
/// Sub-kinds for NonLoc values.
#define NONLOC_SVAL
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def"
} // namespace nonloc

namespace loc {
/// Sub-kinds for Loc values.
#define LOC_SVAL
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def"
} // namespace loc

class UndefinedVal : public SVal {};

class DefinedOrUnknownSVal : public SVal {};

class UnknownVal : public DefinedOrUnknownSVal {};

class DefinedSVal : public DefinedOrUnknownSVal {};

class NonLoc : public DefinedSVal {};

class Loc : public DefinedSVal {};

//==------------------------------------------------------------------------==//
//  Subclasses of NonLoc.
//==------------------------------------------------------------------------==//

namespace nonloc {

/// Represents symbolic expression that isn't a location.
class SymbolVal : public NonLoc {};

/// Value representing integer constant.
class ConcreteInt : public NonLoc {};

class LocAsInteger : public NonLoc {};

/// The simplest example of a concrete compound value is nonloc::CompoundVal,
/// which represents a concrete r-value of an initializer-list or a string.
/// Internally, it contains an llvm::ImmutableList of SVal's stored inside the
/// literal.
class CompoundVal : public NonLoc {};

/// While nonloc::CompoundVal covers a few simple use cases,
/// nonloc::LazyCompoundVal is a more performant and flexible way to represent
/// an rvalue of record type, so it shows up much more frequently during
/// analysis. This value is an r-value that represents a snapshot of any
/// structure "as a whole" at a given moment during the analysis. Such value is
/// already quite far from being referred to as "concrete", as many fields
/// inside it would be unknown or symbolic. nonloc::LazyCompoundVal operates by
/// storing two things:
///   * a reference to the TypedValueRegion being snapshotted (yes, it is always
///     typed), and also
///   * a reference to the whole Store object, obtained from the ProgramState in
///     which the nonloc::LazyCompoundVal was created.
///
/// Note that the old ProgramState and its Store is kept alive during the
/// analysis because these are immutable functional data structures and each new
/// Store value is represented as "earlier Store" + "additional binding".
///
/// Essentially, nonloc::LazyCompoundVal is a performance optimization for the
/// analyzer. Because Store is immutable, creating a nonloc::LazyCompoundVal is
/// a very cheap operation. Note that the Store contains all region bindings in
/// the program state, not only related to the region. Later, if necessary, such
/// value can be unpacked -- eg. when it is assigned to another variable.
///
/// If you ever need to inspect the contents of the LazyCompoundVal, you can use
/// StoreManager::iterBindings(). It'll iterate through all values in the Store,
/// but you're only interested in the ones that belong to
/// LazyCompoundVal::getRegion(); other bindings are immaterial.
///
/// NOTE: LazyCompoundVal::getRegion() itself is also immaterial (see the actual
/// method docs for details).
class LazyCompoundVal : public NonLoc {};

/// Value representing pointer-to-member.
///
/// This value is qualified as NonLoc because neither loading nor storing
/// operations are applied to it. Instead, the analyzer uses the L-value coming
/// from pointer-to-member applied to an object.
/// This SVal is represented by a NamedDecl which can be a member function
/// pointer or a member data pointer and an optional list of CXXBaseSpecifiers.
/// This list is required to accumulate the pointer-to-member cast history to
/// figure out the correct subobject field. In particular, implicit casts grow
/// this list and explicit casts like static_cast shrink this list.
class PointerToMember : public NonLoc {};

} // namespace nonloc

//==------------------------------------------------------------------------==//
//  Subclasses of Loc.
//==------------------------------------------------------------------------==//

namespace loc {

class GotoLabel : public Loc {};

class MemRegionVal : public Loc {};

class ConcreteInt : public Loc {};

} // namespace loc
} // namespace ento
} // namespace clang

namespace llvm {
CastInfo<To, From, std::enable_if_t<std::is_base_of< ::clang::ento::SVal, From>::value>>;
} // namespace llvm

#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H