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 
Init(const Decl * D)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;
GlobalDecl(const VarDecl * D)53   GlobalDecl(const VarDecl *D) { Init(D);}
54   GlobalDecl(const FunctionDecl *D, unsigned MVIndex = 0)
MultiVersionIndex(MVIndex)55       : MultiVersionIndex(MVIndex) {
56     Init(D);
57   }
GlobalDecl(const BlockDecl * D)58   GlobalDecl(const BlockDecl *D) { Init(D); }
GlobalDecl(const CapturedDecl * D)59   GlobalDecl(const CapturedDecl *D) { Init(D); }
GlobalDecl(const ObjCMethodDecl * D)60   GlobalDecl(const ObjCMethodDecl *D) { Init(D); }
GlobalDecl(const OMPDeclareReductionDecl * D)61   GlobalDecl(const OMPDeclareReductionDecl *D) { Init(D); }
GlobalDecl(const OMPDeclareMapperDecl * D)62   GlobalDecl(const OMPDeclareMapperDecl *D) { Init(D); }
GlobalDecl(const CXXConstructorDecl * D,CXXCtorType Type)63   GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type) : Value(D, Type) {}
GlobalDecl(const CXXDestructorDecl * D,CXXDtorType Type)64   GlobalDecl(const CXXDestructorDecl *D, CXXDtorType Type) : Value(D, Type) {}
GlobalDecl(const VarDecl * D,DynamicInitKind StubKind)65   GlobalDecl(const VarDecl *D, DynamicInitKind StubKind)
66       : Value(D, unsigned(StubKind)) {}
67 
getCanonicalDecl()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 
getDecl()77   const Decl *getDecl() const { return Value.getPointer(); }
78 
getCtorType()79   CXXCtorType getCtorType() const {
80     assert(isa<CXXConstructorDecl>(getDecl()) && "Decl is not a ctor!");
81     return static_cast<CXXCtorType>(Value.getInt());
82   }
83 
getDtorType()84   CXXDtorType getDtorType() const {
85     assert(isa<CXXDestructorDecl>(getDecl()) && "Decl is not a dtor!");
86     return static_cast<CXXDtorType>(Value.getInt());
87   }
88 
getDynamicInitKind()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 
getMultiVersionIndex()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 
getAsOpaquePtr()109   void *getAsOpaquePtr() const { return Value.getOpaqueValue(); }
110 
getFromOpaquePtr(void * P)111   static GlobalDecl getFromOpaquePtr(void *P) {
112     GlobalDecl GD;
113     GD.Value.setFromOpaqueValue(P);
114     return GD;
115   }
116 
getWithDecl(const Decl * D)117   GlobalDecl getWithDecl(const Decl *D) {
118     GlobalDecl Result(*this);
119     Result.Value.setPointer(D);
120     return Result;
121   }
122 
getWithCtorType(CXXCtorType Type)123   GlobalDecl getWithCtorType(CXXCtorType Type) {
124     assert(isa<CXXConstructorDecl>(getDecl()));
125     GlobalDecl Result(*this);
126     Result.Value.setInt(Type);
127     return Result;
128   }
129 
getWithDtorType(CXXDtorType Type)130   GlobalDecl getWithDtorType(CXXDtorType Type) {
131     assert(isa<CXXDestructorDecl>(getDecl()));
132     GlobalDecl Result(*this);
133     Result.Value.setInt(Type);
134     return Result;
135   }
136 
getWithMultiVersionIndex(unsigned Index)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