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