Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:34

0001 //==- DependentDiagnostic.h - Dependently-generated diagnostics --*- C++ -*-==//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 //  This file defines interfaces for diagnostics which may or may
0010 //  fire based on how a template is instantiated.
0011 //
0012 //  At the moment, the only consumer of this interface is access
0013 //  control.
0014 //
0015 //===----------------------------------------------------------------------===//
0016 
0017 #ifndef LLVM_CLANG_AST_DEPENDENTDIAGNOSTIC_H
0018 #define LLVM_CLANG_AST_DEPENDENTDIAGNOSTIC_H
0019 
0020 #include "clang/AST/DeclBase.h"
0021 #include "clang/AST/DeclContextInternals.h"
0022 #include "clang/AST/Type.h"
0023 #include "clang/Basic/PartialDiagnostic.h"
0024 #include "clang/Basic/SourceLocation.h"
0025 #include "clang/Basic/Specifiers.h"
0026 #include <cassert>
0027 #include <iterator>
0028 
0029 namespace clang {
0030 
0031 class ASTContext;
0032 class CXXRecordDecl;
0033 class NamedDecl;
0034 
0035 /// A dependently-generated diagnostic.
0036 class DependentDiagnostic {
0037 public:
0038   enum AccessNonce { Access = 0 };
0039 
0040   static DependentDiagnostic *Create(ASTContext &Context,
0041                                      DeclContext *Parent,
0042                                      AccessNonce _,
0043                                      SourceLocation Loc,
0044                                      bool IsMemberAccess,
0045                                      AccessSpecifier AS,
0046                                      NamedDecl *TargetDecl,
0047                                      CXXRecordDecl *NamingClass,
0048                                      QualType BaseObjectType,
0049                                      const PartialDiagnostic &PDiag) {
0050     DependentDiagnostic *DD = Create(Context, Parent, PDiag);
0051     DD->AccessData.Loc = Loc;
0052     DD->AccessData.IsMember = IsMemberAccess;
0053     DD->AccessData.Access = AS;
0054     DD->AccessData.TargetDecl = TargetDecl;
0055     DD->AccessData.NamingClass = NamingClass;
0056     DD->AccessData.BaseObjectType = BaseObjectType.getAsOpaquePtr();
0057     return DD;
0058   }
0059 
0060   unsigned getKind() const {
0061     return Access;
0062   }
0063 
0064   bool isAccessToMember() const {
0065     assert(getKind() == Access);
0066     return AccessData.IsMember;
0067   }
0068 
0069   AccessSpecifier getAccess() const {
0070     assert(getKind() == Access);
0071     return AccessSpecifier(AccessData.Access);
0072   }
0073 
0074   SourceLocation getAccessLoc() const {
0075     assert(getKind() == Access);
0076     return AccessData.Loc;
0077   }
0078 
0079   NamedDecl *getAccessTarget() const {
0080     assert(getKind() == Access);
0081     return AccessData.TargetDecl;
0082   }
0083 
0084   NamedDecl *getAccessNamingClass() const {
0085     assert(getKind() == Access);
0086     return AccessData.NamingClass;
0087   }
0088 
0089   QualType getAccessBaseObjectType() const {
0090     assert(getKind() == Access);
0091     return QualType::getFromOpaquePtr(AccessData.BaseObjectType);
0092   }
0093 
0094   const PartialDiagnostic &getDiagnostic() const {
0095     return Diag;
0096   }
0097 
0098 private:
0099   friend class DeclContext::ddiag_iterator;
0100   friend class DependentStoredDeclsMap;
0101 
0102   DependentDiagnostic(const PartialDiagnostic &PDiag,
0103                       DiagnosticStorage *Storage)
0104       : Diag(PDiag, Storage) {}
0105 
0106   static DependentDiagnostic *Create(ASTContext &Context,
0107                                      DeclContext *Parent,
0108                                      const PartialDiagnostic &PDiag);
0109 
0110   DependentDiagnostic *NextDiagnostic;
0111 
0112   PartialDiagnostic Diag;
0113 
0114   struct {
0115     SourceLocation Loc;
0116     LLVM_PREFERRED_TYPE(AccessSpecifier)
0117     unsigned Access : 2;
0118     LLVM_PREFERRED_TYPE(bool)
0119     unsigned IsMember : 1;
0120     NamedDecl *TargetDecl;
0121     CXXRecordDecl *NamingClass;
0122     void *BaseObjectType;
0123   } AccessData;
0124 };
0125 
0126 /// An iterator over the dependent diagnostics in a dependent context.
0127 class DeclContext::ddiag_iterator {
0128 public:
0129   ddiag_iterator() = default;
0130   explicit ddiag_iterator(DependentDiagnostic *Ptr) : Ptr(Ptr) {}
0131 
0132   using value_type = DependentDiagnostic *;
0133   using reference = DependentDiagnostic *;
0134   using pointer = DependentDiagnostic *;
0135   using difference_type = int;
0136   using iterator_category = std::forward_iterator_tag;
0137 
0138   reference operator*() const { return Ptr; }
0139 
0140   ddiag_iterator &operator++() {
0141     assert(Ptr && "attempt to increment past end of diag list");
0142     Ptr = Ptr->NextDiagnostic;
0143     return *this;
0144   }
0145 
0146   ddiag_iterator operator++(int) {
0147     ddiag_iterator tmp = *this;
0148     ++*this;
0149     return tmp;
0150   }
0151 
0152   bool operator==(ddiag_iterator Other) const {
0153     return Ptr == Other.Ptr;
0154   }
0155 
0156   bool operator!=(ddiag_iterator Other) const {
0157     return Ptr != Other.Ptr;
0158   }
0159 
0160   ddiag_iterator &operator+=(difference_type N) {
0161     assert(N >= 0 && "cannot rewind a DeclContext::ddiag_iterator");
0162     while (N--)
0163       ++*this;
0164     return *this;
0165   }
0166 
0167   ddiag_iterator operator+(difference_type N) const {
0168     ddiag_iterator tmp = *this;
0169     tmp += N;
0170     return tmp;
0171   }
0172 
0173 private:
0174   DependentDiagnostic *Ptr = nullptr;
0175 };
0176 
0177 inline DeclContext::ddiag_range DeclContext::ddiags() const {
0178   assert(isDependentContext()
0179          && "cannot iterate dependent diagnostics of non-dependent context");
0180   const DependentStoredDeclsMap *Map
0181     = static_cast<DependentStoredDeclsMap*>(getPrimaryContext()->getLookupPtr());
0182 
0183   if (!Map)
0184     // Return an empty range using the always-end default constructor.
0185     return ddiag_range(ddiag_iterator(), ddiag_iterator());
0186 
0187   return ddiag_range(ddiag_iterator(Map->FirstDiagnostic), ddiag_iterator());
0188 }
0189 
0190 } // namespace clang
0191 
0192 #endif // LLVM_CLANG_AST_DEPENDENTDIAGNOSTIC_H