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 OMPDeclareMapperDecl *D) { Init(D); } 63 GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type) : Value(D, Type) {} 64 GlobalDecl(const CXXDestructorDecl *D, CXXDtorType Type) : Value(D, Type) {} 65 GlobalDecl(const VarDecl *D, DynamicInitKind StubKind) 66 : Value(D, unsigned(StubKind)) {} 67 68 GlobalDecl getCanonicalDecl() const { 69 GlobalDecl CanonGD; 70 CanonGD.Value.setPointer(Value.getPointer()->getCanonicalDecl()); 71 CanonGD.Value.setInt(Value.getInt()); 72 CanonGD.MultiVersionIndex = MultiVersionIndex; 73 74 return CanonGD; 75 } 76 77 const Decl *getDecl() const { return Value.getPointer(); } 78 79 CXXCtorType getCtorType() const { 80 assert(isa<CXXConstructorDecl>(getDecl()) && "Decl is not a ctor!"); 81 return static_cast<CXXCtorType>(Value.getInt()); 82 } 83 84 CXXDtorType getDtorType() const { 85 assert(isa<CXXDestructorDecl>(getDecl()) && "Decl is not a dtor!"); 86 return static_cast<CXXDtorType>(Value.getInt()); 87 } 88 89 DynamicInitKind getDynamicInitKind() const { 90 assert(isa<VarDecl>(getDecl()) && 91 cast<VarDecl>(getDecl())->hasGlobalStorage() && 92 "Decl is not a global variable!"); 93 return static_cast<DynamicInitKind>(Value.getInt()); 94 } 95 96 unsigned getMultiVersionIndex() const { 97 assert(isa<FunctionDecl>(getDecl()) && 98 !isa<CXXConstructorDecl>(getDecl()) && 99 !isa<CXXDestructorDecl>(getDecl()) && 100 "Decl is not a plain FunctionDecl!"); 101 return MultiVersionIndex; 102 } 103 104 friend bool operator==(const GlobalDecl &LHS, const GlobalDecl &RHS) { 105 return LHS.Value == RHS.Value && 106 LHS.MultiVersionIndex == RHS.MultiVersionIndex; 107 } 108 109 void *getAsOpaquePtr() const { return Value.getOpaqueValue(); } 110 111 static GlobalDecl getFromOpaquePtr(void *P) { 112 GlobalDecl GD; 113 GD.Value.setFromOpaqueValue(P); 114 return GD; 115 } 116 117 GlobalDecl getWithDecl(const Decl *D) { 118 GlobalDecl Result(*this); 119 Result.Value.setPointer(D); 120 return Result; 121 } 122 123 GlobalDecl getWithCtorType(CXXCtorType Type) { 124 assert(isa<CXXConstructorDecl>(getDecl())); 125 GlobalDecl Result(*this); 126 Result.Value.setInt(Type); 127 return Result; 128 } 129 130 GlobalDecl getWithDtorType(CXXDtorType Type) { 131 assert(isa<CXXDestructorDecl>(getDecl())); 132 GlobalDecl Result(*this); 133 Result.Value.setInt(Type); 134 return Result; 135 } 136 137 GlobalDecl getWithMultiVersionIndex(unsigned Index) { 138 assert(isa<FunctionDecl>(getDecl()) && 139 !isa<CXXConstructorDecl>(getDecl()) && 140 !isa<CXXDestructorDecl>(getDecl()) && 141 "Decl is not a plain FunctionDecl!"); 142 GlobalDecl Result(*this); 143 Result.MultiVersionIndex = Index; 144 return Result; 145 } 146 }; 147 148 } // namespace clang 149 150 namespace llvm { 151 152 template<> struct DenseMapInfo<clang::GlobalDecl> { 153 static inline clang::GlobalDecl getEmptyKey() { 154 return clang::GlobalDecl(); 155 } 156 157 static inline clang::GlobalDecl getTombstoneKey() { 158 return clang::GlobalDecl:: 159 getFromOpaquePtr(reinterpret_cast<void*>(-1)); 160 } 161 162 static unsigned getHashValue(clang::GlobalDecl GD) { 163 return DenseMapInfo<void*>::getHashValue(GD.getAsOpaquePtr()); 164 } 165 166 static bool isEqual(clang::GlobalDecl LHS, 167 clang::GlobalDecl RHS) { 168 return LHS == RHS; 169 } 170 }; 171 172 } // namespace llvm 173 174 #endif // LLVM_CLANG_AST_GLOBALDECL_H 175