1 //===--- NestedNameSpecifier.cpp - 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 #include "clang/AST/NestedNameSpecifier.h" 15 #include "clang/AST/ASTContext.h" 16 #include "clang/AST/Decl.h" 17 #include "clang/AST/PrettyPrinter.h" 18 #include "clang/AST/Type.h" 19 #include "llvm/Support/raw_ostream.h" 20 #include <cassert> 21 22 using namespace clang; 23 24 NestedNameSpecifier * 25 NestedNameSpecifier::FindOrInsert(const ASTContext &Context, 26 const NestedNameSpecifier &Mockup) { 27 llvm::FoldingSetNodeID ID; 28 Mockup.Profile(ID); 29 30 void *InsertPos = 0; 31 NestedNameSpecifier *NNS 32 = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos); 33 if (!NNS) { 34 NNS = new (Context, 4) NestedNameSpecifier(Mockup); 35 Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos); 36 } 37 38 return NNS; 39 } 40 41 NestedNameSpecifier * 42 NestedNameSpecifier::Create(const ASTContext &Context, 43 NestedNameSpecifier *Prefix, IdentifierInfo *II) { 44 assert(II && "Identifier cannot be NULL"); 45 assert((!Prefix || Prefix->isDependent()) && "Prefix must be dependent"); 46 47 NestedNameSpecifier Mockup; 48 Mockup.Prefix.setPointer(Prefix); 49 Mockup.Prefix.setInt(Identifier); 50 Mockup.Specifier = II; 51 return FindOrInsert(Context, Mockup); 52 } 53 54 NestedNameSpecifier * 55 NestedNameSpecifier::Create(const ASTContext &Context, 56 NestedNameSpecifier *Prefix, NamespaceDecl *NS) { 57 assert(NS && "Namespace cannot be NULL"); 58 assert((!Prefix || 59 (Prefix->getAsType() == 0 && Prefix->getAsIdentifier() == 0)) && 60 "Broken nested name specifier"); 61 NestedNameSpecifier Mockup; 62 Mockup.Prefix.setPointer(Prefix); 63 Mockup.Prefix.setInt(Namespace); 64 Mockup.Specifier = NS; 65 return FindOrInsert(Context, Mockup); 66 } 67 68 NestedNameSpecifier * 69 NestedNameSpecifier::Create(const ASTContext &Context, 70 NestedNameSpecifier *Prefix, 71 bool Template, const Type *T) { 72 assert(T && "Type cannot be NULL"); 73 NestedNameSpecifier Mockup; 74 Mockup.Prefix.setPointer(Prefix); 75 Mockup.Prefix.setInt(Template? TypeSpecWithTemplate : TypeSpec); 76 Mockup.Specifier = const_cast<Type*>(T); 77 return FindOrInsert(Context, Mockup); 78 } 79 80 NestedNameSpecifier * 81 NestedNameSpecifier::Create(const ASTContext &Context, IdentifierInfo *II) { 82 assert(II && "Identifier cannot be NULL"); 83 NestedNameSpecifier Mockup; 84 Mockup.Prefix.setPointer(0); 85 Mockup.Prefix.setInt(Identifier); 86 Mockup.Specifier = II; 87 return FindOrInsert(Context, Mockup); 88 } 89 90 NestedNameSpecifier * 91 NestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) { 92 if (!Context.GlobalNestedNameSpecifier) 93 Context.GlobalNestedNameSpecifier = new (Context, 4) NestedNameSpecifier(); 94 return Context.GlobalNestedNameSpecifier; 95 } 96 97 /// \brief Whether this nested name specifier refers to a dependent 98 /// type or not. 99 bool NestedNameSpecifier::isDependent() const { 100 switch (getKind()) { 101 case Identifier: 102 // Identifier specifiers always represent dependent types 103 return true; 104 105 case Namespace: 106 case Global: 107 return false; 108 109 case TypeSpec: 110 case TypeSpecWithTemplate: 111 return getAsType()->isDependentType(); 112 } 113 114 // Necessary to suppress a GCC warning. 115 return false; 116 } 117 118 bool NestedNameSpecifier::containsUnexpandedParameterPack() const { 119 switch (getKind()) { 120 case Identifier: 121 return getPrefix() && getPrefix()->containsUnexpandedParameterPack(); 122 123 case Namespace: 124 case Global: 125 return false; 126 127 case TypeSpec: 128 case TypeSpecWithTemplate: 129 return getAsType()->containsUnexpandedParameterPack(); 130 } 131 132 // Necessary to suppress a GCC warning. 133 return false; 134 } 135 136 /// \brief Print this nested name specifier to the given output 137 /// stream. 138 void 139 NestedNameSpecifier::print(llvm::raw_ostream &OS, 140 const PrintingPolicy &Policy) const { 141 if (getPrefix()) 142 getPrefix()->print(OS, Policy); 143 144 switch (getKind()) { 145 case Identifier: 146 OS << getAsIdentifier()->getName(); 147 break; 148 149 case Namespace: 150 OS << getAsNamespace()->getIdentifier()->getName(); 151 break; 152 153 case Global: 154 break; 155 156 case TypeSpecWithTemplate: 157 OS << "template "; 158 // Fall through to print the type. 159 160 case TypeSpec: { 161 std::string TypeStr; 162 const Type *T = getAsType(); 163 164 PrintingPolicy InnerPolicy(Policy); 165 InnerPolicy.SuppressScope = true; 166 167 // Nested-name-specifiers are intended to contain minimally-qualified 168 // types. An actual ElaboratedType will not occur, since we'll store 169 // just the type that is referred to in the nested-name-specifier (e.g., 170 // a TypedefType, TagType, etc.). However, when we are dealing with 171 // dependent template-id types (e.g., Outer<T>::template Inner<U>), 172 // the type requires its own nested-name-specifier for uniqueness, so we 173 // suppress that nested-name-specifier during printing. 174 assert(!isa<ElaboratedType>(T) && 175 "Elaborated type in nested-name-specifier"); 176 if (const TemplateSpecializationType *SpecType 177 = dyn_cast<TemplateSpecializationType>(T)) { 178 // Print the template name without its corresponding 179 // nested-name-specifier. 180 SpecType->getTemplateName().print(OS, InnerPolicy, true); 181 182 // Print the template argument list. 183 TypeStr = TemplateSpecializationType::PrintTemplateArgumentList( 184 SpecType->getArgs(), 185 SpecType->getNumArgs(), 186 InnerPolicy); 187 } else { 188 // Print the type normally 189 TypeStr = QualType(T, 0).getAsString(InnerPolicy); 190 } 191 OS << TypeStr; 192 break; 193 } 194 } 195 196 OS << "::"; 197 } 198 199 void NestedNameSpecifier::dump(const LangOptions &LO) { 200 print(llvm::errs(), PrintingPolicy(LO)); 201 } 202