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