1224135Sdim//===--- GlobalDecl.h - Global declaration holder ---------------*- C++ -*-===//
2224135Sdim//
3224135Sdim//                     The LLVM Compiler Infrastructure
4224135Sdim//
5224135Sdim// This file is distributed under the University of Illinois Open Source
6224135Sdim// License. See LICENSE.TXT for details.
7224135Sdim//
8224135Sdim//===----------------------------------------------------------------------===//
9224135Sdim//
10224135Sdim// A GlobalDecl can hold either a regular variable/function or a C++ ctor/dtor
11224135Sdim// together with its type.
12224135Sdim//
13224135Sdim//===----------------------------------------------------------------------===//
14224135Sdim
15224135Sdim#ifndef LLVM_CLANG_AST_GLOBALDECL_H
16224135Sdim#define LLVM_CLANG_AST_GLOBALDECL_H
17224135Sdim
18224135Sdim#include "clang/AST/DeclCXX.h"
19224135Sdim#include "clang/AST/DeclObjC.h"
20224135Sdim#include "clang/Basic/ABI.h"
21224135Sdim
22224135Sdimnamespace clang {
23224135Sdim
24224135Sdim/// GlobalDecl - represents a global declaration. This can either be a
25224135Sdim/// CXXConstructorDecl and the constructor type (Base, Complete).
26224135Sdim/// a CXXDestructorDecl and the destructor type (Base, Complete) or
27224135Sdim/// a VarDecl, a FunctionDecl or a BlockDecl.
28224135Sdimclass GlobalDecl {
29224135Sdim  llvm::PointerIntPair<const Decl*, 2> Value;
30224135Sdim
31224135Sdim  void Init(const Decl *D) {
32224135Sdim    assert(!isa<CXXConstructorDecl>(D) && "Use other ctor with ctor decls!");
33224135Sdim    assert(!isa<CXXDestructorDecl>(D) && "Use other ctor with dtor decls!");
34224135Sdim
35224135Sdim    Value.setPointer(D);
36224135Sdim  }
37224135Sdim
38224135Sdimpublic:
39224135Sdim  GlobalDecl() {}
40224135Sdim
41224135Sdim  GlobalDecl(const VarDecl *D) { Init(D);}
42224135Sdim  GlobalDecl(const FunctionDecl *D) { Init(D); }
43224135Sdim  GlobalDecl(const BlockDecl *D) { Init(D); }
44263508Sdim  GlobalDecl(const CapturedDecl *D) { Init(D); }
45224135Sdim  GlobalDecl(const ObjCMethodDecl *D) { Init(D); }
46224135Sdim
47224135Sdim  GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type)
48224135Sdim  : Value(D, Type) {}
49224135Sdim  GlobalDecl(const CXXDestructorDecl *D, CXXDtorType Type)
50224135Sdim  : Value(D, Type) {}
51224135Sdim
52224135Sdim  GlobalDecl getCanonicalDecl() const {
53224135Sdim    GlobalDecl CanonGD;
54224135Sdim    CanonGD.Value.setPointer(Value.getPointer()->getCanonicalDecl());
55224135Sdim    CanonGD.Value.setInt(Value.getInt());
56224135Sdim
57224135Sdim    return CanonGD;
58224135Sdim  }
59224135Sdim
60224135Sdim  const Decl *getDecl() const { return Value.getPointer(); }
61224135Sdim
62224135Sdim  CXXCtorType getCtorType() const {
63224135Sdim    assert(isa<CXXConstructorDecl>(getDecl()) && "Decl is not a ctor!");
64224135Sdim    return static_cast<CXXCtorType>(Value.getInt());
65224135Sdim  }
66224135Sdim
67224135Sdim  CXXDtorType getDtorType() const {
68224135Sdim    assert(isa<CXXDestructorDecl>(getDecl()) && "Decl is not a dtor!");
69224135Sdim    return static_cast<CXXDtorType>(Value.getInt());
70224135Sdim  }
71224135Sdim
72224135Sdim  friend bool operator==(const GlobalDecl &LHS, const GlobalDecl &RHS) {
73224135Sdim    return LHS.Value == RHS.Value;
74224135Sdim  }
75224135Sdim
76224135Sdim  void *getAsOpaquePtr() const { return Value.getOpaqueValue(); }
77224135Sdim
78224135Sdim  static GlobalDecl getFromOpaquePtr(void *P) {
79224135Sdim    GlobalDecl GD;
80224135Sdim    GD.Value.setFromOpaqueValue(P);
81224135Sdim    return GD;
82224135Sdim  }
83224135Sdim
84224135Sdim  GlobalDecl getWithDecl(const Decl *D) {
85224135Sdim    GlobalDecl Result(*this);
86224135Sdim    Result.Value.setPointer(D);
87224135Sdim    return Result;
88224135Sdim  }
89224135Sdim};
90224135Sdim
91224135Sdim} // end namespace clang
92224135Sdim
93224135Sdimnamespace llvm {
94224135Sdim  template<class> struct DenseMapInfo;
95224135Sdim
96224135Sdim  template<> struct DenseMapInfo<clang::GlobalDecl> {
97224135Sdim    static inline clang::GlobalDecl getEmptyKey() {
98224135Sdim      return clang::GlobalDecl();
99224135Sdim    }
100224135Sdim
101224135Sdim    static inline clang::GlobalDecl getTombstoneKey() {
102224135Sdim      return clang::GlobalDecl::
103224135Sdim        getFromOpaquePtr(reinterpret_cast<void*>(-1));
104224135Sdim    }
105224135Sdim
106224135Sdim    static unsigned getHashValue(clang::GlobalDecl GD) {
107224135Sdim      return DenseMapInfo<void*>::getHashValue(GD.getAsOpaquePtr());
108224135Sdim    }
109224135Sdim
110224135Sdim    static bool isEqual(clang::GlobalDecl LHS,
111224135Sdim                        clang::GlobalDecl RHS) {
112224135Sdim      return LHS == RHS;
113224135Sdim    }
114224135Sdim
115224135Sdim  };
116224135Sdim
117224135Sdim  // GlobalDecl isn't *technically* a POD type. However, its copy constructor,
118224135Sdim  // copy assignment operator, and destructor are all trivial.
119224135Sdim  template <>
120224135Sdim  struct isPodLike<clang::GlobalDecl> {
121224135Sdim    static const bool value = true;
122224135Sdim  };
123224135Sdim} // end namespace llvm
124224135Sdim
125224135Sdim#endif
126