DeclGroup.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- DeclGroup.h - Classes for representing groups of Decls ---*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // This file defines the DeclGroup, DeclGroupRef, and OwningDeclGroup classes.
  15. //
  16. //===----------------------------------------------------------------------===//
  17. #ifndef LLVM_CLANG_AST_DECLGROUP_H
  18. #define LLVM_CLANG_AST_DECLGROUP_H
  19. #include "llvm/Support/TrailingObjects.h"
  20. #include <cassert>
  21. #include <cstdint>
  22. namespace clang {
  23. class ASTContext;
  24. class Decl;
  25. class DeclGroup final : private llvm::TrailingObjects<DeclGroup, Decl *> {
  26. // FIXME: Include a TypeSpecifier object.
  27. unsigned NumDecls = 0;
  28. private:
  29. DeclGroup() = default;
  30. DeclGroup(unsigned numdecls, Decl** decls);
  31. public:
  32. friend TrailingObjects;
  33. static DeclGroup *Create(ASTContext &C, Decl **Decls, unsigned NumDecls);
  34. unsigned size() const { return NumDecls; }
  35. Decl*& operator[](unsigned i) {
  36. assert (i < NumDecls && "Out-of-bounds access.");
  37. return getTrailingObjects<Decl *>()[i];
  38. }
  39. Decl* const& operator[](unsigned i) const {
  40. assert (i < NumDecls && "Out-of-bounds access.");
  41. return getTrailingObjects<Decl *>()[i];
  42. }
  43. };
  44. class DeclGroupRef {
  45. // Note this is not a PointerIntPair because we need the address of the
  46. // non-group case to be valid as a Decl** for iteration.
  47. enum Kind { SingleDeclKind=0x0, DeclGroupKind=0x1, Mask=0x1 };
  48. Decl* D = nullptr;
  49. Kind getKind() const {
  50. return (Kind) (reinterpret_cast<uintptr_t>(D) & Mask);
  51. }
  52. public:
  53. DeclGroupRef() = default;
  54. explicit DeclGroupRef(Decl* d) : D(d) {}
  55. explicit DeclGroupRef(DeclGroup* dg)
  56. : D((Decl*) (reinterpret_cast<uintptr_t>(dg) | DeclGroupKind)) {}
  57. static DeclGroupRef Create(ASTContext &C, Decl **Decls, unsigned NumDecls) {
  58. if (NumDecls == 0)
  59. return DeclGroupRef();
  60. if (NumDecls == 1)
  61. return DeclGroupRef(Decls[0]);
  62. return DeclGroupRef(DeclGroup::Create(C, Decls, NumDecls));
  63. }
  64. using iterator = Decl **;
  65. using const_iterator = Decl * const *;
  66. bool isNull() const { return D == nullptr; }
  67. bool isSingleDecl() const { return getKind() == SingleDeclKind; }
  68. bool isDeclGroup() const { return getKind() == DeclGroupKind; }
  69. Decl *getSingleDecl() {
  70. assert(isSingleDecl() && "Isn't a single decl");
  71. return D;
  72. }
  73. const Decl *getSingleDecl() const {
  74. return const_cast<DeclGroupRef*>(this)->getSingleDecl();
  75. }
  76. DeclGroup &getDeclGroup() {
  77. assert(isDeclGroup() && "Isn't a declgroup");
  78. return *((DeclGroup*)(reinterpret_cast<uintptr_t>(D) & ~Mask));
  79. }
  80. const DeclGroup &getDeclGroup() const {
  81. return const_cast<DeclGroupRef*>(this)->getDeclGroup();
  82. }
  83. iterator begin() {
  84. if (isSingleDecl())
  85. return D ? &D : nullptr;
  86. return &getDeclGroup()[0];
  87. }
  88. iterator end() {
  89. if (isSingleDecl())
  90. return D ? &D+1 : nullptr;
  91. DeclGroup &G = getDeclGroup();
  92. return &G[0] + G.size();
  93. }
  94. const_iterator begin() const {
  95. if (isSingleDecl())
  96. return D ? &D : nullptr;
  97. return &getDeclGroup()[0];
  98. }
  99. const_iterator end() const {
  100. if (isSingleDecl())
  101. return D ? &D+1 : nullptr;
  102. const DeclGroup &G = getDeclGroup();
  103. return &G[0] + G.size();
  104. }
  105. void *getAsOpaquePtr() const { return D; }
  106. static DeclGroupRef getFromOpaquePtr(void *Ptr) {
  107. DeclGroupRef X;
  108. X.D = static_cast<Decl*>(Ptr);
  109. return X;
  110. }
  111. };
  112. } // namespace clang
  113. namespace llvm {
  114. // DeclGroupRef is "like a pointer", implement PointerLikeTypeTraits.
  115. template <typename T>
  116. struct PointerLikeTypeTraits;
  117. template <>
  118. struct PointerLikeTypeTraits<clang::DeclGroupRef> {
  119. static inline void *getAsVoidPointer(clang::DeclGroupRef P) {
  120. return P.getAsOpaquePtr();
  121. }
  122. static inline clang::DeclGroupRef getFromVoidPointer(void *P) {
  123. return clang::DeclGroupRef::getFromOpaquePtr(P);
  124. }
  125. static constexpr int NumLowBitsAvailable = 0;
  126. };
  127. } // namespace llvm
  128. #endif // LLVM_CLANG_AST_DECLGROUP_H
  129. #ifdef __GNUC__
  130. #pragma GCC diagnostic pop
  131. #endif