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