NestedNameSpecifier.cpp revision 465d41b92b2c862f3062c412a0538db65c6a2661
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 22using namespace clang; 23 24NestedNameSpecifier * 25NestedNameSpecifier::FindOrInsert(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 41NestedNameSpecifier * 42NestedNameSpecifier::Create(ASTContext &Context, NestedNameSpecifier *Prefix, 43 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 54NestedNameSpecifier * 55NestedNameSpecifier::Create(ASTContext &Context, NestedNameSpecifier *Prefix, 56 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 68NestedNameSpecifier * 69NestedNameSpecifier::Create(ASTContext &Context, NestedNameSpecifier *Prefix, 70 bool Template, Type *T) { 71 assert(T && "Type cannot be NULL"); 72 NestedNameSpecifier Mockup; 73 Mockup.Prefix.setPointer(Prefix); 74 Mockup.Prefix.setInt(Template? TypeSpecWithTemplate : TypeSpec); 75 Mockup.Specifier = T; 76 return FindOrInsert(Context, Mockup); 77} 78 79NestedNameSpecifier * 80NestedNameSpecifier::Create(ASTContext &Context, IdentifierInfo *II) { 81 assert(II && "Identifier cannot be NULL"); 82 NestedNameSpecifier Mockup; 83 Mockup.Prefix.setPointer(0); 84 Mockup.Prefix.setInt(Identifier); 85 Mockup.Specifier = II; 86 return FindOrInsert(Context, Mockup); 87} 88 89NestedNameSpecifier *NestedNameSpecifier::GlobalSpecifier(ASTContext &Context) { 90 if (!Context.GlobalNestedNameSpecifier) 91 Context.GlobalNestedNameSpecifier = new (Context, 4) NestedNameSpecifier(); 92 return Context.GlobalNestedNameSpecifier; 93} 94 95/// \brief Whether this nested name specifier refers to a dependent 96/// type or not. 97bool NestedNameSpecifier::isDependent() const { 98 switch (getKind()) { 99 case Identifier: 100 // Identifier specifiers always represent dependent types 101 return true; 102 103 case Namespace: 104 case Global: 105 return false; 106 107 case TypeSpec: 108 case TypeSpecWithTemplate: 109 return getAsType()->isDependentType(); 110 } 111 112 // Necessary to suppress a GCC warning. 113 return false; 114} 115 116/// \brief Print this nested name specifier to the given output 117/// stream. 118void 119NestedNameSpecifier::print(llvm::raw_ostream &OS, 120 const PrintingPolicy &Policy) const { 121 if (getPrefix()) 122 getPrefix()->print(OS, Policy); 123 124 switch (getKind()) { 125 case Identifier: 126 OS << getAsIdentifier()->getName(); 127 break; 128 129 case Namespace: 130 OS << getAsNamespace()->getIdentifier()->getName(); 131 break; 132 133 case Global: 134 break; 135 136 case TypeSpecWithTemplate: 137 OS << "template "; 138 // Fall through to print the type. 139 140 case TypeSpec: { 141 std::string TypeStr; 142 Type *T = getAsType(); 143 144 PrintingPolicy InnerPolicy(Policy); 145 InnerPolicy.SuppressScope = true; 146 147 // Nested-name-specifiers are intended to contain minimally-qualified 148 // types. An actual ElaboratedType will not occur, since we'll store 149 // just the type that is referred to in the nested-name-specifier (e.g., 150 // a TypedefType, TagType, etc.). However, when we are dealing with 151 // dependent template-id types (e.g., Outer<T>::template Inner<U>), 152 // the type requires its own nested-name-specifier for uniqueness, so we 153 // suppress that nested-name-specifier during printing. 154 assert(!isa<ElaboratedType>(T) && 155 "Elaborated type in nested-name-specifier"); 156 if (const TemplateSpecializationType *SpecType 157 = dyn_cast<TemplateSpecializationType>(T)) { 158 // Print the template name without its corresponding 159 // nested-name-specifier. 160 SpecType->getTemplateName().print(OS, InnerPolicy, true); 161 162 // Print the template argument list. 163 TypeStr = TemplateSpecializationType::PrintTemplateArgumentList( 164 SpecType->getArgs(), 165 SpecType->getNumArgs(), 166 InnerPolicy); 167 } else { 168 // Print the type normally 169 TypeStr = QualType(T, 0).getAsString(InnerPolicy); 170 } 171 OS << TypeStr; 172 break; 173 } 174 } 175 176 OS << "::"; 177} 178 179void NestedNameSpecifier::Destroy(ASTContext &Context) { 180 this->~NestedNameSpecifier(); 181 Context.Deallocate((void *)this); 182} 183 184void NestedNameSpecifier::dump(const LangOptions &LO) { 185 print(llvm::errs(), PrintingPolicy(LO)); 186} 187