1 //==- DependentDiagnostic.h - Dependently-generated diagnostics --*- C++ -*-==//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines interfaces for diagnostics which may or may
10 // fire based on how a template is instantiated.
12 // At the moment, the only consumer of this interface is access
15 //===----------------------------------------------------------------------===//
17 #ifndef LLVM_CLANG_AST_DEPENDENTDIAGNOSTIC_H
18 #define LLVM_CLANG_AST_DEPENDENTDIAGNOSTIC_H
20 #include "clang/AST/DeclBase.h"
21 #include "clang/AST/DeclContextInternals.h"
22 #include "clang/AST/Type.h"
23 #include "clang/Basic/PartialDiagnostic.h"
24 #include "clang/Basic/SourceLocation.h"
25 #include "clang/Basic/Specifiers.h"
35 /// A dependently-generated diagnostic.
36 class DependentDiagnostic {
38 enum AccessNonce { Access = 0 };
40 static DependentDiagnostic *Create(ASTContext &Context,
46 NamedDecl *TargetDecl,
47 CXXRecordDecl *NamingClass,
48 QualType BaseObjectType,
49 const PartialDiagnostic &PDiag) {
50 DependentDiagnostic *DD = Create(Context, Parent, PDiag);
51 DD->AccessData.Loc = Loc.getRawEncoding();
52 DD->AccessData.IsMember = IsMemberAccess;
53 DD->AccessData.Access = AS;
54 DD->AccessData.TargetDecl = TargetDecl;
55 DD->AccessData.NamingClass = NamingClass;
56 DD->AccessData.BaseObjectType = BaseObjectType.getAsOpaquePtr();
60 unsigned getKind() const {
64 bool isAccessToMember() const {
65 assert(getKind() == Access);
66 return AccessData.IsMember;
69 AccessSpecifier getAccess() const {
70 assert(getKind() == Access);
71 return AccessSpecifier(AccessData.Access);
74 SourceLocation getAccessLoc() const {
75 assert(getKind() == Access);
76 return SourceLocation::getFromRawEncoding(AccessData.Loc);
79 NamedDecl *getAccessTarget() const {
80 assert(getKind() == Access);
81 return AccessData.TargetDecl;
84 NamedDecl *getAccessNamingClass() const {
85 assert(getKind() == Access);
86 return AccessData.NamingClass;
89 QualType getAccessBaseObjectType() const {
90 assert(getKind() == Access);
91 return QualType::getFromOpaquePtr(AccessData.BaseObjectType);
94 const PartialDiagnostic &getDiagnostic() const {
99 friend class DeclContext::ddiag_iterator;
100 friend class DependentStoredDeclsMap;
102 DependentDiagnostic(const PartialDiagnostic &PDiag,
103 PartialDiagnostic::Storage *Storage)
104 : Diag(PDiag, Storage) {}
106 static DependentDiagnostic *Create(ASTContext &Context,
108 const PartialDiagnostic &PDiag);
110 DependentDiagnostic *NextDiagnostic;
112 PartialDiagnostic Diag;
117 unsigned IsMember : 1;
118 NamedDecl *TargetDecl;
119 CXXRecordDecl *NamingClass;
120 void *BaseObjectType;
124 /// An iterator over the dependent diagnostics in a dependent context.
125 class DeclContext::ddiag_iterator {
127 ddiag_iterator() = default;
128 explicit ddiag_iterator(DependentDiagnostic *Ptr) : Ptr(Ptr) {}
130 using value_type = DependentDiagnostic *;
131 using reference = DependentDiagnostic *;
132 using pointer = DependentDiagnostic *;
133 using difference_type = int;
134 using iterator_category = std::forward_iterator_tag;
136 reference operator*() const { return Ptr; }
138 ddiag_iterator &operator++() {
139 assert(Ptr && "attempt to increment past end of diag list");
140 Ptr = Ptr->NextDiagnostic;
144 ddiag_iterator operator++(int) {
145 ddiag_iterator tmp = *this;
150 bool operator==(ddiag_iterator Other) const {
151 return Ptr == Other.Ptr;
154 bool operator!=(ddiag_iterator Other) const {
155 return Ptr != Other.Ptr;
158 ddiag_iterator &operator+=(difference_type N) {
159 assert(N >= 0 && "cannot rewind a DeclContext::ddiag_iterator");
165 ddiag_iterator operator+(difference_type N) const {
166 ddiag_iterator tmp = *this;
172 DependentDiagnostic *Ptr = nullptr;
175 inline DeclContext::ddiag_range DeclContext::ddiags() const {
176 assert(isDependentContext()
177 && "cannot iterate dependent diagnostics of non-dependent context");
178 const DependentStoredDeclsMap *Map
179 = static_cast<DependentStoredDeclsMap*>(getPrimaryContext()->getLookupPtr());
182 // Return an empty range using the always-end default constructor.
183 return ddiag_range(ddiag_iterator(), ddiag_iterator());
185 return ddiag_range(ddiag_iterator(Map->FirstDiagnostic), ddiag_iterator());
190 #endif // LLVM_CLANG_AST_DEPENDENTDIAGNOSTIC_H