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