//===-- StorageLocation.h ---------------------------------------*- 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 classes that represent elements of the local variable store
 
// and of the heap during dataflow analysis.
 
//
 
//===----------------------------------------------------------------------===//
 
 
 
#ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_STORAGELOCATION_H
 
#define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_STORAGELOCATION_H
 
 
 
#include "clang/AST/Decl.h"
 
#include "clang/AST/Type.h"
 
#include "llvm/ADT/DenseMap.h"
 
 
 
namespace clang {
 
namespace dataflow {
 
 
 
/// Base class for elements of the local variable store and of the heap.
 
///
 
/// Each storage location holds a value. The mapping from storage locations to
 
/// values is stored in the environment.
 
class StorageLocation {
 
public:
 
  enum class Kind { Scalar, Aggregate };
 
 
 
  StorageLocation(Kind LocKind, QualType Type) : LocKind(LocKind), Type(Type) {}
 
 
 
  // Non-copyable because addresses of storage locations are used as their
 
  // identities throughout framework and user code. The framework is responsible
 
  // for construction and destruction of storage locations.
 
  StorageLocation(const StorageLocation &) = delete;
 
  StorageLocation &operator=(const StorageLocation &) = delete;
 
 
 
  virtual ~StorageLocation() = default;
 
 
 
  Kind getKind() const { return LocKind; }
 
 
 
  QualType getType() const { return Type; }
 
 
 
private:
 
  Kind LocKind;
 
  QualType Type;
 
};
 
 
 
/// A storage location that is not subdivided further for the purposes of
 
/// abstract interpretation. For example: `int`, `int*`, `int&`.
 
class ScalarStorageLocation final : public StorageLocation {
 
public:
 
  explicit ScalarStorageLocation(QualType Type)
 
      : StorageLocation(Kind::Scalar, Type) {}
 
 
 
  static bool classof(const StorageLocation *Loc) {
 
    return Loc->getKind() == Kind::Scalar;
 
  }
 
};
 
 
 
/// A storage location which is subdivided into smaller storage locations that
 
/// can be traced independently by abstract interpretation. For example: a
 
/// struct with public members. The child map is flat, so when used for a struct
 
/// or class type, all accessible members of base struct and class types are
 
/// directly accesible as children of this location.
 
/// FIXME: Currently, the storage location of unions is modelled the same way as
 
/// that of structs or classes. Eventually, we need to change this modelling so
 
/// that all of the members of a given union have the same storage location.
 
class AggregateStorageLocation final : public StorageLocation {
 
public:
 
  explicit AggregateStorageLocation(QualType Type)
 
      : AggregateStorageLocation(
 
            Type, llvm::DenseMap<const ValueDecl *, StorageLocation *>()) {}
 
 
 
  AggregateStorageLocation(
 
      QualType Type,
 
      llvm::DenseMap<const ValueDecl *, StorageLocation *> Children)
 
      : StorageLocation(Kind::Aggregate, Type), Children(std::move(Children)) {}
 
 
 
  static bool classof(const StorageLocation *Loc) {
 
    return Loc->getKind() == Kind::Aggregate;
 
  }
 
 
 
  /// Returns the child storage location for `D`.
 
  StorageLocation &getChild(const ValueDecl &D) const {
 
    auto It = Children.find(&D);
 
    assert(It != Children.end());
 
    return *It->second;
 
  }
 
 
 
private:
 
  llvm::DenseMap<const ValueDecl *, StorageLocation *> Children;
 
};
 
 
 
} // namespace dataflow
 
} // namespace clang
 
 
 
#endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_STORAGELOCATION_H