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