Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 1
//===- DelayedDiagnostic.h - Delayed declarator diagnostics -----*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
/// \file
10
/// Defines the classes clang::DelayedDiagnostic and
11
/// clang::AccessedEntity.
12
///
13
/// DelayedDiangostic is used to record diagnostics that are being
14
/// conditionally produced during declarator parsing.  Certain kinds of
15
/// diagnostics -- notably deprecation and access control -- are suppressed
16
/// based on semantic properties of the parsed declaration that aren't known
17
/// until it is fully parsed.
18
//
19
//===----------------------------------------------------------------------===//
20
 
21
#ifndef LLVM_CLANG_SEMA_DELAYEDDIAGNOSTIC_H
22
#define LLVM_CLANG_SEMA_DELAYEDDIAGNOSTIC_H
23
 
24
#include "clang/AST/DeclAccessPair.h"
25
#include "clang/AST/DeclBase.h"
26
#include "clang/AST/DeclCXX.h"
27
#include "clang/AST/Type.h"
28
#include "clang/Basic/LLVM.h"
29
#include "clang/Basic/PartialDiagnostic.h"
30
#include "clang/Basic/SourceLocation.h"
31
#include "clang/Basic/Specifiers.h"
32
#include "clang/Sema/Sema.h"
33
#include "llvm/ADT/ArrayRef.h"
34
#include "llvm/ADT/SmallVector.h"
35
#include "llvm/ADT/StringRef.h"
36
#include "llvm/Support/Casting.h"
37
#include <cassert>
38
#include <cstddef>
39
#include <utility>
40
 
