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