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