1 //===--- NestedNameSpecifier.h - C++ nested name specifiers -----*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the NestedNameSpecifier class, which represents
11 // a C++ nested-name-specifier.
13 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
15 #define LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
17 #include "clang/Basic/Diagnostic.h"
18 #include "llvm/ADT/FoldingSet.h"
19 #include "llvm/ADT/PointerIntPair.h"
30 struct PrintingPolicy;
34 /// \brief Represents a C++ nested name specifier, such as
35 /// "::std::vector<int>::".
37 /// C++ nested name specifiers are the prefixes to qualified
38 /// namespaces. For example, "foo::" in "foo::x" is a nested name
39 /// specifier. Nested name specifiers are made up of a sequence of
40 /// specifiers, each of which can be a namespace, type, identifier
41 /// (for dependent names), or the global specifier ('::', must be the
43 class NestedNameSpecifier : public llvm::FoldingSetNode {
44 /// \brief The nested name specifier that precedes this nested name
47 /// The pointer is the nested-name-specifier that precedes this
48 /// one. The integer stores one of the first four values of type
50 llvm::PointerIntPair<NestedNameSpecifier *, 2> Prefix;
52 /// \brief The last component in the nested name specifier, which
53 /// can be an identifier, a declaration, or a type.
55 /// When the pointer is NULL, this specifier represents the global
56 /// specifier '::'. Otherwise, the pointer is one of
57 /// IdentifierInfo*, Namespace*, or Type*, depending on the kind of
58 /// specifier as encoded within the prefix.
62 /// \brief The kind of specifier that completes this nested name
65 /// \brief An identifier, stored as an IdentifierInfo*.
67 /// \brief A namespace, stored as a Namespace*.
69 /// \brief A type, stored as a Type*.
71 /// \brief A type that was preceded by the 'template' keyword,
72 /// stored as a Type*.
73 TypeSpecWithTemplate = 3,
74 /// \brief The global specifier '::'. There is no stored value.
79 /// \brief Builds the global specifier.
80 NestedNameSpecifier() : Prefix(0, 0), Specifier(0) { }
82 /// \brief Copy constructor used internally to clone nested name
84 NestedNameSpecifier(const NestedNameSpecifier &Other)
85 : llvm::FoldingSetNode(Other), Prefix(Other.Prefix),
86 Specifier(Other.Specifier) {
89 NestedNameSpecifier &operator=(const NestedNameSpecifier &); // do not implement
91 /// \brief Either find or insert the given nested name specifier
92 /// mockup in the given context.
93 static NestedNameSpecifier *FindOrInsert(ASTContext &Context,
94 const NestedNameSpecifier &Mockup);
97 /// \brief Builds a specifier combining a prefix and an identifier.
99 /// The prefix must be dependent, since nested name specifiers
100 /// referencing an identifier are only permitted when the identifier
101 /// cannot be resolved.
102 static NestedNameSpecifier *Create(ASTContext &Context,
103 NestedNameSpecifier *Prefix,
106 /// \brief Builds a nested name specifier that names a namespace.
107 static NestedNameSpecifier *Create(ASTContext &Context,
108 NestedNameSpecifier *Prefix,
111 /// \brief Builds a nested name specifier that names a type.
112 static NestedNameSpecifier *Create(ASTContext &Context,
113 NestedNameSpecifier *Prefix,
114 bool Template, Type *T);
116 /// \brief Builds a specifier that consists of just an identifier.
118 /// The nested-name-specifier is assumed to be dependent, but has no
119 /// prefix because the prefix is implied by something outside of the
120 /// nested name specifier, e.g., in "x->Base::f", the "x" has a dependent
122 static NestedNameSpecifier *Create(ASTContext &Context, IdentifierInfo *II);
124 /// \brief Returns the nested name specifier representing the global
126 static NestedNameSpecifier *GlobalSpecifier(ASTContext &Context);
128 /// \brief Return the prefix of this nested name specifier.
130 /// The prefix contains all of the parts of the nested name
131 /// specifier that preced this current specifier. For example, for a
132 /// nested name specifier that represents "foo::bar::", the current
133 /// specifier will contain "bar::" and the prefix will contain
135 NestedNameSpecifier *getPrefix() const { return Prefix.getPointer(); }
137 /// \brief Determine what kind of nested name specifier is stored.
138 SpecifierKind getKind() const {
141 return (SpecifierKind)Prefix.getInt();
144 /// \brief Retrieve the identifier stored in this nested name
146 IdentifierInfo *getAsIdentifier() const {
147 if (Prefix.getInt() == Identifier)
148 return (IdentifierInfo *)Specifier;
153 /// \brief Retrieve the namespace stored in this nested name
155 NamespaceDecl *getAsNamespace() const {
156 if (Prefix.getInt() == Namespace)
157 return (NamespaceDecl *)Specifier;
162 /// \brief Retrieve the type stored in this nested name specifier.
163 Type *getAsType() const {
164 if (Prefix.getInt() == TypeSpec ||
165 Prefix.getInt() == TypeSpecWithTemplate)
166 return (Type *)Specifier;
171 /// \brief Whether this nested name specifier refers to a dependent
173 bool isDependent() const;
175 /// \brief Print this nested name specifier to the given output
177 void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const;
179 void Profile(llvm::FoldingSetNodeID &ID) const {
180 ID.AddPointer(Prefix.getOpaqueValue());
181 ID.AddPointer(Specifier);
184 /// \brief Dump the nested name specifier to standard output to aid
186 void dump(const LangOptions &LO);
189 /// Insertion operator for diagnostics. This allows sending NestedNameSpecifiers
190 /// into a diagnostic with <<.
191 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
192 NestedNameSpecifier *NNS) {
193 DB.AddTaggedVal(reinterpret_cast<intptr_t>(NNS),
194 Diagnostic::ak_nestednamespec);