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