• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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