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