NestedNameSpecifier.cpp revision 208600
1193326Sed//===--- NestedNameSpecifier.cpp - C++ nested name specifiers -----*- C++ -*-=// 2193326Sed// 3193326Sed// The LLVM Compiler Infrastructure 4193326Sed// 5193326Sed// This file is distributed under the University of Illinois Open Source 6193326Sed// License. See LICENSE.TXT for details. 7193326Sed// 8193326Sed//===----------------------------------------------------------------------===// 9193326Sed// 10193326Sed// This file defines the NestedNameSpecifier class, which represents 11193326Sed// a C++ nested-name-specifier. 12193326Sed// 13193326Sed//===----------------------------------------------------------------------===// 14193326Sed#include "clang/AST/NestedNameSpecifier.h" 15193326Sed#include "clang/AST/ASTContext.h" 16193326Sed#include "clang/AST/Decl.h" 17193326Sed#include "clang/AST/PrettyPrinter.h" 18193326Sed#include "clang/AST/Type.h" 19193326Sed#include "llvm/Support/raw_ostream.h" 20193326Sed#include <cassert> 21193326Sed 22193326Sedusing namespace clang; 23193326Sed 24193326SedNestedNameSpecifier * 25198092SrdivackyNestedNameSpecifier::FindOrInsert(ASTContext &Context, 26193326Sed const NestedNameSpecifier &Mockup) { 27193326Sed llvm::FoldingSetNodeID ID; 28193326Sed Mockup.Profile(ID); 29193326Sed 30193326Sed void *InsertPos = 0; 31198092Srdivacky NestedNameSpecifier *NNS 32193326Sed = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos); 33193326Sed if (!NNS) { 34193326Sed NNS = new (Context, 4) NestedNameSpecifier(Mockup); 35193326Sed Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos); 36193326Sed } 37193326Sed 38193326Sed return NNS; 39193326Sed} 40193326Sed 41193326SedNestedNameSpecifier * 42198092SrdivackyNestedNameSpecifier::Create(ASTContext &Context, NestedNameSpecifier *Prefix, 43193326Sed IdentifierInfo *II) { 44193326Sed assert(II && "Identifier cannot be NULL"); 45198092Srdivacky assert((!Prefix || Prefix->isDependent()) && "Prefix must be dependent"); 46193326Sed 47193326Sed NestedNameSpecifier Mockup; 48193326Sed Mockup.Prefix.setPointer(Prefix); 49193326Sed Mockup.Prefix.setInt(Identifier); 50193326Sed Mockup.Specifier = II; 51193326Sed return FindOrInsert(Context, Mockup); 52193326Sed} 53193326Sed 54193326SedNestedNameSpecifier * 55198092SrdivackyNestedNameSpecifier::Create(ASTContext &Context, NestedNameSpecifier *Prefix, 56193326Sed NamespaceDecl *NS) { 57193326Sed assert(NS && "Namespace cannot be NULL"); 58198092Srdivacky assert((!Prefix || 59193326Sed (Prefix->getAsType() == 0 && Prefix->getAsIdentifier() == 0)) && 60193326Sed "Broken nested name specifier"); 61193326Sed NestedNameSpecifier Mockup; 62193326Sed Mockup.Prefix.setPointer(Prefix); 63193326Sed Mockup.Prefix.setInt(Namespace); 64193326Sed Mockup.Specifier = NS; 65193326Sed return FindOrInsert(Context, Mockup); 66193326Sed} 67193326Sed 68193326SedNestedNameSpecifier * 69193326SedNestedNameSpecifier::Create(ASTContext &Context, NestedNameSpecifier *Prefix, 70193326Sed bool Template, Type *T) { 71193326Sed assert(T && "Type cannot be NULL"); 72193326Sed NestedNameSpecifier Mockup; 73193326Sed Mockup.Prefix.setPointer(Prefix); 74193326Sed Mockup.Prefix.setInt(Template? TypeSpecWithTemplate : TypeSpec); 75193326Sed Mockup.Specifier = T; 76193326Sed return FindOrInsert(Context, Mockup); 77193326Sed} 78198092Srdivacky 79198092SrdivackyNestedNameSpecifier * 80198092SrdivackyNestedNameSpecifier::Create(ASTContext &Context, IdentifierInfo *II) { 81198092Srdivacky assert(II && "Identifier cannot be NULL"); 82198092Srdivacky NestedNameSpecifier Mockup; 83198092Srdivacky Mockup.Prefix.setPointer(0); 84198092Srdivacky Mockup.Prefix.setInt(Identifier); 85198092Srdivacky Mockup.Specifier = II; 86198092Srdivacky return FindOrInsert(Context, Mockup); 87198092Srdivacky} 88198092Srdivacky 89193326SedNestedNameSpecifier *NestedNameSpecifier::GlobalSpecifier(ASTContext &Context) { 90193326Sed if (!Context.GlobalNestedNameSpecifier) 91193326Sed Context.GlobalNestedNameSpecifier = new (Context, 4) NestedNameSpecifier(); 92193326Sed return Context.GlobalNestedNameSpecifier; 93193326Sed} 94193326Sed 95193326Sed/// \brief Whether this nested name specifier refers to a dependent 96193326Sed/// type or not. 97193326Sedbool NestedNameSpecifier::isDependent() const { 98193326Sed switch (getKind()) { 99193326Sed case Identifier: 100193326Sed // Identifier specifiers always represent dependent types 101193326Sed return true; 102193326Sed 103193326Sed case Namespace: 104193326Sed case Global: 105193326Sed return false; 106193326Sed 107193326Sed case TypeSpec: 108193326Sed case TypeSpecWithTemplate: 109193326Sed return getAsType()->isDependentType(); 110193326Sed } 111193326Sed 112193326Sed // Necessary to suppress a GCC warning. 113193326Sed return false; 114193326Sed} 115193326Sed 116193326Sed/// \brief Print this nested name specifier to the given output 117193326Sed/// stream. 118198092Srdivackyvoid 119198092SrdivackyNestedNameSpecifier::print(llvm::raw_ostream &OS, 120193326Sed const PrintingPolicy &Policy) const { 121193326Sed if (getPrefix()) 122193326Sed getPrefix()->print(OS, Policy); 123193326Sed 124193326Sed switch (getKind()) { 125193326Sed case Identifier: 126193326Sed OS << getAsIdentifier()->getName(); 127193326Sed break; 128193326Sed 129193326Sed case Namespace: 130193326Sed OS << getAsNamespace()->getIdentifier()->getName(); 131193326Sed break; 132193326Sed 133193326Sed case Global: 134193326Sed break; 135193326Sed 136193326Sed case TypeSpecWithTemplate: 137193326Sed OS << "template "; 138193326Sed // Fall through to print the type. 139193326Sed 140193326Sed case TypeSpec: { 141193326Sed std::string TypeStr; 142193326Sed Type *T = getAsType(); 143193326Sed 144193326Sed PrintingPolicy InnerPolicy(Policy); 145198092Srdivacky InnerPolicy.SuppressScope = true; 146198092Srdivacky 147198092Srdivacky // Nested-name-specifiers are intended to contain minimally-qualified 148208600Srdivacky // types. An actual ElaboratedType will not occur, since we'll store 149198092Srdivacky // just the type that is referred to in the nested-name-specifier (e.g., 150198092Srdivacky // a TypedefType, TagType, etc.). However, when we are dealing with 151198092Srdivacky // dependent template-id types (e.g., Outer<T>::template Inner<U>), 152198092Srdivacky // the type requires its own nested-name-specifier for uniqueness, so we 153198092Srdivacky // suppress that nested-name-specifier during printing. 154208600Srdivacky assert(!isa<ElaboratedType>(T) && 155208600Srdivacky "Elaborated type in nested-name-specifier"); 156198092Srdivacky if (const TemplateSpecializationType *SpecType 157198092Srdivacky = dyn_cast<TemplateSpecializationType>(T)) { 158198092Srdivacky // Print the template name without its corresponding 159198092Srdivacky // nested-name-specifier. 160198092Srdivacky SpecType->getTemplateName().print(OS, InnerPolicy, true); 161198092Srdivacky 162198092Srdivacky // Print the template argument list. 163198092Srdivacky TypeStr = TemplateSpecializationType::PrintTemplateArgumentList( 164198092Srdivacky SpecType->getArgs(), 165198092Srdivacky SpecType->getNumArgs(), 166198092Srdivacky InnerPolicy); 167198092Srdivacky } else { 168198092Srdivacky // Print the type normally 169199482Srdivacky TypeStr = QualType(T, 0).getAsString(InnerPolicy); 170198092Srdivacky } 171193326Sed OS << TypeStr; 172193326Sed break; 173193326Sed } 174193326Sed } 175193326Sed 176193326Sed OS << "::"; 177193326Sed} 178193326Sed 179193326Sedvoid NestedNameSpecifier::Destroy(ASTContext &Context) { 180193326Sed this->~NestedNameSpecifier(); 181193326Sed Context.Deallocate((void *)this); 182193326Sed} 183193326Sed 184195341Sedvoid NestedNameSpecifier::dump(const LangOptions &LO) { 185195341Sed print(llvm::errs(), PrintingPolicy(LO)); 186193326Sed} 187