Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/include/clang/AST/NestedNameSpecifier.h
Line
Count
Source (jump to first uncovered line)
1
//===- NestedNameSpecifier.h - C++ nested name specifiers -------*- 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
//  This file defines the NestedNameSpecifier class, which represents
10
//  a C++ nested-name-specifier.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#ifndef LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
15
#define LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
16
17
#include "clang/Basic/Diagnostic.h"
18
#include "clang/Basic/SourceLocation.h"
19
#include "llvm/ADT/FoldingSet.h"
20
#include "llvm/ADT/PointerIntPair.h"
21
#include "llvm/Support/Compiler.h"
22
#include <cstdint>
23
#include <cstdlib>
24
#include <utility>
25
26
namespace clang {
27
28
class ASTContext;
29
class CXXRecordDecl;
30
class IdentifierInfo;
31
class LangOptions;
32
class NamespaceAliasDecl;
33
class NamespaceDecl;
34
struct PrintingPolicy;
35
class Type;
36
class TypeLoc;
37
38
/// Represents a C++ nested name specifier, such as
39
/// "\::std::vector<int>::".
40
///
41
/// C++ nested name specifiers are the prefixes to qualified
42
/// names. For example, "foo::" in "foo::x" is a nested name
43
/// specifier. Nested name specifiers are made up of a sequence of
44
/// specifiers, each of which can be a namespace, type, identifier
45
/// (for dependent names), decltype specifier, or the global specifier ('::').
46
/// The last two specifiers can only appear at the start of a
47
/// nested-namespace-specifier.
48
class NestedNameSpecifier : public llvm::FoldingSetNode {
49
  /// Enumeration describing
50
  enum StoredSpecifierKind {
51
    StoredIdentifier = 0,
52
    StoredDecl = 1,
53
    StoredTypeSpec = 2,
54
    StoredTypeSpecWithTemplate = 3
55
  };
56
57
  /// The nested name specifier that precedes this nested name
58
  /// specifier.
59
  ///
60
  /// The pointer is the nested-name-specifier that precedes this
61
  /// one. The integer stores one of the first four values of type
62
  /// SpecifierKind.
63
  llvm::PointerIntPair<NestedNameSpecifier *, 2, StoredSpecifierKind> Prefix;
64
65
  /// The last component in the nested name specifier, which
66
  /// can be an identifier, a declaration, or a type.
67
  ///
68
  /// When the pointer is NULL, this specifier represents the global
69
  /// specifier '::'. Otherwise, the pointer is one of
70
  /// IdentifierInfo*, Namespace*, or Type*, depending on the kind of
71
  /// specifier as encoded within the prefix.
72
  void* Specifier = nullptr;
73
74
public:
75
  /// The kind of specifier that completes this nested name
76
  /// specifier.
77
  enum SpecifierKind {
78
    /// An identifier, stored as an IdentifierInfo*.
79
    Identifier,
80
81
    /// A namespace, stored as a NamespaceDecl*.
82
    Namespace,
83
84
    /// A namespace alias, stored as a NamespaceAliasDecl*.
85
    NamespaceAlias,
86
87
    /// A type, stored as a Type*.
88
    TypeSpec,
89
90
    /// A type that was preceded by the 'template' keyword,
91
    /// stored as a Type*.
92
    TypeSpecWithTemplate,
93
94
    /// The global specifier '::'. There is no stored value.
95
    Global,
96
97
    /// Microsoft's '__super' specifier, stored as a CXXRecordDecl* of
98
    /// the class it appeared in.
99
    Super
100
  };
101
102
private:
103
  /// Builds the global specifier.
104
12.7M
  NestedNameSpecifier() : Prefix(nullptr, StoredIdentifier) {}
105
106
  /// Copy constructor used internally to clone nested name
107
  /// specifiers.
108
  NestedNameSpecifier(const NestedNameSpecifier &Other) = default;
109
110
  /// Either find or insert the given nested name specifier
111
  /// mockup in the given context.
112
  static NestedNameSpecifier *FindOrInsert(const ASTContext &Context,
113
                                           const NestedNameSpecifier &Mockup);
114
115
public:
116
  NestedNameSpecifier &operator=(const NestedNameSpecifier &) = delete;
117
118
  /// Builds a specifier combining a prefix and an identifier.
119
  ///
120
  /// The prefix must be dependent, since nested name specifiers
121
  /// referencing an identifier are only permitted when the identifier
122
  /// cannot be resolved.
123
  static NestedNameSpecifier *Create(const ASTContext &Context,
124
                                     NestedNameSpecifier *Prefix,
125
                                     IdentifierInfo *II);
126
127
  /// Builds a nested name specifier that names a namespace.
128
  static NestedNameSpecifier *Create(const ASTContext &Context,
129
                                     NestedNameSpecifier *Prefix,
130
                                     const NamespaceDecl *NS);
131
132
  /// Builds a nested name specifier that names a namespace alias.
133
  static NestedNameSpecifier *Create(const ASTContext &Context,
134
                                     NestedNameSpecifier *Prefix,
135
                                     NamespaceAliasDecl *Alias);
136
137
  /// Builds a nested name specifier that names a type.
138
  static NestedNameSpecifier *Create(const ASTContext &Context,
139
                                     NestedNameSpecifier *Prefix,
140
                                     bool Template, const Type *T);
141
142
  /// Builds a specifier that consists of just an identifier.
143
  ///
144
  /// The nested-name-specifier is assumed to be dependent, but has no
145
  /// prefix because the prefix is implied by something outside of the
146
  /// nested name specifier, e.g., in "x->Base::f", the "x" has a dependent
147
  /// type.
148
  static NestedNameSpecifier *Create(const ASTContext &Context,
149
                                     IdentifierInfo *II);
150
151
  /// Returns the nested name specifier representing the global
152
  /// scope.
153
  static NestedNameSpecifier *GlobalSpecifier(const ASTContext &Context);
154
155
  /// Returns the nested name specifier representing the __super scope
156
  /// for the given CXXRecordDecl.
157
  static NestedNameSpecifier *SuperSpecifier(const ASTContext &Context,
158
                                             CXXRecordDecl *RD);
159
160
  /// Return the prefix of this nested name specifier.
161
  ///
162
  /// The prefix contains all of the parts of the nested name
163
  /// specifier that preced this current specifier. For example, for a
164
  /// nested name specifier that represents "foo::bar::", the current
165
  /// specifier will contain "bar::" and the prefix will contain
166
  /// "foo::".
167
117M
  NestedNameSpecifier *getPrefix() const { return Prefix.getPointer(); }
168
169
  /// Determine what kind of nested name specifier is stored.
170
  SpecifierKind getKind() const;
171
172
  /// Retrieve the identifier stored in this nested name
173
  /// specifier.
174
50.2k
  IdentifierInfo *getAsIdentifier() const {
175
50.2k
    if (Prefix.getInt() == StoredIdentifier)
176
50.2k
      return (IdentifierInfo *)Specifier;
177
0
178
0
    return nullptr;
179
0
  }
180
181
  /// Retrieve the namespace stored in this nested name
182
  /// specifier.
183
  NamespaceDecl *getAsNamespace() const;
184
185
  /// Retrieve the namespace alias stored in this nested name
186
  /// specifier.
187
  NamespaceAliasDecl *getAsNamespaceAlias() const;
188
189
  /// Retrieve the record declaration stored in this nested name
190
  /// specifier.
191
  CXXRecordDecl *getAsRecordDecl() const;
192
193
  /// Retrieve the type stored in this nested name specifier.
194
86.9M
  const Type *getAsType() const {
195
86.9M
    if (Prefix.getInt() == StoredTypeSpec ||
196
86.9M
        
Prefix.getInt() == StoredTypeSpecWithTemplate100k
)
197
86.8M
      return (const Type *)Specifier;
198
87.3k
199
87.3k
    return nullptr;
200
87.3k
  }
201
202
  /// Whether this nested name specifier refers to a dependent
203
  /// type or not.
204
  bool isDependent() const;
205
206
  /// Whether this nested name specifier involves a template
207
  /// parameter.
208
  bool isInstantiationDependent() const;
209
210
  /// Whether this nested-name-specifier contains an unexpanded
211
  /// parameter pack (for C++11 variadic templates).
212
  bool containsUnexpandedParameterPack() const;
213
214
  /// Print this nested name specifier to the given output stream. If
215
  /// `ResolveTemplateArguments` is true, we'll print actual types, e.g.
216
  /// `ns::SomeTemplate<int, MyClass>` instead of
217
  /// `ns::SomeTemplate<Container::value_type, T>`.
218
  void print(raw_ostream &OS, const PrintingPolicy &Policy,
219
             bool ResolveTemplateArguments = false) const;
220
221
38.4M
  void Profile(llvm::FoldingSetNodeID &ID) const {
222
38.4M
    ID.AddPointer(Prefix.getOpaqueValue());
223
38.4M
    ID.AddPointer(Specifier);
224
38.4M
  }
225
226
  /// Dump the nested name specifier to standard output to aid
227
  /// in debugging.
228
  void dump(const LangOptions &LO) const;
229
  void dump() const;
230
  void dump(llvm::raw_ostream &OS) const;
231
  void dump(llvm::raw_ostream &OS, const LangOptions &LO) const;
232
};
233
234
/// A C++ nested-name-specifier augmented with source location
235
/// information.
236
class NestedNameSpecifierLoc {
237
  NestedNameSpecifier *Qualifier = nullptr;
238
  void *Data = nullptr;
239
240
  /// Determines the data length for the last component in the
241
  /// given nested-name-specifier.
242
  static unsigned getLocalDataLength(NestedNameSpecifier *Qualifier);
243
244
  /// Determines the data length for the entire
245
  /// nested-name-specifier.
246
  static unsigned getDataLength(NestedNameSpecifier *Qualifier);
247
248
public:
249
  /// Construct an empty nested-name-specifier.
250
45.4M
  NestedNameSpecifierLoc() = default;
251
252
  /// Construct a nested-name-specifier with source location information
253
  /// from
254
  NestedNameSpecifierLoc(NestedNameSpecifier *Qualifier, void *Data)
255
54.4M
      : Qualifier(Qualifier), Data(Data) {}
256
257
  /// Evaluates true when this nested-name-specifier location is
258
  /// non-empty.
259
156M
  explicit operator bool() const { return Qualifier; }
260
261
  /// Evaluates true when this nested-name-specifier location is
262
  /// empty.
263
570
  bool hasQualifier() const { return Qualifier; }
264
265
  /// Retrieve the nested-name-specifier to which this instance
266
  /// refers.
267
43.7M
  NestedNameSpecifier *getNestedNameSpecifier() const {
268
43.7M
    return Qualifier;
269
43.7M
  }
270
271
  /// Retrieve the opaque pointer that refers to source-location data.
272
17.1M
  void *getOpaqueData() const { return Data; }
273
274
  /// Retrieve the source range covering the entirety of this
275
  /// nested-name-specifier.
276
  ///
277
  /// For example, if this instance refers to a nested-name-specifier
278
  /// \c \::std::vector<int>::, the returned source range would cover
279
  /// from the initial '::' to the last '::'.
280
  SourceRange getSourceRange() const LLVM_READONLY;
281
282
  /// Retrieve the source range covering just the last part of
283
  /// this nested-name-specifier, not including the prefix.
284
  ///
285
  /// For example, if this instance refers to a nested-name-specifier
286
  /// \c \::std::vector<int>::, the returned source range would cover
287
  /// from "vector" to the last '::'.
288
  SourceRange getLocalSourceRange() const;
289
290
  /// Retrieve the location of the beginning of this
291
  /// nested-name-specifier.
292
14.3M
  SourceLocation getBeginLoc() const {
293
14.3M
    return getSourceRange().getBegin();
294
14.3M
  }
295
296
  /// Retrieve the location of the end of this
297
  /// nested-name-specifier.
298
530k
  SourceLocation getEndLoc() const {
299
530k
    return getSourceRange().getEnd();
300
530k
  }
301
302
  /// Retrieve the location of the beginning of this
303
  /// component of the nested-name-specifier.
304
3.96M
  SourceLocation getLocalBeginLoc() const {
305
3.96M
    return getLocalSourceRange().getBegin();
306
3.96M
  }
307
308
  /// Retrieve the location of the end of this component of the
309
  /// nested-name-specifier.
310
4.00M
  SourceLocation getLocalEndLoc() const {
311
4.00M
    return getLocalSourceRange().getEnd();
312
4.00M
  }
313
314
  /// Return the prefix of this nested-name-specifier.
315
  ///
316
  /// For example, if this instance refers to a nested-name-specifier
317
  /// \c \::std::vector<int>::, the prefix is \c \::std::. Note that the
318
  /// returned prefix may be empty, if this is the first component of
319
  /// the nested-name-specifier.
320
33.9M
  NestedNameSpecifierLoc getPrefix() const {
321
33.9M
    if (!Qualifier)
322
0
      return *this;
323
33.9M
324
33.9M
    return NestedNameSpecifierLoc(Qualifier->getPrefix(), Data);
325
33.9M
  }
326
327
  /// For a nested-name-specifier that refers to a type,
328
  /// retrieve the type with source-location information.
329
  TypeLoc getTypeLoc() const;
330
331
  /// Determines the data length for the entire
332
  /// nested-name-specifier.
333
13.4M
  unsigned getDataLength() const { return getDataLength(Qualifier); }
334
335
  friend bool operator==(NestedNameSpecifierLoc X,
336
2.93M
                         NestedNameSpecifierLoc Y) {
337
2.93M
    return X.Qualifier == Y.Qualifier && 
X.Data == Y.Data1.53M
;
338
2.93M
  }
339
340
  friend bool operator!=(NestedNameSpecifierLoc X,
341
30.2k
                         NestedNameSpecifierLoc Y) {
342
30.2k
    return !(X == Y);
343
30.2k
  }
344
};
345
346
/// Class that aids in the construction of nested-name-specifiers along
347
/// with source-location information for all of the components of the
348
/// nested-name-specifier.
349
class NestedNameSpecifierLocBuilder {
350
  /// The current representation of the nested-name-specifier we're
351
  /// building.
352
  NestedNameSpecifier *Representation = nullptr;
353
354
  /// Buffer used to store source-location information for the
355
  /// nested-name-specifier.
356
  ///
357
  /// Note that we explicitly manage the buffer (rather than using a
358
  /// SmallVector) because \c Declarator expects it to be possible to memcpy()
359
  /// a \c CXXScopeSpec, and CXXScopeSpec uses a NestedNameSpecifierLocBuilder.
360
  char *Buffer = nullptr;
361
362
  /// The size of the buffer used to store source-location information
363
  /// for the nested-name-specifier.
364
  unsigned BufferSize = 0;
365
366
  /// The capacity of the buffer used to store source-location
367
  /// information for the nested-name-specifier.
368
  unsigned BufferCapacity = 0;
369
370
public:
371
146M
  NestedNameSpecifierLocBuilder() = default;
372
  NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other);
373
374
  NestedNameSpecifierLocBuilder &
375
  operator=(const NestedNameSpecifierLocBuilder &Other);
376
377
164M
  ~NestedNameSpecifierLocBuilder() {
378
164M
    if (BufferCapacity)
379
8.60M
      free(Buffer);
380
164M
  }
381
382
  /// Retrieve the representation of the nested-name-specifier.
383
277M
  NestedNameSpecifier *getRepresentation() const { return Representation; }
384
385
  /// Extend the current nested-name-specifier by another
386
  /// nested-name-specifier component of the form 'type::'.
387
  ///
388
  /// \param Context The AST context in which this nested-name-specifier
389
  /// resides.
390
  ///
391
  /// \param TemplateKWLoc The location of the 'template' keyword, if present.
392
  ///
393
  /// \param TL The TypeLoc that describes the type preceding the '::'.
394
  ///
395
  /// \param ColonColonLoc The location of the trailing '::'.
396
  void Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL,
397
              SourceLocation ColonColonLoc);
