Coverage Report

Created: 2018-07-19 20:53

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