41
namespace clang {
42
 
43
class ObjCInterfaceDecl;
44
class ObjCPropertyDecl;
45
 
46
namespace sema {
47
 
48
/// A declaration being accessed, together with information about how
49
/// it was accessed.
50
class AccessedEntity {
51
public:
52
  /// A member declaration found through lookup.  The target is the
53
  /// member.
54
  enum MemberNonce { Member };
55
 
56
  /// A hierarchy (base-to-derived or derived-to-base) conversion.
57
  /// The target is the base class.
58
  enum BaseNonce { Base };
59
 
60
  AccessedEntity(PartialDiagnostic::DiagStorageAllocator &Allocator,
61
                 MemberNonce _, CXXRecordDecl *NamingClass,
62
                 DeclAccessPair FoundDecl, QualType BaseObjectType)
63
      : Access(FoundDecl.getAccess()), IsMember(true),
64
        Target(FoundDecl.getDecl()), NamingClass(NamingClass),
65
        BaseObjectType(BaseObjectType), Diag(0, Allocator) {}
66
 
67
  AccessedEntity(PartialDiagnostic::DiagStorageAllocator &Allocator,
68
                 BaseNonce _, CXXRecordDecl *BaseClass,
69
                 CXXRecordDecl *DerivedClass, AccessSpecifier Access)
70
      : Access(Access), IsMember(false), Target(BaseClass),
71
        NamingClass(DerivedClass), Diag(0, Allocator) {}
72
 
73
  bool isMemberAccess() const { return IsMember; }
74
 
75
  bool isQuiet() const { return Diag.getDiagID() == 0; }
76
 
77
  AccessSpecifier getAccess() const { return AccessSpecifier(Access); }
78
 
79
  // These apply to member decls...
80
  NamedDecl *getTargetDecl() const { return Target; }
81
  CXXRecordDecl *getNamingClass() const { return NamingClass; }
82
 
83
  // ...and these apply to hierarchy conversions.
84
  CXXRecordDecl *getBaseClass() const {
85
    assert(!IsMember); return cast<CXXRecordDecl>(Target);
86
  }
87
  CXXRecordDecl *getDerivedClass() const { return NamingClass; }
88
 
89
  /// Retrieves the base object type, important when accessing
90
  /// an instance member.
91
  QualType getBaseObjectType() const { return BaseObjectType; }
92
 
93
  /// Sets a diagnostic to be performed.  The diagnostic is given
94
  /// four (additional) arguments:
95
  ///   %0 - 0 if the entity was private, 1 if protected
96
  ///   %1 - the DeclarationName of the entity
97
  ///   %2 - the TypeDecl type of the naming class
98
  ///   %3 - the TypeDecl type of the declaring class
99
  void setDiag(const PartialDiagnostic &PDiag) {
100
    assert(isQuiet() && "partial diagnostic already defined");
101
    Diag = PDiag;
102
  }
103
  PartialDiagnostic &setDiag(unsigned DiagID) {
104
    assert(isQuiet() && "partial diagnostic already defined");
105
    assert(DiagID && "creating null diagnostic");
106
    Diag.Reset(DiagID);
107
    return Diag;
108
  }
109
  const PartialDiagnostic &getDiag() const {
110
    return Diag;
111
  }
112
 
113
private:
114
  unsigned Access : 2;
115
  unsigned IsMember : 1;
116
  NamedDecl *Target;
117
  CXXRecordDecl *NamingClass;
118
  QualType BaseObjectType;
119
  PartialDiagnostic Diag;
120
};
121
 
122
/// A diagnostic message which has been conditionally emitted pending
123
/// the complete parsing of the current declaration.
124
class DelayedDiagnostic {
125
public:
126
  enum DDKind : unsigned char { Availability, Access, ForbiddenType };
127
 
128
  DDKind Kind;
129
  bool Triggered;
130
 
131
  SourceLocation Loc;
132
 
133
  void Destroy();
134
 
135
  static DelayedDiagnostic makeAvailability(AvailabilityResult AR,
136
                                            ArrayRef<SourceLocation> Locs,
137
                                            const NamedDecl *ReferringDecl,
138
                                            const NamedDecl *OffendingDecl,
139
                                            const ObjCInterfaceDecl *UnknownObjCClass,
140
                                            const ObjCPropertyDecl  *ObjCProperty,
141
                                            StringRef Msg,
142
                                            bool ObjCPropertyAccess);
143
 
144
  static DelayedDiagnostic makeAccess(SourceLocation Loc,
145
                                      const AccessedEntity &Entity) {
146
    DelayedDiagnostic DD;
147
    DD.Kind = Access;
148
    DD.Triggered = false;
149
    DD.Loc = Loc;
150
    new (&DD.getAccessData()) AccessedEntity(Entity);
151
    return DD;
152
  }
153
 
154
  static DelayedDiagnostic makeForbiddenType(SourceLocation loc,
155
                                             unsigned diagnostic,
156
                                             QualType type,
157
                                             unsigned argument) {
158
    DelayedDiagnostic DD;
159
    DD.Kind = ForbiddenType;
160
    DD.Triggered = false;
161
    DD.Loc = loc;
162
    DD.ForbiddenTypeData.Diagnostic = diagnostic;
163
    DD.ForbiddenTypeData.OperandType = type.getAsOpaquePtr();
164
    DD.ForbiddenTypeData.Argument = argument;
165
    return DD;
166
  }
167
 
168
  AccessedEntity &getAccessData() {
169
    assert(Kind == Access && "Not an access diagnostic.");
170
    return *reinterpret_cast<AccessedEntity*>(AccessData);
171
  }
172
  const AccessedEntity &getAccessData() const {
173
    assert(Kind == Access && "Not an access diagnostic.");
174
    return *reinterpret_cast<const AccessedEntity*>(AccessData);
175
  }
176
 
177
  const NamedDecl *getAvailabilityReferringDecl() const {
178
    assert(Kind == Availability && "Not an availability diagnostic.");
179
    return AvailabilityData.ReferringDecl;
180
  }
181
 
182
  const NamedDecl *getAvailabilityOffendingDecl() const {
183
    return AvailabilityData.OffendingDecl;
184
  }
185
 
186
  StringRef getAvailabilityMessage() const {
187
    assert(Kind == Availability && "Not an availability diagnostic.");
188
    return StringRef(AvailabilityData.Message, AvailabilityData.MessageLen);
189
  }
190
 
191
  ArrayRef<SourceLocation> getAvailabilitySelectorLocs() const {
192
    assert(Kind == Availability && "Not an availability diagnostic.");
193
    return llvm::ArrayRef(AvailabilityData.SelectorLocs,
194
                          AvailabilityData.NumSelectorLocs);
195
  }
196
 
197
  AvailabilityResult getAvailabilityResult() const {
198
    assert(Kind == Availability && "Not an availability diagnostic.");
199
    return AvailabilityData.AR;
200
  }
201
 
202
  /// The diagnostic ID to emit.  Used like so:
203
  ///   Diag(diag.Loc, diag.getForbiddenTypeDiagnostic())
204
  ///     << diag.getForbiddenTypeOperand()
205
  ///     << diag.getForbiddenTypeArgument();
206
  unsigned getForbiddenTypeDiagnostic() const {
207
    assert(Kind == ForbiddenType && "not a forbidden-type diagnostic");
208
    return ForbiddenTypeData.Diagnostic;
209
  }
210
 
211
  unsigned getForbiddenTypeArgument() const {
212
    assert(Kind == ForbiddenType && "not a forbidden-type diagnostic");
213
    return ForbiddenTypeData.Argument;
214
  }
215
 
216
  QualType getForbiddenTypeOperand() const {
217
    assert(Kind == ForbiddenType && "not a forbidden-type diagnostic");
218
    return QualType::getFromOpaquePtr(ForbiddenTypeData.OperandType);
219
  }
220
 
221
  const ObjCInterfaceDecl *getUnknownObjCClass() const {
222
    return AvailabilityData.UnknownObjCClass;
223
  }
224
 
225
  const ObjCPropertyDecl *getObjCProperty() const {
226
    return AvailabilityData.ObjCProperty;
227
  }
228
 
229
  bool getObjCPropertyAccess() const {
230
    return AvailabilityData.ObjCPropertyAccess;
231
  }
232
 
233
private:
234
  struct AD {
235
    const NamedDecl *ReferringDecl;
236
    const NamedDecl *OffendingDecl;
237
    const ObjCInterfaceDecl *UnknownObjCClass;
238
    const ObjCPropertyDecl  *ObjCProperty;
239
    const char *Message;
240
    size_t MessageLen;
241
    SourceLocation *SelectorLocs;
242
    size_t NumSelectorLocs;
243
    AvailabilityResult AR;
244
    bool ObjCPropertyAccess;
245
  };
246
 
247
  struct FTD {
248
    unsigned Diagnostic;
249
    unsigned Argument;
250
    void *OperandType;
251
  };
252
 
253
  union {
254
    struct AD AvailabilityData;
255
    struct FTD ForbiddenTypeData;
256
 
257
    /// Access control.
258
    char AccessData[sizeof(AccessedEntity)];
259
  };
260
};
261
 
262
/// A collection of diagnostics which were delayed.
263
class DelayedDiagnosticPool {
264
  const DelayedDiagnosticPool *Parent;
265
  SmallVector<DelayedDiagnostic, 4> Diagnostics;
266
 
267
public:
268
  DelayedDiagnosticPool(const DelayedDiagnosticPool *parent) : Parent(parent) {}
269
 
270
  DelayedDiagnosticPool(const DelayedDiagnosticPool &) = delete;
271
  DelayedDiagnosticPool &operator=(const DelayedDiagnosticPool &) = delete;
272
 
273
  DelayedDiagnosticPool(DelayedDiagnosticPool &&Other)
274
      : Parent(Other.Parent), Diagnostics(std::move(Other.Diagnostics)) {
275
    Other.Diagnostics.clear();
276
  }
277
 
278
  DelayedDiagnosticPool &operator=(DelayedDiagnosticPool &&Other) {
279
    Parent = Other.Parent;
280
    Diagnostics = std::move(Other.Diagnostics);
281
    Other.Diagnostics.clear();
282
    return *this;
283
  }
284
 
285
  ~DelayedDiagnosticPool() {
286
    for (SmallVectorImpl<DelayedDiagnostic>::iterator
287
           i = Diagnostics.begin(), e = Diagnostics.end(); i != e; ++i)
288
      i->Destroy();
289
  }
290
 
291
  const DelayedDiagnosticPool *getParent() const { return Parent; }
292
 
293
  /// Does this pool, or any of its ancestors, contain any diagnostics?
294
  bool empty() const {
295
    return (Diagnostics.empty() && (!Parent || Parent->empty()));
296
  }
297
 
298
  /// Add a diagnostic to this pool.
299
  void add(const DelayedDiagnostic &diag) {
300
    Diagnostics.push_back(diag);
301
  }
302
 
303
  /// Steal the diagnostics from the given pool.
304
  void steal(DelayedDiagnosticPool &pool) {
305
    if (pool.Diagnostics.empty()) return;
306
 
307
    if (Diagnostics.empty()) {
308
      Diagnostics = std::move(pool.Diagnostics);
309
    } else {
310
      Diagnostics.append(pool.pool_begin(), pool.pool_end());
311
    }
312
    pool.Diagnostics.clear();
313
  }
314
 
315
  using pool_iterator = SmallVectorImpl<DelayedDiagnostic>::const_iterator;
316
 
317
  pool_iterator pool_begin() const { return Diagnostics.begin(); }
318
  pool_iterator pool_end() const { return Diagnostics.end(); }
319
  bool pool_empty() const { return Diagnostics.empty(); }
320
};
321
 
322
} // namespace clang
323
 
324
/// Add a diagnostic to the current delay pool.
325
inline void Sema::DelayedDiagnostics::add(const sema::DelayedDiagnostic &diag) {
326
  assert(shouldDelayDiagnostics() && "trying to delay without pool");
327
  CurPool->add(diag);
328
}
329
 
330
} // namespace clang
331
 
332
#endif // LLVM_CLANG_SEMA_DELAYEDDIAGNOSTIC_H