NestedNameSpecifier.h revision 1eb4433ac451dc16f4133a88af2d002ac26c58ef
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 "clang/Basic/Diagnostic.h" 18#include "llvm/ADT/FoldingSet.h" 19#include "llvm/ADT/PointerIntPair.h" 20 21namespace llvm { 22 class raw_ostream; 23} 24 25namespace clang { 26 27class ASTContext; 28class NamespaceDecl; 29class IdentifierInfo; 30struct PrintingPolicy; 31class Type; 32class LangOptions; 33 34/// \brief Represents a C++ nested name specifier, such as 35/// "::std::vector<int>::". 36/// 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 42/// first specifier). 43class NestedNameSpecifier : public llvm::FoldingSetNode { 44 /// \brief The nested name specifier that precedes this nested name 45 /// specifier. 46 /// 47 /// The pointer is the nested-name-specifier that precedes this 48 /// one. The integer stores one of the first four values of type 49 /// SpecifierKind. 50 llvm::PointerIntPair<NestedNameSpecifier *, 2> Prefix; 51 52 /// \brief The last component in the nested name specifier, which 53 /// can be an identifier, a declaration, or a type. 54 /// 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. 59 void* Specifier; 60 61public: 62 /// \brief The kind of specifier that completes this nested name 63 /// specifier. 64 enum SpecifierKind { 65 /// \brief An identifier, stored as an IdentifierInfo*. 66 Identifier = 0, 67 /// \brief A namespace, stored as a Namespace*. 68 Namespace = 1, 69 /// \brief A type, stored as a Type*. 70 TypeSpec = 2, 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. 75 Global = 4 76 }; 77 78private: 79 /// \brief Builds the global specifier. 80 NestedNameSpecifier() : Prefix(0, 0), Specifier(0) { } 81 82 /// \brief Copy constructor used internally to clone nested name 83 /// specifiers. 84 NestedNameSpecifier(const NestedNameSpecifier &Other) 85 : llvm::FoldingSetNode(Other), Prefix(Other.Prefix), 86 Specifier(Other.Specifier) { 87 } 88 89 NestedNameSpecifier &operator=(const NestedNameSpecifier &); // do not implement 90 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); 95 96public: 97 /// \brief Builds a specifier combining a prefix and an identifier. 98 /// 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, 104 IdentifierInfo *II); 105 106 /// \brief Builds a nested name specifier that names a namespace. 107 static NestedNameSpecifier *Create(ASTContext &Context, 108 NestedNameSpecifier *Prefix, 109 NamespaceDecl *NS); 110 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); 115 116 /// \brief Builds a specifier that consists of just an identifier. 117 /// 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 121 /// type. 122 static NestedNameSpecifier *Create(ASTContext &Context, IdentifierInfo *II); 123 124 /// \brief Returns the nested name specifier representing the global 125 /// scope. 126 static NestedNameSpecifier *GlobalSpecifier(ASTContext &Context); 127 128 /// \brief Return the prefix of this nested name specifier. 129 /// 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 134 /// "foo::". 135 NestedNameSpecifier *getPrefix() const { return Prefix.getPointer(); } 136 137 /// \brief Determine what kind of nested name specifier is stored. 138 SpecifierKind getKind() const { 139 if (Specifier == 0) 140 return Global; 141 return (SpecifierKind)Prefix.getInt(); 142 } 143 144 /// \brief Retrieve the identifier stored in this nested name 145 /// specifier. 146 IdentifierInfo *getAsIdentifier() const { 147 if (Prefix.getInt() == Identifier) 148 return (IdentifierInfo *)Specifier; 149 150 return 0; 151 } 152 153 /// \brief Retrieve the namespace stored in this nested name 154 /// specifier. 155 NamespaceDecl *getAsNamespace() const { 156 if (Prefix.getInt() == Namespace) 157 return (NamespaceDecl *)Specifier; 158 159 return 0; 160 } 161 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; 167 168 return 0; 169 } 170 171 /// \brief Whether this nested name specifier refers to a dependent 172 /// type or not. 173 bool isDependent() const; 174 175 /// \brief Print this nested name specifier to the given output 176 /// stream. 177 void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const; 178 179 void Profile(llvm::FoldingSetNodeID &ID) const { 180 ID.AddPointer(Prefix.getOpaqueValue()); 181 ID.AddPointer(Specifier); 182 } 183 184 void Destroy(ASTContext &Context); 185 186 /// \brief Dump the nested name specifier to standard output to aid 187 /// in debugging. 188 void dump(const LangOptions &LO); 189}; 190 191/// Insertion operator for diagnostics. This allows sending NestedNameSpecifiers 192/// into a diagnostic with <<. 193inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 194 NestedNameSpecifier *NNS) { 195 DB.AddTaggedVal(reinterpret_cast<intptr_t>(NNS), 196 Diagnostic::ak_nestednamespec); 197 return DB; 198} 199 200} 201 202#endif 203