398
399
  /// Extend the current nested-name-specifier by another
400
  /// nested-name-specifier component of the form 'identifier::'.
401
  ///
402
  /// \param Context The AST context in which this nested-name-specifier
403
  /// resides.
404
  ///
405
  /// \param Identifier The identifier.
406
  ///
407
  /// \param IdentifierLoc The location of the identifier.
408
  ///
409
  /// \param ColonColonLoc The location of the trailing '::'.
410
  void Extend(ASTContext &Context, IdentifierInfo *Identifier,
411
              SourceLocation IdentifierLoc, SourceLocation ColonColonLoc);
412
413
  /// Extend the current nested-name-specifier by another
414
  /// nested-name-specifier component of the form 'namespace::'.
415
  ///
416
  /// \param Context The AST context in which this nested-name-specifier
417
  /// resides.
418
  ///
419
  /// \param Namespace The namespace.
420
  ///
421
  /// \param NamespaceLoc The location of the namespace name.
422
  ///
423
  /// \param ColonColonLoc The location of the trailing '::'.
424
  void Extend(ASTContext &Context, NamespaceDecl *Namespace,
425
              SourceLocation NamespaceLoc, SourceLocation ColonColonLoc);
426
427
  /// Extend the current nested-name-specifier by another
428
  /// nested-name-specifier component of the form 'namespace-alias::'.
