xref: /freebsd/contrib/llvm-project/clang/include/clang/AST/DeclAccessPair.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===--- DeclAccessPair.h - A decl bundled with its path access -*- 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 //  This file defines the DeclAccessPair class, which provides an
10 //  efficient representation of a pair of a NamedDecl* and an
11 //  AccessSpecifier.  Generally the access specifier gives the
12 //  natural access of a declaration when named in a class, as
13 //  defined in C++ [class.access.base]p1.
14 //
15 //===----------------------------------------------------------------------===//
16 
17 #ifndef LLVM_CLANG_AST_DECLACCESSPAIR_H
18 #define LLVM_CLANG_AST_DECLACCESSPAIR_H
19 
20 #include "clang/Basic/Specifiers.h"
21 #include "llvm/Support/DataTypes.h"
22 #include "llvm/Support/Endian.h"
23 
24 namespace clang {
25 
26 class NamedDecl;
27 
28 /// A POD class for pairing a NamedDecl* with an access specifier.
29 /// Can be put into unions.
30 class DeclAccessPair {
31   /// Use the lower 2 bit to store AccessSpecifier. Use the higher
32   /// 61 bit to store the pointer to a NamedDecl or the DeclID to
33   /// a NamedDecl. If the 3rd bit is set, storing the DeclID, otherwise
34   /// storing the pointer.
35   llvm::support::detail::packed_endian_specific_integral<
36       uint64_t, llvm::endianness::native, alignof(void *)>
37       Ptr;
38 
39   enum { ASMask = 0x3, Mask = 0x7 };
40 
isDeclID()41   bool isDeclID() const { return (Ptr >> 2) & 0x1; }
42 
43 public:
make(NamedDecl * D,AccessSpecifier AS)44   static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS) {
45     DeclAccessPair p;
46     p.set(D, AS);
47     return p;
48   }
49 
makeLazy(uint64_t ID,AccessSpecifier AS)50   static DeclAccessPair makeLazy(uint64_t ID, AccessSpecifier AS) {
51     DeclAccessPair p;
52     p.Ptr = (ID << 3) | (0x1 << 2) | uint64_t(AS);
53     return p;
54   }
55 
getDeclID()56   uint64_t getDeclID() const {
57     assert(isDeclID());
58     return (~Mask & Ptr) >> 3;
59   }
60 
getDecl()61   NamedDecl *getDecl() const {
62     assert(!isDeclID());
63     return reinterpret_cast<NamedDecl*>(~Mask & Ptr);
64   }
getAccess()65   AccessSpecifier getAccess() const { return AccessSpecifier(ASMask & Ptr); }
66 
setDecl(NamedDecl * D)67   void setDecl(NamedDecl *D) {
68     set(D, getAccess());
69   }
setAccess(AccessSpecifier AS)70   void setAccess(AccessSpecifier AS) {
71     set(getDecl(), AS);
72   }
set(NamedDecl * D,AccessSpecifier AS)73   void set(NamedDecl *D, AccessSpecifier AS) {
74     Ptr = uint64_t(AS) | reinterpret_cast<uint64_t>(D);
75   }
76 
77   operator NamedDecl*() const { return getDecl(); }
78   NamedDecl *operator->() const { return getDecl(); }
79 };
80 
81 // Make sure DeclAccessPair is pointer-aligned types.
82 static_assert(alignof(DeclAccessPair) == alignof(void *));
83 // Make sure DeclAccessPair is still POD.
84 static_assert(std::is_standard_layout_v<DeclAccessPair> &&
85               std::is_trivial_v<DeclAccessPair>);
86 }
87 
88 #endif
89