1 //===-- DataflowAnalysisContext.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 a DataflowAnalysisContext class that owns objects that
10 //  encompass the state of a program and stores context that is used during
11 //  dataflow analysis.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWANALYSISCONTEXT_H
16 #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWANALYSISCONTEXT_H
17 
18 #include "clang/AST/Decl.h"
19 #include "clang/AST/Expr.h"
20 #include "clang/Analysis/FlowSensitive/StorageLocation.h"
21 #include "clang/Analysis/FlowSensitive/Value.h"
22 #include "llvm/ADT/DenseMap.h"
23 #include <cassert>
24 #include <memory>
25 #include <type_traits>
26 #include <utility>
27 #include <vector>
28 
29 namespace clang {
30 namespace dataflow {
31 
32 /// Owns objects that encompass the state of a program and stores context that
33 /// is used during dataflow analysis.
34 class DataflowAnalysisContext {
35 public:
36   DataflowAnalysisContext()
37       : TrueVal(&takeOwnership(std::make_unique<BoolValue>())),
38         FalseVal(&takeOwnership(std::make_unique<BoolValue>())) {}
39 
40   /// Takes ownership of `Loc` and returns a reference to it.
41   ///
42   /// Requirements:
43   ///
44   ///  `Loc` must not be null.
45   template <typename T>
46   typename std::enable_if<std::is_base_of<StorageLocation, T>::value, T &>::type
47   takeOwnership(std::unique_ptr<T> Loc) {
48     assert(Loc != nullptr);
49     Locs.push_back(std::move(Loc));
50     return *cast<T>(Locs.back().get());
51   }
52 
53   /// Takes ownership of `Val` and returns a reference to it.
54   ///
55   /// Requirements:
56   ///
57   ///  `Val` must not be null.
58   template <typename T>
59   typename std::enable_if<std::is_base_of<Value, T>::value, T &>::type
60   takeOwnership(std::unique_ptr<T> Val) {
61     assert(Val != nullptr);
62     Vals.push_back(std::move(Val));
63     return *cast<T>(Vals.back().get());
64   }
65 
66   /// Assigns `Loc` as the storage location of `D`.
67   ///
68   /// Requirements:
69   ///
70   ///  `D` must not be assigned a storage location.
71   void setStorageLocation(const ValueDecl &D, StorageLocation &Loc) {
72     assert(DeclToLoc.find(&D) == DeclToLoc.end());
73     DeclToLoc[&D] = &Loc;
74   }
75 
76   /// Returns the storage location assigned to `D` or null if `D` has no
77   /// assigned storage location.
78   StorageLocation *getStorageLocation(const ValueDecl &D) const {
79     auto It = DeclToLoc.find(&D);
80     return It == DeclToLoc.end() ? nullptr : It->second;
81   }
82 
83   /// Assigns `Loc` as the storage location of `E`.
84   ///
85   /// Requirements:
86   ///
87   ///  `E` must not be assigned a storage location.
88   void setStorageLocation(const Expr &E, StorageLocation &Loc) {
89     assert(ExprToLoc.find(&E) == ExprToLoc.end());
90     ExprToLoc[&E] = &Loc;
91   }
92 
93   /// Returns the storage location assigned to `E` or null if `E` has no
94   /// assigned storage location.
95   StorageLocation *getStorageLocation(const Expr &E) const {
96     auto It = ExprToLoc.find(&E);
97     return It == ExprToLoc.end() ? nullptr : It->second;
98   }
99 
100   /// Assigns `Loc` as the storage location of the `this` pointee.
101   ///
102   /// Requirements:
103   ///
104   ///  The `this` pointee must not be assigned a storage location.
105   void setThisPointeeStorageLocation(StorageLocation &Loc) {
106     assert(ThisPointeeLoc == nullptr);
107     ThisPointeeLoc = &Loc;
108   }
109 
110   /// Returns the storage location assigned to the `this` pointee or null if the
111   /// `this` pointee has no assigned storage location.
112   StorageLocation *getThisPointeeStorageLocation() const {
113     return ThisPointeeLoc;
114   }
115 
116   /// Returns a symbolic boolean value that models a boolean literal equal to
117   /// `Value`.
118   BoolValue &getBoolLiteralValue(bool Value) const {
119     return Value ? *TrueVal : *FalseVal;
120   }
121 
122 private:
123   // Storage for the state of a program.
124   std::vector<std::unique_ptr<StorageLocation>> Locs;
125   std::vector<std::unique_ptr<Value>> Vals;
126 
127   // Maps from program declarations and statements to storage locations that are
128   // assigned to them. These assignments are global (aggregated across all basic
129   // blocks) and are used to produce stable storage locations when the same
130   // basic blocks are evaluated multiple times. The storage locations that are
131   // in scope for a particular basic block are stored in `Environment`.
132   llvm::DenseMap<const ValueDecl *, StorageLocation *> DeclToLoc;
133   llvm::DenseMap<const Expr *, StorageLocation *> ExprToLoc;
134 
135   StorageLocation *ThisPointeeLoc = nullptr;
136 
137   // FIXME: Add support for boolean expressions.
138   BoolValue *TrueVal;
139   BoolValue *FalseVal;
140 };
141 
142 } // namespace dataflow
143 } // namespace clang
144 
145 #endif // LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_DATAFLOWANALYSISCONTEXT_H
146