429
  ///
430
  /// \param Context The AST context in which this nested-name-specifier
431
  /// resides.
432
  ///
433
  /// \param Alias The namespace alias.
434
  ///
435
  /// \param AliasLoc The location of the namespace alias
436
  /// name.
437
  ///
438
  /// \param ColonColonLoc The location of the trailing '::'.
439
  void Extend(ASTContext &Context, NamespaceAliasDecl *Alias,
440
              SourceLocation AliasLoc, SourceLocation ColonColonLoc);
441
442
  /// Turn this (empty) nested-name-specifier into the global
443
  /// nested-name-specifier '::'.
444
  void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc);
445
446
  /// Turns this (empty) nested-name-specifier into '__super'
447
  /// nested-name-specifier.
448
  ///
449
  /// \param Context The AST context in which this nested-name-specifier
450
  /// resides.
451
  ///
452
  /// \param RD The declaration of the class in which nested-name-specifier
453
  /// appeared.
454
  ///
455
  /// \param SuperLoc The location of the '__super' keyword.
456
  /// name.
457
  ///
458
  /// \param ColonColonLoc The location of the trailing '::'.
459
  void MakeSuper(ASTContext &Context, CXXRecordDecl *RD,
460
                 SourceLocation SuperLoc, SourceLocation ColonColonLoc);
