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