DependentDiagnostic.h revision 30a2e16f6c27f888dd11eba6bbbae1e980078fcb
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/AST/DeclBase.h"
22#include "clang/AST/DeclContextInternals.h"
23#include "clang/AST/Type.h"
24#include "clang/Basic/PartialDiagnostic.h"
25#include "clang/Basic/SourceLocation.h"
26
27namespace clang {
28
29class ASTContext;
30class CXXRecordDecl;
31class NamedDecl;
32
33/// A dependently-generated diagnostic.
34class DependentDiagnostic {
35public:
36  enum AccessNonce { Access = 0 };
37
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
58  unsigned getKind() const {
59    return Access;
60  }
61
62  bool isAccessToMember() const {
63    assert(getKind() == Access);
64    return AccessData.IsMember;
65  }
66
67  AccessSpecifier getAccess() const {
68    assert(getKind() == Access);
69    return AccessSpecifier(AccessData.Access);
70  }
71
72  SourceLocation getAccessLoc() const {
73    assert(getKind() == Access);
74    return SourceLocation::getFromRawEncoding(AccessData.Loc);
75  }
76
77  NamedDecl *getAccessTarget() const {
78    assert(getKind() == Access);
79    return AccessData.TargetDecl;
80  }
81
82  NamedDecl *getAccessNamingClass() const {
83    assert(getKind() == Access);
84    return AccessData.NamingClass;
85  }
86
87  QualType getAccessBaseObjectType() const {
88    assert(getKind() == Access);
89    return QualType::getFromOpaquePtr(AccessData.BaseObjectType);
90  }
91
92  const PartialDiagnostic &getDiagnostic() const {
93    return Diag;
94  }
95
96private:
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.
126class DeclContext::ddiag_iterator {
127public:
128  ddiag_iterator() : Ptr(0) {}
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
172private:
173  DependentDiagnostic *Ptr;
174};
175
176inline 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
186inline DeclContext::ddiag_iterator DeclContext::ddiag_end() const {
187  return ddiag_iterator();
188}
189
190}
191
192#endif
193