461
462
  /// Make a new nested-name-specifier from incomplete source-location
463
  /// information.
464
  ///
465
  /// This routine should be used very, very rarely, in cases where we
466
  /// need to synthesize a nested-name-specifier. Most code should instead use
467
  /// \c Adopt() with a proper \c NestedNameSpecifierLoc.
468
  void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier,
469
                   SourceRange R);
470
471
  /// Adopt an existing nested-name-specifier (with source-range
472
  /// information).
473
  void Adopt(NestedNameSpecifierLoc Other);
474
475
  /// Retrieve the source range covered by this nested-name-specifier.
476
0
  SourceRange getSourceRange() const LLVM_READONLY {
477
0
    return NestedNameSpecifierLoc(Representation, Buffer).getSourceRange();
478
0
  }
479
480
  /// Retrieve a nested-name-specifier with location information,
481
  /// copied into the given AST context.
482
  ///
483
  /// \param Context The context into which this nested-name-specifier will be
484
  /// copied.
485
  NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const;
486
487
  /// Retrieve a nested-name-specifier with location
488
  /// information based on the information in this builder.
489
  ///
490
  /// This loc will contain references to the builder's internal data and may
491
  /// be invalidated by any change to the builder.
492
3.09M
  NestedNameSpecifierLoc getTemporary() const {
493
3.09M
    return NestedNameSpecifierLoc(Representation, Buffer);
494
3.09M
  }
495
496
  /// Clear out this builder, and prepare it to build another
497
  /// nested-name-specifier with source-location information.
498
33.7M
  void Clear() {
499
33.7M
    Representation = nullptr;
500
33.7M
    BufferSize = 0;
501
33.7M
  }
502
503
  /// Retrieve the underlying buffer.
504
  ///
505
  /// \returns A pair containing a pointer to the buffer of source-location
506
  /// data and the size of the source-location data that resides in that
507
  /// buffer.
508
21.8M
  std::pair<char *, unsigned> getBuffer() const {
509
21.8M
    return std::make_pair(Buffer, BufferSize);
510
21.8M
  }
511
};
512
513
/// Insertion operator for diagnostics.  This allows sending
514
/// NestedNameSpecifiers into a diagnostic with <<.
515
inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
516
361
                                           NestedNameSpecifier *NNS) {
517
361
  DB.AddTaggedVal(reinterpret_cast<intptr_t>(NNS),
518
361
                  DiagnosticsEngine::ak_nestednamespec);
519
361
  return DB;
520
361
}
521
522
} // namespace clang
523
524
#endif // LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H