/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/AST/DependentDiagnostic.h
Line | Count | Source (jump to first uncovered line) |
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 | 97 | const PartialDiagnostic &PDiag) { |
50 | 97 | DependentDiagnostic *DD = Create(Context, Parent, PDiag); |
51 | 97 | DD->AccessData.Loc = Loc; |
52 | 97 | DD->AccessData.IsMember = IsMemberAccess; |
53 | 97 | DD->AccessData.Access = AS; |
54 | 97 | DD->AccessData.TargetDecl = TargetDecl; |
55 | 97 | DD->AccessData.NamingClass = NamingClass; |
56 | 97 | DD->AccessData.BaseObjectType = BaseObjectType.getAsOpaquePtr(); |
57 | 97 | return DD; |
58 | 97 | } |
59 | | |
60 | 980 | unsigned getKind() const { |
61 | 980 | return Access; |
62 | 980 | } |
63 | | |
64 | 140 | bool isAccessToMember() const { |
65 | 140 | assert(getKind() == Access); |
66 | 140 | return AccessData.IsMember; |
67 | 140 | } |
68 | | |
69 | 140 | AccessSpecifier getAccess() const { |
70 | 140 | assert(getKind() == Access); |
71 | 140 | return AccessSpecifier(AccessData.Access); |
72 | 140 | } |
73 | | |
74 | 140 | SourceLocation getAccessLoc() const { |
75 | 140 | assert(getKind() == Access); |
76 | 140 | return AccessData.Loc; |
77 | 140 | } |
78 | | |
79 | 140 | NamedDecl *getAccessTarget() const { |
80 | 140 | assert(getKind() == Access); |
81 | 140 | return AccessData.TargetDecl; |
82 | 140 | } |
83 | | |
84 | 140 | NamedDecl *getAccessNamingClass() const { |
85 | 140 | assert(getKind() == Access); |
86 | 140 | return AccessData.NamingClass; |
87 | 140 | } |
88 | | |
89 | 140 | QualType getAccessBaseObjectType() const { |
90 | 140 | assert(getKind() == Access); |
91 | 140 | return QualType::getFromOpaquePtr(AccessData.BaseObjectType); |
92 | 140 | } |
93 | | |
94 | 140 | const PartialDiagnostic &getDiagnostic() const { |
95 | 140 | return Diag; |
96 | 140 | } |
97 | | |
98 | | private: |
99 | | friend class DeclContext::ddiag_iterator; |
100 | | friend class DependentStoredDeclsMap; |
101 | | |
102 | | DependentDiagnostic(const PartialDiagnostic &PDiag, |
103 | | DiagnosticStorage *Storage) |
104 | 97 | : 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 | | unsigned Access : 2; |
117 | | unsigned IsMember : 1; |
118 | | NamedDecl *TargetDecl; |
119 | | CXXRecordDecl *NamingClass; |
120 | | void *BaseObjectType; |
121 | | } AccessData; |
122 | | }; |
123 | | |
124 | | /// An iterator over the dependent diagnostics in a dependent context. |
125 | | class DeclContext::ddiag_iterator { |
126 | | public: |
127 | 1.11M | ddiag_iterator() = default; |
128 | 696k | explicit ddiag_iterator(DependentDiagnostic *Ptr) : Ptr(Ptr) {} |
129 | | |
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; |
135 | | |
136 | 140 | reference operator*() const { return Ptr; } |
137 | | |
138 | 140 | ddiag_iterator &operator++() { |
139 | 140 | assert(Ptr && "attempt to increment past end of diag list"); |
140 | 140 | Ptr = Ptr->NextDiagnostic; |
141 | 140 | return *this; |
142 | 140 | } |
143 | | |
144 | 0 | ddiag_iterator operator++(int) { |
145 | 0 | ddiag_iterator tmp = *this; |
146 | 0 | ++*this; |
147 | 0 | return tmp; |
148 | 0 | } |
149 | | |
150 | 0 | bool operator==(ddiag_iterator Other) const { |
151 | 0 | return Ptr == Other.Ptr; |
152 | 0 | } |
153 | | |
154 | 904k | bool operator!=(ddiag_iterator Other) const { |
155 | 904k | return Ptr != Other.Ptr; |
156 | 904k | } |
157 | | |
158 | 0 | ddiag_iterator &operator+=(difference_type N) { |
159 | 0 | assert(N >= 0 && "cannot rewind a DeclContext::ddiag_iterator"); |
160 | 0 | while (N--) |
161 | 0 | ++*this; |
162 | 0 | return *this; |
163 | 0 | } |
164 | | |
165 | 0 | ddiag_iterator operator+(difference_type N) const { |
166 | 0 | ddiag_iterator tmp = *this; |
167 | 0 | tmp += N; |
168 | 0 | return tmp; |
169 | 0 | } |
170 | | |
171 | | private: |
172 | | DependentDiagnostic *Ptr = nullptr; |
173 | | }; |
174 | | |
175 | 904k | inline DeclContext::ddiag_range DeclContext::ddiags() const { |
176 | 904k | assert(isDependentContext() |
177 | 904k | && "cannot iterate dependent diagnostics of non-dependent context"); |
178 | 904k | const DependentStoredDeclsMap *Map |
179 | 904k | = static_cast<DependentStoredDeclsMap*>(getPrimaryContext()->getLookupPtr()); |
180 | | |
181 | 904k | if (!Map) |
182 | | // Return an empty range using the always-end default constructor. |
183 | 207k | return ddiag_range(ddiag_iterator(), ddiag_iterator()); |
184 | | |
185 | 696k | return ddiag_range(ddiag_iterator(Map->FirstDiagnostic), ddiag_iterator()); |
186 | 696k | } |
187 | | |
188 | | } // namespace clang |
189 | | |
190 | | #endif // LLVM_CLANG_AST_DEPENDENTDIAGNOSTIC_H |