1 //===- GlobalDecl.h - Global declaration holder -----------------*- 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 // A GlobalDecl can hold either a regular variable/function or a C++ ctor/dtor 10 // together with its type. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CLANG_AST_GLOBALDECL_H 15 #define LLVM_CLANG_AST_GLOBALDECL_H 16 17 #include "clang/AST/DeclCXX.h" 18 #include "clang/AST/DeclObjC.h" 19 #include "clang/AST/DeclOpenMP.h" 20 #include "clang/Basic/ABI.h" 21 #include "clang/Basic/LLVM.h" 22 #include "llvm/ADT/DenseMapInfo.h" 23 #include "llvm/ADT/PointerIntPair.h" 24 #include "llvm/Support/Casting.h" 25 #include "llvm/Support/type_traits.h" 26 #include <cassert> 27 28 namespace clang { 29 30 enum class DynamicInitKind : unsigned { 31 NoStub = 0, 32 Initializer, 33 AtExit, 34 }; 35 36 /// GlobalDecl - represents a global declaration. This can either be a 37 /// CXXConstructorDecl and the constructor type (Base, Complete). 38 /// a CXXDestructorDecl and the destructor type (Base, Complete) or 39 /// a VarDecl, a FunctionDecl or a BlockDecl. 40 class GlobalDecl { 41 llvm::PointerIntPair<const Decl *, 2> Value; 42 unsigned MultiVersionIndex = 0; 43 44 void Init(const Decl *D) { 45 assert(!isa<CXXConstructorDecl>(D) && "Use other ctor with ctor decls!"); 46 assert(!isa<CXXDestructorDecl>(D) && "Use other ctor with dtor decls!"); 47 48 Value.setPointer(D); 49 } 50 51 public: 52 GlobalDecl() = default; 53 GlobalDecl(const VarDecl *D) { Init(D);} 54 GlobalDecl(const FunctionDecl *D, unsigned MVIndex = 0) 55 : MultiVersionIndex(MVIndex) { 56 Init(D); 57 } 58 GlobalDecl(const BlockDecl *D) { Init(D); } 59 GlobalDecl(const CapturedDecl *D) { Init(D); } 60 GlobalDecl(const ObjCMethodDecl *D) { Init(D); } 61 GlobalDecl(const OMPDeclareReductionDecl *D) { Init(D); } 62 GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type) : Value(D, Type) {} 63 GlobalDecl(const CXXDestructorDecl *D, CXXDtorType Type) : Value(D, Type) {} 64 GlobalDecl(const VarDecl *D, DynamicInitKind StubKind) 65 : Value(D, unsigned(StubKind)) {} 66 67 GlobalDecl getCanonicalDecl() const { 68 GlobalDecl CanonGD; 69 CanonGD.Value.setPointer(Value.getPointer()->getCanonicalDecl()); 70 CanonGD.Value.setInt(Value.getInt()); 71 CanonGD.MultiVersionIndex = MultiVersionIndex; 72 73 return CanonGD; 74 } 75 76 const Decl *getDecl() const { return Value.getPointer(); } 77 78 CXXCtorType getCtorType() const { 79 assert(isa<CXXConstructorDecl>(getDecl()) && "Decl is not a ctor!"); 80 return static_cast<CXXCtorType>(Value.getInt()); 81 } 82 83 CXXDtorType getDtorType() const { 84 assert(isa<CXXDestructorDecl>(getDecl()) && "Decl is not a dtor!"); 85 return static_cast<CXXDtorType>(Value.getInt()); 86 } 87 88 DynamicInitKind getDynamicInitKind() const { 89 assert(isa<VarDecl>(getDecl()) && 90 cast<VarDecl>(getDecl())->hasGlobalStorage() && 91 "Decl is not a global variable!"); 92 return static_cast<DynamicInitKind>(Value.getInt()); 93 } 94 95 unsigned getMultiVersionIndex() const { 96 assert(isa<FunctionDecl>(getDecl()) && 97 !isa<CXXConstructorDecl>(getDecl()) && 98 !isa<CXXDestructorDecl>(getDecl()) && 99 "Decl is not a plain FunctionDecl!"); 100 return MultiVersionIndex; 101 } 102 103 friend bool operator==(const GlobalDecl &LHS, const GlobalDecl &RHS) { 104 return LHS.Value == RHS.Value && 105 LHS.MultiVersionIndex == RHS.MultiVersionIndex; 106 } 107 108 void *getAsOpaquePtr() const { return Value.getOpaqueValue(); } 109 110 static GlobalDecl getFromOpaquePtr(void *P) { 111 GlobalDecl GD; 112 GD.Value.setFromOpaqueValue(P); 113 return GD; 114 } 115 116 GlobalDecl getWithDecl(const Decl *D) { 117 GlobalDecl Result(*this); 118 Result.Value.setPointer(D); 119 return Result; 120 } 121 122 GlobalDecl getWithCtorType(CXXCtorType Type) { 123 assert(isa<CXXConstructorDecl>(getDecl())); 124 GlobalDecl Result(*this); 125 Result.Value.setInt(Type); 126 return Result; 127 } 128 129 GlobalDecl getWithDtorType(CXXDtorType Type) { 130 assert(isa<CXXDestructorDecl>(getDecl())); 131 GlobalDecl Result(*this); 132 Result.Value.setInt(Type); 133 return Result; 134 } 135 136 GlobalDecl getWithMultiVersionIndex(unsigned Index) { 137 assert(isa<FunctionDecl>(getDecl()) && 138 !isa<CXXConstructorDecl>(getDecl()) && 139 !isa<CXXDestructorDecl>(getDecl()) && 140 "Decl is not a plain FunctionDecl!"); 141 GlobalDecl Result(*this); 142 Result.MultiVersionIndex = Index; 143 return Result; 144 } 145 }; 146 147 } // namespace clang 148 149 namespace llvm { 150 151 template<> struct DenseMapInfo<clang::GlobalDecl> { 152 static inline clang::GlobalDecl getEmptyKey() { 153 return clang::GlobalDecl(); 154 } 155 156 static inline clang::GlobalDecl getTombstoneKey() { 157 return clang::GlobalDecl:: 158 getFromOpaquePtr(reinterpret_cast<void*>(-1)); 159 } 160 161 static unsigned getHashValue(clang::GlobalDecl GD) { 162 return DenseMapInfo<void*>::getHashValue(GD.getAsOpaquePtr()); 163 } 164 165 static bool isEqual(clang::GlobalDecl LHS, 166 clang::GlobalDecl RHS) { 167 return LHS == RHS; 168 } 169 }; 170 171 } // namespace llvm 172 173 #endif // LLVM_CLANG_AST_GLOBALDECL_H 174