1 //===- GlobalDecl.h - Global declaration holder -----------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // A GlobalDecl can hold either a regular variable/function or a C++ ctor/dtor 11 // together with its type. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_CLANG_AST_GLOBALDECL_H 16 #define LLVM_CLANG_AST_GLOBALDECL_H 17 18 #include "clang/AST/DeclCXX.h" 19 #include "clang/AST/DeclObjC.h" 20 #include "clang/AST/DeclOpenMP.h" 21 #include "clang/Basic/ABI.h" 22 #include "clang/Basic/LLVM.h" 23 #include "llvm/ADT/DenseMapInfo.h" 24 #include "llvm/ADT/PointerIntPair.h" 25 #include "llvm/Support/Casting.h" 26 #include "llvm/Support/type_traits.h" 27 #include <cassert> 28 29 namespace clang { 30 31 /// GlobalDecl - represents a global declaration. This can either be a 32 /// CXXConstructorDecl and the constructor type (Base, Complete). 33 /// a CXXDestructorDecl and the destructor type (Base, Complete) or 34 /// a VarDecl, a FunctionDecl or a BlockDecl. 35 class GlobalDecl { 36 llvm::PointerIntPair<const Decl *, 2> Value; 37 unsigned MultiVersionIndex = 0; 38 Init(const Decl * D)39 void Init(const Decl *D) { 40 assert(!isa<CXXConstructorDecl>(D) && "Use other ctor with ctor decls!"); 41 assert(!isa<CXXDestructorDecl>(D) && "Use other ctor with dtor decls!"); 42 43 Value.setPointer(D); 44 } 45 46 public: 47 GlobalDecl() = default; GlobalDecl(const VarDecl * D)48 GlobalDecl(const VarDecl *D) { Init(D);} 49 GlobalDecl(const FunctionDecl *D, unsigned MVIndex = 0) MultiVersionIndex(MVIndex)50 : MultiVersionIndex(MVIndex) { 51 Init(D); 52 } GlobalDecl(const BlockDecl * D)53 GlobalDecl(const BlockDecl *D) { Init(D); } GlobalDecl(const CapturedDecl * D)54 GlobalDecl(const CapturedDecl *D) { Init(D); } GlobalDecl(const ObjCMethodDecl * D)55 GlobalDecl(const ObjCMethodDecl *D) { Init(D); } GlobalDecl(const OMPDeclareReductionDecl * D)56 GlobalDecl(const OMPDeclareReductionDecl *D) { Init(D); } GlobalDecl(const CXXConstructorDecl * D,CXXCtorType Type)57 GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type) : Value(D, Type) {} GlobalDecl(const CXXDestructorDecl * D,CXXDtorType Type)58 GlobalDecl(const CXXDestructorDecl *D, CXXDtorType Type) : Value(D, Type) {} 59 getCanonicalDecl()60 GlobalDecl getCanonicalDecl() const { 61 GlobalDecl CanonGD; 62 CanonGD.Value.setPointer(Value.getPointer()->getCanonicalDecl()); 63 CanonGD.Value.setInt(Value.getInt()); 64 CanonGD.MultiVersionIndex = MultiVersionIndex; 65 66 return CanonGD; 67 } 68 getDecl()69 const Decl *getDecl() const { return Value.getPointer(); } 70 getCtorType()71 CXXCtorType getCtorType() const { 72 assert(isa<CXXConstructorDecl>(getDecl()) && "Decl is not a ctor!"); 73 return static_cast<CXXCtorType>(Value.getInt()); 74 } 75 getDtorType()76 CXXDtorType getDtorType() const { 77 assert(isa<CXXDestructorDecl>(getDecl()) && "Decl is not a dtor!"); 78 return static_cast<CXXDtorType>(Value.getInt()); 79 } 80 getMultiVersionIndex()81 unsigned getMultiVersionIndex() const { 82 assert(isa<FunctionDecl>(getDecl()) && 83 !isa<CXXConstructorDecl>(getDecl()) && 84 !isa<CXXDestructorDecl>(getDecl()) && 85 "Decl is not a plain FunctionDecl!"); 86 return MultiVersionIndex; 87 } 88 89 friend bool operator==(const GlobalDecl &LHS, const GlobalDecl &RHS) { 90 return LHS.Value == RHS.Value && 91 LHS.MultiVersionIndex == RHS.MultiVersionIndex; 92 } 93 getAsOpaquePtr()94 void *getAsOpaquePtr() const { return Value.getOpaqueValue(); } 95 getFromOpaquePtr(void * P)96 static GlobalDecl getFromOpaquePtr(void *P) { 97 GlobalDecl GD; 98 GD.Value.setFromOpaqueValue(P); 99 return GD; 100 } 101 getWithDecl(const Decl * D)102 GlobalDecl getWithDecl(const Decl *D) { 103 GlobalDecl Result(*this); 104 Result.Value.setPointer(D); 105 return Result; 106 } 107 getWithMultiVersionIndex(unsigned Index)108 GlobalDecl getWithMultiVersionIndex(unsigned Index) { 109 assert(isa<FunctionDecl>(getDecl()) && 110 !isa<CXXConstructorDecl>(getDecl()) && 111 !isa<CXXDestructorDecl>(getDecl()) && 112 "Decl is not a plain FunctionDecl!"); 113 GlobalDecl Result(*this); 114 Result.MultiVersionIndex = Index; 115 return Result; 116 } 117 }; 118 119 } // namespace clang 120 121 namespace llvm { 122 123 template<> struct DenseMapInfo<clang::GlobalDecl> { 124 static inline clang::GlobalDecl getEmptyKey() { 125 return clang::GlobalDecl(); 126 } 127 128 static inline clang::GlobalDecl getTombstoneKey() { 129 return clang::GlobalDecl:: 130 getFromOpaquePtr(reinterpret_cast<void*>(-1)); 131 } 132 133 static unsigned getHashValue(clang::GlobalDecl GD) { 134 return DenseMapInfo<void*>::getHashValue(GD.getAsOpaquePtr()); 135 } 136 137 static bool isEqual(clang::GlobalDecl LHS, 138 clang::GlobalDecl RHS) { 139 return LHS == RHS; 140 } 141 }; 142 143 // GlobalDecl isn't *technically* a POD type. However, its copy constructor, 144 // copy assignment operator, and destructor are all trivial. 145 template <> 146 struct isPodLike<clang::GlobalDecl> { 147 static const bool value = true; 148 }; 149 150 } // namespace llvm 151 152 #endif // LLVM_CLANG_AST_GLOBALDECL_H 153