NestedNameSpecifier.h revision e4f2142d00fa5fdb580c4e2413da91882d955381
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#ifndef LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
15#define LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H
16
17#include "llvm/ADT/FoldingSet.h"
18#include "llvm/ADT/PointerIntPair.h"
19
20namespace llvm {
21  class raw_ostream;
22}
23
24namespace clang {
25
26class ASTContext;
27class NamespaceDecl;
28class IdentifierInfo;
29class PrintingPolicy;
30class Type;
31class LangOptions;
32
33/// \brief Represents a C++ nested name specifier, such as
34/// "::std::vector<int>::".
35///
36/// C++ nested name specifiers are the prefixes to qualified
37/// namespaces. For example, "foo::" in "foo::x" is a nested name
38/// specifier. Nested name specifiers are made up of a sequence of
39/// specifiers, each of which can be a namespace, type, identifier
40/// (for dependent names), or the global specifier ('::', must be the
41/// first specifier).
42class NestedNameSpecifier : public llvm::FoldingSetNode {
43  /// \brief The nested name specifier that precedes this nested name
44  /// specifier.
45  ///
46  /// The pointer is the nested-name-specifier that precedes this
47  /// one. The integer stores one of the first four values of type
48  /// SpecifierKind.
49  llvm::PointerIntPair<NestedNameSpecifier *, 2> Prefix;
50
51  /// \brief The last component in the nested name specifier, which
52  /// can be an identifier, a declaration, or a type.
53  ///
54  /// When the pointer is NULL, this specifier represents the global
55  /// specifier '::'. Otherwise, the pointer is one of
56  /// IdentifierInfo*, Namespace*, or Type*, depending on the kind of
57  /// specifier as encoded within the prefix.
58  void* Specifier;
59
60public:
61  /// \brief The kind of specifier that completes this nested name
62  /// specifier.
63  enum SpecifierKind {
64    /// \brief An identifier, stored as an IdentifierInfo*.
65    Identifier = 0,
66    /// \brief A namespace, stored as a Namespace*.
67    Namespace = 1,
68    /// \brief A type, stored as a Type*.
69    TypeSpec = 2,
70    /// \brief A type that was preceded by the 'template' keyword,
71    /// stored as a Type*.
72    TypeSpecWithTemplate = 3,
73    /// \brief The global specifier '::'. There is no stored value.
74    Global = 4
75  };
76
77private:
78  /// \brief Builds the global specifier.
79  NestedNameSpecifier() : Prefix(0, 0), Specifier(0) { }
80
81  /// \brief Copy constructor used internally to clone nested name
82  /// specifiers.
83  NestedNameSpecifier(const NestedNameSpecifier &Other)
84    : llvm::FoldingSetNode(Other), Prefix(Other.Prefix),
85      Specifier(Other.Specifier) {
86  }
87
88  NestedNameSpecifier &operator=(const NestedNameSpecifier &); // do not implement
89
90  /// \brief Either find or insert the given nested name specifier
91  /// mockup in the given context.
92  static NestedNameSpecifier *FindOrInsert(ASTContext &Context,
93                                           const NestedNameSpecifier &Mockup);
94
95public:
96  /// \brief Builds a specifier combining a prefix and an identifier.
97  ///
98  /// The prefix must be dependent, since nested name specifiers
99  /// referencing an identifier are only permitted when the identifier
100  /// cannot be resolved.
101  static NestedNameSpecifier *Create(ASTContext &Context,
102                                     NestedNameSpecifier *Prefix,
103                                     IdentifierInfo *II);
104
105  /// \brief Builds a nested name specifier that names a namespace.
106  static NestedNameSpecifier *Create(ASTContext &Context,
107                                     NestedNameSpecifier *Prefix,
108                                     NamespaceDecl *NS);
109
110  /// \brief Builds a nested name specifier that names a type.
111  static NestedNameSpecifier *Create(ASTContext &Context,
112                                     NestedNameSpecifier *Prefix,
113                                     bool Template, Type *T);
114
115  /// \brief Returns the nested name specifier representing the global
116  /// scope.
117  static NestedNameSpecifier *GlobalSpecifier(ASTContext &Context);
118
119  /// \brief Return the prefix of this nested name specifier.
120  ///
121  /// The prefix contains all of the parts of the nested name
122  /// specifier that preced this current specifier. For example, for a
123  /// nested name specifier that represents "foo::bar::", the current
124  /// specifier will contain "bar::" and the prefix will contain
125  /// "foo::".
126  NestedNameSpecifier *getPrefix() const { return Prefix.getPointer(); }
127
128  /// \brief Determine what kind of nested name specifier is stored.
129  SpecifierKind getKind() const {
130    if (Specifier == 0)
131      return Global;
132    return (SpecifierKind)Prefix.getInt();
133  }
134
135  /// \brief Retrieve the identifier stored in this nested name
136  /// specifier.
137  IdentifierInfo *getAsIdentifier() const {
138    if (Prefix.getInt() == Identifier)
139      return (IdentifierInfo *)Specifier;
140
141    return 0;
142  }
143
144  /// \brief Retrieve the namespace stored in this nested name
145  /// specifier.
146  NamespaceDecl *getAsNamespace() const {
147    if (Prefix.getInt() == Namespace)
148      return (NamespaceDecl *)Specifier;
149
150    return 0;
151  }
152
153  /// \brief Retrieve the type stored in this nested name specifier.
154  Type *getAsType() const {
155    if (Prefix.getInt() == TypeSpec ||
156        Prefix.getInt() == TypeSpecWithTemplate)
157      return (Type *)Specifier;
158
159    return 0;
160  }
161
162  /// \brief Whether this nested name specifier refers to a dependent
163  /// type or not.
164  bool isDependent() const;
165
166  /// \brief Print this nested name specifier to the given output
167  /// stream.
168  void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const;
169
170  void Profile(llvm::FoldingSetNodeID &ID) const {
171    ID.AddPointer(Prefix.getOpaqueValue());
172    ID.AddPointer(Specifier);
173  }
174
175  void Destroy(ASTContext &Context);
176
177  /// \brief Dump the nested name specifier to standard output to aid
178  /// in debugging.
179  void dump(const LangOptions &LO);
180};
181
182}
183
184#endif
185