1327952Sdim//===- GlobalDecl.h - Global declaration holder -----------------*- C++ -*-===//
2224135Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6224135Sdim//
7224135Sdim//===----------------------------------------------------------------------===//
8224135Sdim//
9224135Sdim// A GlobalDecl can hold either a regular variable/function or a C++ ctor/dtor
10224135Sdim// together with its type.
11224135Sdim//
12224135Sdim//===----------------------------------------------------------------------===//
13224135Sdim
14224135Sdim#ifndef LLVM_CLANG_AST_GLOBALDECL_H
15224135Sdim#define LLVM_CLANG_AST_GLOBALDECL_H
16224135Sdim
17224135Sdim#include "clang/AST/DeclCXX.h"
18224135Sdim#include "clang/AST/DeclObjC.h"
19309124Sdim#include "clang/AST/DeclOpenMP.h"
20224135Sdim#include "clang/Basic/ABI.h"
21327952Sdim#include "clang/Basic/LLVM.h"
22327952Sdim#include "llvm/ADT/DenseMapInfo.h"
23327952Sdim#include "llvm/ADT/PointerIntPair.h"
24327952Sdim#include "llvm/Support/Casting.h"
25327952Sdim#include "llvm/Support/type_traits.h"
26327952Sdim#include <cassert>
27224135Sdim
28224135Sdimnamespace clang {
29224135Sdim
30353358Sdimenum class DynamicInitKind : unsigned {
31353358Sdim  NoStub = 0,
32353358Sdim  Initializer,
33353358Sdim  AtExit,
34353358Sdim};
35353358Sdim
36224135Sdim/// GlobalDecl - represents a global declaration. This can either be a
37224135Sdim/// CXXConstructorDecl and the constructor type (Base, Complete).
38224135Sdim/// a CXXDestructorDecl and the destructor type (Base, Complete) or
39224135Sdim/// a VarDecl, a FunctionDecl or a BlockDecl.
40224135Sdimclass GlobalDecl {
41327952Sdim  llvm::PointerIntPair<const Decl *, 2> Value;
42344779Sdim  unsigned MultiVersionIndex = 0;
43224135Sdim
44224135Sdim  void Init(const Decl *D) {
45224135Sdim    assert(!isa<CXXConstructorDecl>(D) && "Use other ctor with ctor decls!");
46224135Sdim    assert(!isa<CXXDestructorDecl>(D) && "Use other ctor with dtor decls!");
47224135Sdim
48224135Sdim    Value.setPointer(D);
49224135Sdim  }
50224135Sdim
51224135Sdimpublic:
52327952Sdim  GlobalDecl() = default;
53224135Sdim  GlobalDecl(const VarDecl *D) { Init(D);}
54344779Sdim  GlobalDecl(const FunctionDecl *D, unsigned MVIndex = 0)
55344779Sdim      : MultiVersionIndex(MVIndex) {
56344779Sdim    Init(D);
57344779Sdim  }
58224135Sdim  GlobalDecl(const BlockDecl *D) { Init(D); }
59261991Sdim  GlobalDecl(const CapturedDecl *D) { Init(D); }
60224135Sdim  GlobalDecl(const ObjCMethodDecl *D) { Init(D); }
61309124Sdim  GlobalDecl(const OMPDeclareReductionDecl *D) { Init(D); }
62360784Sdim  GlobalDecl(const OMPDeclareMapperDecl *D) { Init(D); }
63327952Sdim  GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type) : Value(D, Type) {}
64327952Sdim  GlobalDecl(const CXXDestructorDecl *D, CXXDtorType Type) : Value(D, Type) {}
65353358Sdim  GlobalDecl(const VarDecl *D, DynamicInitKind StubKind)
66353358Sdim      : Value(D, unsigned(StubKind)) {}
67224135Sdim
68224135Sdim  GlobalDecl getCanonicalDecl() const {
69224135Sdim    GlobalDecl CanonGD;
70224135Sdim    CanonGD.Value.setPointer(Value.getPointer()->getCanonicalDecl());
71224135Sdim    CanonGD.Value.setInt(Value.getInt());
72344779Sdim    CanonGD.MultiVersionIndex = MultiVersionIndex;
73341825Sdim
74224135Sdim    return CanonGD;
75224135Sdim  }
76224135Sdim
77224135Sdim  const Decl *getDecl() const { return Value.getPointer(); }
78224135Sdim
79224135Sdim  CXXCtorType getCtorType() const {
80224135Sdim    assert(isa<CXXConstructorDecl>(getDecl()) && "Decl is not a ctor!");
81224135Sdim    return static_cast<CXXCtorType>(Value.getInt());
82224135Sdim  }
83224135Sdim
84224135Sdim  CXXDtorType getDtorType() const {
85224135Sdim    assert(isa<CXXDestructorDecl>(getDecl()) && "Decl is not a dtor!");
86224135Sdim    return static_cast<CXXDtorType>(Value.getInt());
87224135Sdim  }
88341825Sdim
89353358Sdim  DynamicInitKind getDynamicInitKind() const {
90353358Sdim    assert(isa<VarDecl>(getDecl()) &&
91353358Sdim           cast<VarDecl>(getDecl())->hasGlobalStorage() &&
92353358Sdim           "Decl is not a global variable!");
93353358Sdim    return static_cast<DynamicInitKind>(Value.getInt());
94353358Sdim  }
95353358Sdim
96344779Sdim  unsigned getMultiVersionIndex() const {
97344779Sdim    assert(isa<FunctionDecl>(getDecl()) &&
98344779Sdim           !isa<CXXConstructorDecl>(getDecl()) &&
99344779Sdim           !isa<CXXDestructorDecl>(getDecl()) &&
100344779Sdim           "Decl is not a plain FunctionDecl!");
101344779Sdim    return MultiVersionIndex;
102344779Sdim  }
103344779Sdim
104224135Sdim  friend bool operator==(const GlobalDecl &LHS, const GlobalDecl &RHS) {
105344779Sdim    return LHS.Value == RHS.Value &&
106344779Sdim           LHS.MultiVersionIndex == RHS.MultiVersionIndex;
107224135Sdim  }
108341825Sdim
109224135Sdim  void *getAsOpaquePtr() const { return Value.getOpaqueValue(); }
110224135Sdim
111224135Sdim  static GlobalDecl getFromOpaquePtr(void *P) {
112224135Sdim    GlobalDecl GD;
113224135Sdim    GD.Value.setFromOpaqueValue(P);
114224135Sdim    return GD;
115224135Sdim  }
116341825Sdim
117224135Sdim  GlobalDecl getWithDecl(const Decl *D) {
118224135Sdim    GlobalDecl Result(*this);
119224135Sdim    Result.Value.setPointer(D);
120224135Sdim    return Result;
121224135Sdim  }
122344779Sdim
123353358Sdim  GlobalDecl getWithCtorType(CXXCtorType Type) {
124353358Sdim    assert(isa<CXXConstructorDecl>(getDecl()));
125353358Sdim    GlobalDecl Result(*this);
126353358Sdim    Result.Value.setInt(Type);
127353358Sdim    return Result;
128353358Sdim  }
129353358Sdim
130353358Sdim  GlobalDecl getWithDtorType(CXXDtorType Type) {
131353358Sdim    assert(isa<CXXDestructorDecl>(getDecl()));
132353358Sdim    GlobalDecl Result(*this);
133353358Sdim    Result.Value.setInt(Type);
134353358Sdim    return Result;
135353358Sdim  }
136353358Sdim
137344779Sdim  GlobalDecl getWithMultiVersionIndex(unsigned Index) {
138344779Sdim    assert(isa<FunctionDecl>(getDecl()) &&
139344779Sdim           !isa<CXXConstructorDecl>(getDecl()) &&
140344779Sdim           !isa<CXXDestructorDecl>(getDecl()) &&
141344779Sdim           "Decl is not a plain FunctionDecl!");
142344779Sdim    GlobalDecl Result(*this);
143344779Sdim    Result.MultiVersionIndex = Index;
144344779Sdim    return Result;
145344779Sdim  }
146224135Sdim};
147224135Sdim
148327952Sdim} // namespace clang
149224135Sdim
150224135Sdimnamespace llvm {
151224135Sdim
152224135Sdim  template<> struct DenseMapInfo<clang::GlobalDecl> {
153224135Sdim    static inline clang::GlobalDecl getEmptyKey() {
154224135Sdim      return clang::GlobalDecl();
155224135Sdim    }
156341825Sdim
157224135Sdim    static inline clang::GlobalDecl getTombstoneKey() {
158224135Sdim      return clang::GlobalDecl::
159224135Sdim        getFromOpaquePtr(reinterpret_cast<void*>(-1));
160224135Sdim    }
161224135Sdim
162224135Sdim    static unsigned getHashValue(clang::GlobalDecl GD) {
163224135Sdim      return DenseMapInfo<void*>::getHashValue(GD.getAsOpaquePtr());
164224135Sdim    }
165341825Sdim
166341825Sdim    static bool isEqual(clang::GlobalDecl LHS,
167224135Sdim                        clang::GlobalDecl RHS) {
168224135Sdim      return LHS == RHS;
169224135Sdim    }
170224135Sdim  };
171341825Sdim
172327952Sdim} // namespace llvm
173327952Sdim
174327952Sdim#endif // LLVM_CLANG_AST_GLOBALDECL_H
175