NestedNameSpecifier.h revision 3b4ea54acf01f72f6eb74d96689dda86d950228f
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; 29struct 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