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