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 CapturedDecl *D) { Init(D); }
45  GlobalDecl(const ObjCMethodDecl *D) { Init(D); }
46
47  GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type)
48  : Value(D, Type) {}
49  GlobalDecl(const CXXDestructorDecl *D, CXXDtorType Type)
50  : Value(D, Type) {}
51
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
60  const Decl *getDecl() const { return Value.getPointer(); }
61
62  CXXCtorType getCtorType() const {
63    assert(isa<CXXConstructorDecl>(getDecl()) && "Decl is not a ctor!");
64    return static_cast<CXXCtorType>(Value.getInt());
65  }
66
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
76  void *getAsOpaquePtr() const { return Value.getOpaqueValue(); }
77
78  static GlobalDecl getFromOpaquePtr(void *P) {
79    GlobalDecl GD;
80    GD.Value.setFromOpaqueValue(P);
81    return GD;
82  }
83
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
93namespace 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