1 //===-- StorageLocation.h ---------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines classes that represent elements of the local variable store
10 // and of the heap during dataflow analysis.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_STORAGELOCATION_H
15 #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_STORAGELOCATION_H
16 
17 #include "clang/AST/Decl.h"
18 #include "clang/AST/Type.h"
19 #include "llvm/ADT/DenseMap.h"
20 
21 namespace clang {
22 namespace dataflow {
23 
24 /// Base class for elements of the local variable store and of the heap.
25 ///
26 /// Each storage location holds a value. The mapping from storage locations to
27 /// values is stored in the environment.
28 class StorageLocation {
29 public:
30   enum class Kind { Scalar, Aggregate };
31 
32   StorageLocation(Kind LocKind, QualType Type) : LocKind(LocKind), Type(Type) {}
33 
34   // Non-copyable because addresses of storage locations are used as their
35   // identities throughout framework and user code. The framework is responsible
36   // for construction and destruction of storage locations.
37   StorageLocation(const StorageLocation &) = delete;
38   StorageLocation &operator=(const StorageLocation &) = delete;
39 
40   virtual ~StorageLocation() = default;
41 
42   Kind getKind() const { return LocKind; }
43 
44   QualType getType() const { return Type; }
45 
46 private:
47   Kind LocKind;
48   QualType Type;
49 };
50 
51 /// A storage location that is not subdivided further for the purposes of
52 /// abstract interpretation. For example: `int`, `int*`, `int&`.
53 class ScalarStorageLocation final : public StorageLocation {
54 public:
55   explicit ScalarStorageLocation(QualType Type)
56       : StorageLocation(Kind::Scalar, Type) {}
57 
58   static bool classof(const StorageLocation *Loc) {
59     return Loc->getKind() == Kind::Scalar;
60   }
61 };
62 
63 /// A storage location which is subdivided into smaller storage locations that
64 /// can be traced independently by abstract interpretation. For example: a
65 /// struct with public members. The child map is flat, so when used for a struct
66 /// or class type, all accessible members of base struct and class types are
67 /// directly accesible as children of this location.
68 class AggregateStorageLocation final : public StorageLocation {
69 public:
70   explicit AggregateStorageLocation(QualType Type)
71       : AggregateStorageLocation(
72             Type, llvm::DenseMap<const ValueDecl *, StorageLocation *>()) {}
73 
74   AggregateStorageLocation(
75       QualType Type,
76       llvm::DenseMap<const ValueDecl *, StorageLocation *> Children)
77       : StorageLocation(Kind::Aggregate, Type), Children(std::move(Children)) {}
78 
79   static bool classof(const StorageLocation *Loc) {
80     return Loc->getKind() == Kind::Aggregate;
81   }
82 
83   /// Returns the child storage location for `D`.
84   StorageLocation &getChild(const ValueDecl &D) const {
85     auto It = Children.find(&D);
86     assert(It != Children.end());
87     return *It->second;
88   }
89 
90 private:
91   llvm::DenseMap<const ValueDecl *, StorageLocation *> Children;
92 };
93 
94 } // namespace dataflow
95 } // namespace clang
96 
97 #endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_STORAGELOCATION_H
98