DependentDiagnostic.h revision b836518bfc0a2ad5e22a670c82fa070ed83ea909
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
26namespace clang {
27
28class ASTContext;
29class CXXRecordDecl;
30class NamedDecl;
31
32/// A dependently-generated diagnostic.
33class DependentDiagnostic {
34public:
35  enum AccessNonce { Access = 0 };
36
37  static DependentDiagnostic *Create(ASTContext &Context,
38                                     DeclContext *Parent,
39                                     AccessNonce _,
40                                     SourceLocation Loc,
41                                     bool IsMemberAccess,
42                                     AccessSpecifier AS,
43                                     NamedDecl *TargetDecl,
44                                     CXXRecordDecl *NamingClass,
45                                     const PartialDiagnostic &PDiag) {
46    DependentDiagnostic *DD = Create(Context, Parent, PDiag);
47    DD->AccessData.Loc = Loc.getRawEncoding();
48    DD->AccessData.IsMember = IsMemberAccess;
49    DD->AccessData.Access = AS;
50    DD->AccessData.TargetDecl = TargetDecl;
51    DD->AccessData.NamingClass = NamingClass;
52    return DD;
53  }
54
55  unsigned getKind() const {
56    return Access;
57  }
58
59  bool isAccessToMember() const {
60    assert(getKind() == Access);
61    return AccessData.IsMember;
62  }
63
64  AccessSpecifier getAccess() const {
65    assert(getKind() == Access);
66    return AccessSpecifier(AccessData.Access);
67  }
68
69  SourceLocation getAccessLoc() const {
70    assert(getKind() == Access);
71    return SourceLocation::getFromRawEncoding(AccessData.Loc);
72  }
73
74  NamedDecl *getAccessTarget() const {
75    assert(getKind() == Access);
76    return AccessData.TargetDecl;
77  }
78
79  NamedDecl *getAccessNamingClass() const {
80    assert(getKind() == Access);
81    return AccessData.NamingClass;
82  }
83
84  const PartialDiagnostic &getDiagnostic() const {
85    return Diag;
86  }
87
88private:
89  DependentDiagnostic(const PartialDiagnostic &PDiag,
90                      PartialDiagnostic::Storage *Storage)
91    : Diag(PDiag, Storage) {}
92
93  static DependentDiagnostic *Create(ASTContext &Context,
94                                     DeclContext *Parent,
95                                     const PartialDiagnostic &PDiag);
96
97  friend class DependentStoredDeclsMap;
98  friend class DeclContext::ddiag_iterator;
99  DependentDiagnostic *NextDiagnostic;
100
101  PartialDiagnostic Diag;
102
103  union {
104    struct {
105      unsigned Loc;
106      unsigned Access : 2;
107      unsigned IsMember : 1;
108      NamedDecl *TargetDecl;
109      CXXRecordDecl *NamingClass;
110    } AccessData;
111  };
112};
113
114///
115
116/// An iterator over the dependent diagnostics in a dependent context.
117class DeclContext::ddiag_iterator {
118public:
119  ddiag_iterator() : Ptr(0) {}
120  explicit ddiag_iterator(DependentDiagnostic *Ptr) : Ptr(Ptr) {}
121
122  typedef DependentDiagnostic *value_type;
123  typedef DependentDiagnostic *reference;
124  typedef DependentDiagnostic *pointer;
125  typedef int difference_type;
126  typedef std::forward_iterator_tag iterator_category;
127
128  reference operator*() const { return Ptr; }
129
130  ddiag_iterator &operator++() {
131    assert(Ptr && "attempt to increment past end of diag list");
132    Ptr = Ptr->NextDiagnostic;
133    return *this;
134  }
135
136  ddiag_iterator operator++(int) {
137    ddiag_iterator tmp = *this;
138    ++*this;
139    return tmp;
140  }
141
142  bool operator==(ddiag_iterator Other) const {
143    return Ptr == Other.Ptr;
144  }
145
146  bool operator!=(ddiag_iterator Other) const {
147    return Ptr != Other.Ptr;
148  }
149
150  ddiag_iterator &operator+=(difference_type N) {
151    assert(N >= 0 && "cannot rewind a DeclContext::ddiag_iterator");
152    while (N--)
153      ++*this;
154    return *this;
155  }
156
157  ddiag_iterator operator+(difference_type N) const {
158    ddiag_iterator tmp = *this;
159    tmp += N;
160    return tmp;
161  }
162
163private:
164  DependentDiagnostic *Ptr;
165};
166
167inline DeclContext::ddiag_iterator DeclContext::ddiag_begin() const {
168  assert(isDependentContext()
169         && "cannot iterate dependent diagnostics of non-dependent context");
170  const DependentStoredDeclsMap *Map
171    = static_cast<DependentStoredDeclsMap*>(getPrimaryContext()->LookupPtr);
172
173  if (!Map) return ddiag_iterator();
174  return ddiag_iterator(Map->FirstDiagnostic);
175}
176
177inline DeclContext::ddiag_iterator DeclContext::ddiag_end() const {
178  return ddiag_iterator();
179}
180
181}
182
183#endif
184