clang  3.7.0
DelayedDiagnostic.h
Go to the documentation of this file.
1 //===--- DelayedDiagnostic.h - Delayed declarator 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 /// \file
11 /// \brief Defines the classes clang::DelayedDiagnostic and
12 /// clang::AccessedEntity.
13 ///
14 /// DelayedDiangostic is used to record diagnostics that are being
15 /// conditionally produced during declarator parsing. Certain kinds of
16 /// diagnostics -- notably deprecation and access control -- are suppressed
17 /// based on semantic properties of the parsed declaration that aren't known
18 /// until it is fully parsed.
19 ///
20 //===----------------------------------------------------------------------===//
21 
22 #ifndef LLVM_CLANG_SEMA_DELAYEDDIAGNOSTIC_H
23 #define LLVM_CLANG_SEMA_DELAYEDDIAGNOSTIC_H
24 
25 #include "clang/Sema/Sema.h"
26 
27 namespace clang {
28 namespace sema {
29 
30 /// A declaration being accessed, together with information about how
31 /// it was accessed.
33 public:
34  /// A member declaration found through lookup. The target is the
35  /// member.
36  enum MemberNonce { Member };
37 
38  /// A hierarchy (base-to-derived or derived-to-base) conversion.
39  /// The target is the base class.
40  enum BaseNonce { Base };
41 
42  bool isMemberAccess() const { return IsMember; }
43 
45  MemberNonce _,
46  CXXRecordDecl *NamingClass,
47  DeclAccessPair FoundDecl,
48  QualType BaseObjectType)
49  : Access(FoundDecl.getAccess()), IsMember(true),
50  Target(FoundDecl.getDecl()), NamingClass(NamingClass),
51  BaseObjectType(BaseObjectType), Diag(0, Allocator) {
52  }
53 
55  BaseNonce _,
56  CXXRecordDecl *BaseClass,
57  CXXRecordDecl *DerivedClass,
58  AccessSpecifier Access)
59  : Access(Access), IsMember(false),
60  Target(BaseClass),
61  NamingClass(DerivedClass),
62  Diag(0, Allocator) {
63  }
64 
65  bool isQuiet() const { return Diag.getDiagID() == 0; }
66 
67  AccessSpecifier getAccess() const { return AccessSpecifier(Access); }
68 
69  // These apply to member decls...
70  NamedDecl *getTargetDecl() const { return Target; }
71  CXXRecordDecl *getNamingClass() const { return NamingClass; }
72 
73  // ...and these apply to hierarchy conversions.
75  assert(!IsMember); return cast<CXXRecordDecl>(Target);
76  }
77  CXXRecordDecl *getDerivedClass() const { return NamingClass; }
78 
79  /// Retrieves the base object type, important when accessing
80  /// an instance member.
81  QualType getBaseObjectType() const { return BaseObjectType; }
82 
83  /// Sets a diagnostic to be performed. The diagnostic is given
84  /// four (additional) arguments:
85  /// %0 - 0 if the entity was private, 1 if protected
86  /// %1 - the DeclarationName of the entity
87  /// %2 - the TypeDecl type of the naming class
88  /// %3 - the TypeDecl type of the declaring class
89  void setDiag(const PartialDiagnostic &PDiag) {
90  assert(isQuiet() && "partial diagnostic already defined");
91  Diag = PDiag;
92  }
93  PartialDiagnostic &setDiag(unsigned DiagID) {
94  assert(isQuiet() && "partial diagnostic already defined");
95  assert(DiagID && "creating null diagnostic");
96  Diag.Reset(DiagID);
97  return Diag;
98  }
99  const PartialDiagnostic &getDiag() const {
100  return Diag;
101  }
102 
103 private:
104  unsigned Access : 2;
105  unsigned IsMember : 1;
106  NamedDecl *Target;
107  CXXRecordDecl *NamingClass;
108  QualType BaseObjectType;
109  PartialDiagnostic Diag;
110 };
111 
112 /// A diagnostic message which has been conditionally emitted pending
113 /// the complete parsing of the current declaration.
115 public:
117 
118  unsigned char Kind; // actually a DDKind
119  bool Triggered;
120 
122 
123  void Destroy();
124 
127  const NamedDecl *D,
128  const ObjCInterfaceDecl *UnknownObjCClass,
129  const ObjCPropertyDecl *ObjCProperty,
130  StringRef Msg,
131  bool ObjCPropertyAccess);
132 
133 
135  const AccessedEntity &Entity) {
137  DD.Kind = Access;
138  DD.Triggered = false;
139  DD.Loc = Loc;
140  new (&DD.getAccessData()) AccessedEntity(Entity);
141  return DD;
142  }
143 
145  unsigned diagnostic,
146  QualType type,
147  unsigned argument) {
149  DD.Kind = ForbiddenType;
150  DD.Triggered = false;
151  DD.Loc = loc;
152  DD.ForbiddenTypeData.Diagnostic = diagnostic;
153  DD.ForbiddenTypeData.OperandType = type.getAsOpaquePtr();
154  DD.ForbiddenTypeData.Argument = argument;
155  return DD;
156  }
157 
159  assert(Kind == Access && "Not an access diagnostic.");
160  return *reinterpret_cast<AccessedEntity*>(AccessData);
161  }
162  const AccessedEntity &getAccessData() const {
163  assert(Kind == Access && "Not an access diagnostic.");
164  return *reinterpret_cast<const AccessedEntity*>(AccessData);
165  }
166 
167  const NamedDecl *getDeprecationDecl() const {
168  assert((Kind == Deprecation || Kind == Unavailable) &&
169  "Not a deprecation diagnostic.");
170  return DeprecationData.Decl;
171  }
172 
173  StringRef getDeprecationMessage() const {
174  assert((Kind == Deprecation || Kind == Unavailable) &&
175  "Not a deprecation diagnostic.");
176  return StringRef(DeprecationData.Message,
177  DeprecationData.MessageLen);
178  }
179 
180  /// The diagnostic ID to emit. Used like so:
181  /// Diag(diag.Loc, diag.getForbiddenTypeDiagnostic())
182  /// << diag.getForbiddenTypeOperand()
183  /// << diag.getForbiddenTypeArgument();
184  unsigned getForbiddenTypeDiagnostic() const {
185  assert(Kind == ForbiddenType && "not a forbidden-type diagnostic");
186  return ForbiddenTypeData.Diagnostic;
187  }
188 
189  unsigned getForbiddenTypeArgument() const {
190  assert(Kind == ForbiddenType && "not a forbidden-type diagnostic");
191  return ForbiddenTypeData.Argument;
192  }
193 
195  assert(Kind == ForbiddenType && "not a forbidden-type diagnostic");
196  return QualType::getFromOpaquePtr(ForbiddenTypeData.OperandType);
197  }
198 
200  return DeprecationData.UnknownObjCClass;
201  }
202 
204  return DeprecationData.ObjCProperty;
205  }
206 
207  bool getObjCPropertyAccess() const {
208  return DeprecationData.ObjCPropertyAccess;
209  }
210 
211 private:
212 
213  struct DD {
214  const NamedDecl *Decl;
215  const ObjCInterfaceDecl *UnknownObjCClass;
216  const ObjCPropertyDecl *ObjCProperty;
217  const char *Message;
218  size_t MessageLen;
219  bool ObjCPropertyAccess;
220  };
221 
222  struct FTD {
223  unsigned Diagnostic;
224  unsigned Argument;
225  void *OperandType;
226  };
227 
228  union {
229  /// Deprecation
230  struct DD DeprecationData;
231  struct FTD ForbiddenTypeData;
232 
233  /// Access control.
234  char AccessData[sizeof(AccessedEntity)];
235  };
236 };
237 
238 /// \brief A collection of diagnostics which were delayed.
240  const DelayedDiagnosticPool *Parent;
242 
244  void operator=(const DelayedDiagnosticPool &) = delete;
245 public:
246  DelayedDiagnosticPool(const DelayedDiagnosticPool *parent) : Parent(parent) {}
249  i = Diagnostics.begin(), e = Diagnostics.end(); i != e; ++i)
250  i->Destroy();
251  }
252 
254  : Parent(Other.Parent), Diagnostics(std::move(Other.Diagnostics)) {
255  Other.Diagnostics.clear();
256  }
258  Parent = Other.Parent;
259  Diagnostics = std::move(Other.Diagnostics);
260  Other.Diagnostics.clear();
261  return *this;
262  }
263 
264  const DelayedDiagnosticPool *getParent() const { return Parent; }
265 
266  /// Does this pool, or any of its ancestors, contain any diagnostics?
267  bool empty() const {
268  return (Diagnostics.empty() && (!Parent || Parent->empty()));
269  }
270 
271  /// Add a diagnostic to this pool.
272  void add(const DelayedDiagnostic &diag) {
273  Diagnostics.push_back(diag);
274  }
275 
276  /// Steal the diagnostics from the given pool.
278  if (pool.Diagnostics.empty()) return;
279 
280  if (Diagnostics.empty()) {
281  Diagnostics = std::move(pool.Diagnostics);
282  } else {
283  Diagnostics.append(pool.pool_begin(), pool.pool_end());
284  }
285  pool.Diagnostics.clear();
286  }
287 
289  pool_iterator pool_begin() const { return Diagnostics.begin(); }
290  pool_iterator pool_end() const { return Diagnostics.end(); }
291  bool pool_empty() const { return Diagnostics.empty(); }
292 };
293 
294 }
295 
296 /// Add a diagnostic to the current delay pool.
298  assert(shouldDelayDiagnostics() && "trying to delay without pool");
299  CurPool->add(diag);
300 }
301 
302 
303 }
304 
305 #endif
DelayedDiagnosticPool(const DelayedDiagnosticPool *parent)
DelayedDiagnosticPool(DelayedDiagnosticPool &&Other)
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
Definition: Specifiers.h:83
void * getAsOpaquePtr() const
Definition: Type.h:614
CXXRecordDecl * getDerivedClass() const
char AccessData[sizeof(AccessedEntity)]
Access control.
void add(const DelayedDiagnostic &diag)
Add a diagnostic to this pool.
CXXRecordDecl * getBaseClass() const
void Reset(unsigned DiagID=0)
Clear out this partial diagnostic, giving it a new diagnostic ID and removing all of its arguments...
unsigned getDiagID() const
const DelayedDiagnosticPool * getParent() const
QualType getForbiddenTypeOperand() const
void steal(DelayedDiagnosticPool &pool)
Steal the diagnostics from the given pool.
Represents an ObjC class declaration.
Definition: DeclObjC.h:851
llvm::SpecificBumpPtrAllocator< FormatToken > Allocator
Definition: Format.cpp:1211
const PartialDiagnostic & getDiag() const
CXXRecordDecl * getNamingClass() const
struct DD DeprecationData
Deprecation.
static DelayedDiagnostic makeAvailability(Sema::AvailabilityDiagnostic AD, SourceLocation Loc, const NamedDecl *D, const ObjCInterfaceDecl *UnknownObjCClass, const ObjCPropertyDecl *ObjCProperty, StringRef Msg, bool ObjCPropertyAccess)
bool empty() const
Does this pool, or any of its ancestors, contain any diagnostics?
static DelayedDiagnostic makeForbiddenType(SourceLocation loc, unsigned diagnostic, QualType type, unsigned argument)
An allocator for Storage objects, which uses a small cache to objects, used to reduce malloc()/free()...
unsigned getForbiddenTypeDiagnostic() const
#define false
Definition: stdbool.h:33
Kind
AccessedEntity(PartialDiagnostic::StorageAllocator &Allocator, BaseNonce _, CXXRecordDecl *BaseClass, CXXRecordDecl *DerivedClass, AccessSpecifier Access)
Encodes a location in the source. The SourceManager can decode this to get at the full include stack...
const ObjCInterfaceDecl * getUnknownObjCClass() const
AvailabilityDiagnostic
Definition: Sema.h:3476
const NamedDecl * getDeprecationDecl() const
bool shouldDelayDiagnostics()
Determines whether diagnostics should be delayed.
Definition: Sema.h:561
PartialDiagnostic & setDiag(unsigned DiagID)
StringRef getDeprecationMessage() const
Represents one property declaration in an Objective-C interface.
Definition: DeclObjC.h:2424
unsigned getForbiddenTypeArgument() const
DelayedDiagnosticPool & operator=(DelayedDiagnosticPool &&Other)
static QualType getFromOpaquePtr(const void *Ptr)
Definition: Type.h:615
const AccessedEntity & getAccessData() const
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
Definition: ASTMatchers.h:1639
void setDiag(const PartialDiagnostic &PDiag)
void add(const sema::DelayedDiagnostic &diag)
Adds a delayed diagnostic.
AccessedEntity(PartialDiagnostic::StorageAllocator &Allocator, MemberNonce _, CXXRecordDecl *NamingClass, DeclAccessPair FoundDecl, QualType BaseObjectType)
const ObjCPropertyDecl * getObjCProperty() const
AccessSpecifier getAccess() const
Represents a C++ struct/union/class.
Definition: DeclCXX.h:285
NamedDecl * getTargetDecl() const
A collection of diagnostics which were delayed.
#define true
Definition: stdbool.h:32
QualType getBaseObjectType() const
static DelayedDiagnostic makeAccess(SourceLocation Loc, const AccessedEntity &Entity)
SmallVectorImpl< DelayedDiagnostic >::const_iterator pool_iterator