DependentDiagnostic.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //==- DependentDiagnostic.h - Dependently-generated diagnostics --*- 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 interfaces for diagnostics which may or may
  15. // fire based on how a template is instantiated.
  16. //
  17. // At the moment, the only consumer of this interface is access
  18. // control.
  19. //
  20. //===----------------------------------------------------------------------===//
  21. #ifndef LLVM_CLANG_AST_DEPENDENTDIAGNOSTIC_H
  22. #define LLVM_CLANG_AST_DEPENDENTDIAGNOSTIC_H
  23. #include "clang/AST/DeclBase.h"
  24. #include "clang/AST/DeclContextInternals.h"
  25. #include "clang/AST/Type.h"
  26. #include "clang/Basic/PartialDiagnostic.h"
  27. #include "clang/Basic/SourceLocation.h"
  28. #include "clang/Basic/Specifiers.h"
  29. #include <cassert>
  30. #include <iterator>
  31. namespace clang {
  32. class ASTContext;
  33. class CXXRecordDecl;
  34. class NamedDecl;
  35. /// A dependently-generated diagnostic.
  36. class DependentDiagnostic {
  37. public:
  38. enum AccessNonce { Access = 0 };
  39. static DependentDiagnostic *Create(ASTContext &Context,
  40. DeclContext *Parent,
  41. AccessNonce _,
  42. SourceLocation Loc,
  43. bool IsMemberAccess,
  44. AccessSpecifier AS,
  45. NamedDecl *TargetDecl,
  46. CXXRecordDecl *NamingClass,
  47. QualType BaseObjectType,
  48. const PartialDiagnostic &PDiag) {
  49. DependentDiagnostic *DD = Create(Context, Parent, PDiag);
  50. DD->AccessData.Loc = Loc;
  51. DD->AccessData.IsMember = IsMemberAccess;
  52. DD->AccessData.Access = AS;
  53. DD->AccessData.TargetDecl = TargetDecl;
  54. DD->AccessData.NamingClass = NamingClass;
  55. DD->AccessData.BaseObjectType = BaseObjectType.getAsOpaquePtr();
  56. return DD;
  57. }
  58. unsigned getKind() const {
  59. return Access;
  60. }
  61. bool isAccessToMember() const {
  62. assert(getKind() == Access);
  63. return AccessData.IsMember;
  64. }
  65. AccessSpecifier getAccess() const {
  66. assert(getKind() == Access);
  67. return AccessSpecifier(AccessData.Access);
  68. }
  69. SourceLocation getAccessLoc() const {
  70. assert(getKind() == Access);
  71. return AccessData.Loc;
  72. }
  73. NamedDecl *getAccessTarget() const {
  74. assert(getKind() == Access);
  75. return AccessData.TargetDecl;
  76. }
  77. NamedDecl *getAccessNamingClass() const {
  78. assert(getKind() == Access);
  79. return AccessData.NamingClass;
  80. }
  81. QualType getAccessBaseObjectType() const {
  82. assert(getKind() == Access);
  83. return QualType::getFromOpaquePtr(AccessData.BaseObjectType);
  84. }
  85. const PartialDiagnostic &getDiagnostic() const {
  86. return Diag;
  87. }
  88. private:
  89. friend class DeclContext::ddiag_iterator;
  90. friend class DependentStoredDeclsMap;
  91. DependentDiagnostic(const PartialDiagnostic &PDiag,
  92. DiagnosticStorage *Storage)
  93. : Diag(PDiag, Storage) {}
  94. static DependentDiagnostic *Create(ASTContext &Context,
  95. DeclContext *Parent,
  96. const PartialDiagnostic &PDiag);
  97. DependentDiagnostic *NextDiagnostic;
  98. PartialDiagnostic Diag;
  99. struct {
  100. SourceLocation Loc;
  101. unsigned Access : 2;
  102. unsigned IsMember : 1;
  103. NamedDecl *TargetDecl;
  104. CXXRecordDecl *NamingClass;
  105. void *BaseObjectType;
  106. } AccessData;
  107. };
  108. /// An iterator over the dependent diagnostics in a dependent context.
  109. class DeclContext::ddiag_iterator {
  110. public:
  111. ddiag_iterator() = default;
  112. explicit ddiag_iterator(DependentDiagnostic *Ptr) : Ptr(Ptr) {}
  113. using value_type = DependentDiagnostic *;
  114. using reference = DependentDiagnostic *;
  115. using pointer = DependentDiagnostic *;
  116. using difference_type = int;
  117. using iterator_category = std::forward_iterator_tag;
  118. reference operator*() const { return Ptr; }
  119. ddiag_iterator &operator++() {
  120. assert(Ptr && "attempt to increment past end of diag list");
  121. Ptr = Ptr->NextDiagnostic;
  122. return *this;
  123. }
  124. ddiag_iterator operator++(int) {
  125. ddiag_iterator tmp = *this;
  126. ++*this;
  127. return tmp;
  128. }
  129. bool operator==(ddiag_iterator Other) const {
  130. return Ptr == Other.Ptr;
  131. }
  132. bool operator!=(ddiag_iterator Other) const {
  133. return Ptr != Other.Ptr;
  134. }
  135. ddiag_iterator &operator+=(difference_type N) {
  136. assert(N >= 0 && "cannot rewind a DeclContext::ddiag_iterator");
  137. while (N--)
  138. ++*this;
  139. return *this;
  140. }
  141. ddiag_iterator operator+(difference_type N) const {
  142. ddiag_iterator tmp = *this;
  143. tmp += N;
  144. return tmp;
  145. }
  146. private:
  147. DependentDiagnostic *Ptr = nullptr;
  148. };
  149. inline DeclContext::ddiag_range DeclContext::ddiags() const {
  150. assert(isDependentContext()
  151. && "cannot iterate dependent diagnostics of non-dependent context");
  152. const DependentStoredDeclsMap *Map
  153. = static_cast<DependentStoredDeclsMap*>(getPrimaryContext()->getLookupPtr());
  154. if (!Map)
  155. // Return an empty range using the always-end default constructor.
  156. return ddiag_range(ddiag_iterator(), ddiag_iterator());
  157. return ddiag_range(ddiag_iterator(Map->FirstDiagnostic), ddiag_iterator());
  158. }
  159. } // namespace clang
  160. #endif // LLVM_CLANG_AST_DEPENDENTDIAGNOSTIC_H
  161. #ifdef __GNUC__
  162. #pragma GCC diagnostic pop
  163. #endif