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