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