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/Basic/ABI.h"
21 
22 namespace clang {
23 
24 /// GlobalDecl - represents a global declaration. This can either be a
25 /// CXXConstructorDecl and the constructor type (Base, Complete).
26 /// a CXXDestructorDecl and the destructor type (Base, Complete) or
27 /// a VarDecl, a FunctionDecl or a BlockDecl.
28 class GlobalDecl {
29   llvm::PointerIntPair<const Decl*, 2> Value;
30 
Init(const Decl * D)31   void Init(const Decl *D) {
32     assert(!isa<CXXConstructorDecl>(D) && "Use other ctor with ctor decls!");
33     assert(!isa<CXXDestructorDecl>(D) && "Use other ctor with dtor decls!");
34 
35     Value.setPointer(D);
36   }
37 
38 public:
GlobalDecl()39   GlobalDecl() {}
40 
GlobalDecl(const VarDecl * D)41   GlobalDecl(const VarDecl *D) { Init(D);}
GlobalDecl(const FunctionDecl * D)42   GlobalDecl(const FunctionDecl *D) { Init(D); }
GlobalDecl(const BlockDecl * D)43   GlobalDecl(const BlockDecl *D) { Init(D); }
GlobalDecl(const CapturedDecl * D)44   GlobalDecl(const CapturedDecl *D) { Init(D); }
GlobalDecl(const ObjCMethodDecl * D)45   GlobalDecl(const ObjCMethodDecl *D) { Init(D); }
46 
GlobalDecl(const CXXConstructorDecl * D,CXXCtorType Type)47   GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type)
48   : Value(D, Type) {}
GlobalDecl(const CXXDestructorDecl * D,CXXDtorType Type)49   GlobalDecl(const CXXDestructorDecl *D, CXXDtorType Type)
50   : Value(D, Type) {}
51 
getCanonicalDecl()52   GlobalDecl getCanonicalDecl() const {
53     GlobalDecl CanonGD;
54     CanonGD.Value.setPointer(Value.getPointer()->getCanonicalDecl());
55     CanonGD.Value.setInt(Value.getInt());
56 
57     return CanonGD;
58   }
59 
getDecl()60   const Decl *getDecl() const { return Value.getPointer(); }
61 
getCtorType()62   CXXCtorType getCtorType() const {
63     assert(isa<CXXConstructorDecl>(getDecl()) && "Decl is not a ctor!");
64     return static_cast<CXXCtorType>(Value.getInt());
65   }
66 
getDtorType()67   CXXDtorType getDtorType() const {
68     assert(isa<CXXDestructorDecl>(getDecl()) && "Decl is not a dtor!");
69     return static_cast<CXXDtorType>(Value.getInt());
70   }
71 
72   friend bool operator==(const GlobalDecl &LHS, const GlobalDecl &RHS) {
73     return LHS.Value == RHS.Value;
74   }
75 
getAsOpaquePtr()76   void *getAsOpaquePtr() const { return Value.getOpaqueValue(); }
77 
getFromOpaquePtr(void * P)78   static GlobalDecl getFromOpaquePtr(void *P) {
79     GlobalDecl GD;
80     GD.Value.setFromOpaqueValue(P);
81     return GD;
82   }
83 
getWithDecl(const Decl * D)84   GlobalDecl getWithDecl(const Decl *D) {
85     GlobalDecl Result(*this);
86     Result.Value.setPointer(D);
87     return Result;
88   }
89 };
90 
91 } // end namespace clang
92 
93 namespace llvm {
94   template<class> struct DenseMapInfo;
95 
96   template<> struct DenseMapInfo<clang::GlobalDecl> {
97     static inline clang::GlobalDecl getEmptyKey() {
98       return clang::GlobalDecl();
99     }
100 
101     static inline clang::GlobalDecl getTombstoneKey() {
102       return clang::GlobalDecl::
103         getFromOpaquePtr(reinterpret_cast<void*>(-1));
104     }
105 
106     static unsigned getHashValue(clang::GlobalDecl GD) {
107       return DenseMapInfo<void*>::getHashValue(GD.getAsOpaquePtr());
108     }
109 
110     static bool isEqual(clang::GlobalDecl LHS,
111                         clang::GlobalDecl RHS) {
112       return LHS == RHS;
113     }
114 
115   };
116 
117   // GlobalDecl isn't *technically* a POD type. However, its copy constructor,
118   // copy assignment operator, and destructor are all trivial.
119   template <>
120   struct isPodLike<clang::GlobalDecl> {
121     static const bool value = true;
122   };
123 } // end namespace llvm
124 
125 #endif
126