//===- 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