NestedNameSpecifier.cpp revision 219077
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" 17219077Sdim#include "clang/AST/DeclCXX.h" 18193326Sed#include "clang/AST/PrettyPrinter.h" 19193326Sed#include "clang/AST/Type.h" 20219077Sdim#include "clang/AST/TypeLoc.h" 21193326Sed#include "llvm/Support/raw_ostream.h" 22193326Sed#include <cassert> 23193326Sed 24193326Sedusing namespace clang; 25193326Sed 26193326SedNestedNameSpecifier * 27218893SdimNestedNameSpecifier::FindOrInsert(const ASTContext &Context, 28193326Sed const NestedNameSpecifier &Mockup) { 29193326Sed llvm::FoldingSetNodeID ID; 30193326Sed Mockup.Profile(ID); 31193326Sed 32193326Sed void *InsertPos = 0; 33198092Srdivacky NestedNameSpecifier *NNS 34193326Sed = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos); 35193326Sed if (!NNS) { 36193326Sed NNS = new (Context, 4) NestedNameSpecifier(Mockup); 37193326Sed Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos); 38193326Sed } 39193326Sed 40193326Sed return NNS; 41193326Sed} 42193326Sed 43193326SedNestedNameSpecifier * 44218893SdimNestedNameSpecifier::Create(const ASTContext &Context, 45218893Sdim NestedNameSpecifier *Prefix, IdentifierInfo *II) { 46193326Sed assert(II && "Identifier cannot be NULL"); 47198092Srdivacky assert((!Prefix || Prefix->isDependent()) && "Prefix must be dependent"); 48193326Sed 49193326Sed NestedNameSpecifier Mockup; 50193326Sed Mockup.Prefix.setPointer(Prefix); 51219077Sdim Mockup.Prefix.setInt(StoredIdentifier); 52193326Sed Mockup.Specifier = II; 53193326Sed return FindOrInsert(Context, Mockup); 54193326Sed} 55193326Sed 56193326SedNestedNameSpecifier * 57218893SdimNestedNameSpecifier::Create(const ASTContext &Context, 58218893Sdim NestedNameSpecifier *Prefix, NamespaceDecl *NS) { 59193326Sed assert(NS && "Namespace cannot be NULL"); 60198092Srdivacky assert((!Prefix || 61193326Sed (Prefix->getAsType() == 0 && Prefix->getAsIdentifier() == 0)) && 62193326Sed "Broken nested name specifier"); 63193326Sed NestedNameSpecifier Mockup; 64193326Sed Mockup.Prefix.setPointer(Prefix); 65219077Sdim Mockup.Prefix.setInt(StoredNamespaceOrAlias); 66193326Sed Mockup.Specifier = NS; 67193326Sed return FindOrInsert(Context, Mockup); 68193326Sed} 69193326Sed 70193326SedNestedNameSpecifier * 71218893SdimNestedNameSpecifier::Create(const ASTContext &Context, 72219077Sdim NestedNameSpecifier *Prefix, 73219077Sdim NamespaceAliasDecl *Alias) { 74219077Sdim assert(Alias && "Namespace alias cannot be NULL"); 75219077Sdim assert((!Prefix || 76219077Sdim (Prefix->getAsType() == 0 && Prefix->getAsIdentifier() == 0)) && 77219077Sdim "Broken nested name specifier"); 78219077Sdim NestedNameSpecifier Mockup; 79219077Sdim Mockup.Prefix.setPointer(Prefix); 80219077Sdim Mockup.Prefix.setInt(StoredNamespaceOrAlias); 81219077Sdim Mockup.Specifier = Alias; 82219077Sdim return FindOrInsert(Context, Mockup); 83219077Sdim} 84219077Sdim 85219077SdimNestedNameSpecifier * 86219077SdimNestedNameSpecifier::Create(const ASTContext &Context, 87218893Sdim NestedNameSpecifier *Prefix, 88218893Sdim bool Template, const Type *T) { 89193326Sed assert(T && "Type cannot be NULL"); 90193326Sed NestedNameSpecifier Mockup; 91193326Sed Mockup.Prefix.setPointer(Prefix); 92219077Sdim Mockup.Prefix.setInt(Template? StoredTypeSpecWithTemplate : StoredTypeSpec); 93218893Sdim Mockup.Specifier = const_cast<Type*>(T); 94193326Sed return FindOrInsert(Context, Mockup); 95193326Sed} 96198092Srdivacky 97198092SrdivackyNestedNameSpecifier * 98218893SdimNestedNameSpecifier::Create(const ASTContext &Context, IdentifierInfo *II) { 99198092Srdivacky assert(II && "Identifier cannot be NULL"); 100198092Srdivacky NestedNameSpecifier Mockup; 101198092Srdivacky Mockup.Prefix.setPointer(0); 102219077Sdim Mockup.Prefix.setInt(StoredIdentifier); 103198092Srdivacky Mockup.Specifier = II; 104198092Srdivacky return FindOrInsert(Context, Mockup); 105198092Srdivacky} 106198092Srdivacky 107218893SdimNestedNameSpecifier * 108218893SdimNestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) { 109193326Sed if (!Context.GlobalNestedNameSpecifier) 110193326Sed Context.GlobalNestedNameSpecifier = new (Context, 4) NestedNameSpecifier(); 111193326Sed return Context.GlobalNestedNameSpecifier; 112193326Sed} 113193326Sed 114219077SdimNestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const { 115219077Sdim if (Specifier == 0) 116219077Sdim return Global; 117219077Sdim 118219077Sdim switch (Prefix.getInt()) { 119219077Sdim case StoredIdentifier: 120219077Sdim return Identifier; 121219077Sdim 122219077Sdim case StoredNamespaceOrAlias: 123219077Sdim return isa<NamespaceDecl>(static_cast<NamedDecl *>(Specifier))? Namespace 124219077Sdim : NamespaceAlias; 125219077Sdim 126219077Sdim case StoredTypeSpec: 127219077Sdim return TypeSpec; 128219077Sdim 129219077Sdim case StoredTypeSpecWithTemplate: 130219077Sdim return TypeSpecWithTemplate; 131219077Sdim } 132219077Sdim 133219077Sdim return Global; 134219077Sdim} 135219077Sdim 136219077Sdim/// \brief Retrieve the namespace stored in this nested name 137219077Sdim/// specifier. 138219077SdimNamespaceDecl *NestedNameSpecifier::getAsNamespace() const { 139219077Sdim if (Prefix.getInt() == StoredNamespaceOrAlias) 140219077Sdim return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier)); 141219077Sdim 142219077Sdim return 0; 143219077Sdim} 144219077Sdim 145219077Sdim/// \brief Retrieve the namespace alias stored in this nested name 146219077Sdim/// specifier. 147219077SdimNamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const { 148219077Sdim if (Prefix.getInt() == StoredNamespaceOrAlias) 149219077Sdim return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier)); 150219077Sdim 151219077Sdim return 0; 152219077Sdim} 153219077Sdim 154219077Sdim 155193326Sed/// \brief Whether this nested name specifier refers to a dependent 156193326Sed/// type or not. 157193326Sedbool NestedNameSpecifier::isDependent() const { 158193326Sed switch (getKind()) { 159193326Sed case Identifier: 160193326Sed // Identifier specifiers always represent dependent types 161193326Sed return true; 162193326Sed 163193326Sed case Namespace: 164219077Sdim case NamespaceAlias: 165193326Sed case Global: 166193326Sed return false; 167193326Sed 168193326Sed case TypeSpec: 169193326Sed case TypeSpecWithTemplate: 170193326Sed return getAsType()->isDependentType(); 171193326Sed } 172193326Sed 173193326Sed // Necessary to suppress a GCC warning. 174193326Sed return false; 175193326Sed} 176193326Sed 177218893Sdimbool NestedNameSpecifier::containsUnexpandedParameterPack() const { 178218893Sdim switch (getKind()) { 179218893Sdim case Identifier: 180218893Sdim return getPrefix() && getPrefix()->containsUnexpandedParameterPack(); 181218893Sdim 182218893Sdim case Namespace: 183219077Sdim case NamespaceAlias: 184218893Sdim case Global: 185218893Sdim return false; 186218893Sdim 187218893Sdim case TypeSpec: 188218893Sdim case TypeSpecWithTemplate: 189218893Sdim return getAsType()->containsUnexpandedParameterPack(); 190218893Sdim } 191218893Sdim 192218893Sdim // Necessary to suppress a GCC warning. 193218893Sdim return false; 194218893Sdim} 195218893Sdim 196193326Sed/// \brief Print this nested name specifier to the given output 197193326Sed/// stream. 198198092Srdivackyvoid 199198092SrdivackyNestedNameSpecifier::print(llvm::raw_ostream &OS, 200193326Sed const PrintingPolicy &Policy) const { 201193326Sed if (getPrefix()) 202193326Sed getPrefix()->print(OS, Policy); 203193326Sed 204193326Sed switch (getKind()) { 205193326Sed case Identifier: 206193326Sed OS << getAsIdentifier()->getName(); 207193326Sed break; 208193326Sed 209193326Sed case Namespace: 210219077Sdim OS << getAsNamespace()->getName(); 211193326Sed break; 212193326Sed 213219077Sdim case NamespaceAlias: 214219077Sdim OS << getAsNamespaceAlias()->getName(); 215219077Sdim break; 216219077Sdim 217193326Sed case Global: 218193326Sed break; 219193326Sed 220193326Sed case TypeSpecWithTemplate: 221193326Sed OS << "template "; 222193326Sed // Fall through to print the type. 223193326Sed 224193326Sed case TypeSpec: { 225193326Sed std::string TypeStr; 226218893Sdim const Type *T = getAsType(); 227193326Sed 228193326Sed PrintingPolicy InnerPolicy(Policy); 229198092Srdivacky InnerPolicy.SuppressScope = true; 230198092Srdivacky 231198092Srdivacky // Nested-name-specifiers are intended to contain minimally-qualified 232208600Srdivacky // types. An actual ElaboratedType will not occur, since we'll store 233198092Srdivacky // just the type that is referred to in the nested-name-specifier (e.g., 234198092Srdivacky // a TypedefType, TagType, etc.). However, when we are dealing with 235198092Srdivacky // dependent template-id types (e.g., Outer<T>::template Inner<U>), 236198092Srdivacky // the type requires its own nested-name-specifier for uniqueness, so we 237198092Srdivacky // suppress that nested-name-specifier during printing. 238208600Srdivacky assert(!isa<ElaboratedType>(T) && 239208600Srdivacky "Elaborated type in nested-name-specifier"); 240198092Srdivacky if (const TemplateSpecializationType *SpecType 241198092Srdivacky = dyn_cast<TemplateSpecializationType>(T)) { 242198092Srdivacky // Print the template name without its corresponding 243198092Srdivacky // nested-name-specifier. 244198092Srdivacky SpecType->getTemplateName().print(OS, InnerPolicy, true); 245198092Srdivacky 246198092Srdivacky // Print the template argument list. 247198092Srdivacky TypeStr = TemplateSpecializationType::PrintTemplateArgumentList( 248198092Srdivacky SpecType->getArgs(), 249198092Srdivacky SpecType->getNumArgs(), 250198092Srdivacky InnerPolicy); 251198092Srdivacky } else { 252198092Srdivacky // Print the type normally 253199482Srdivacky TypeStr = QualType(T, 0).getAsString(InnerPolicy); 254198092Srdivacky } 255193326Sed OS << TypeStr; 256193326Sed break; 257193326Sed } 258193326Sed } 259193326Sed 260193326Sed OS << "::"; 261193326Sed} 262193326Sed 263195341Sedvoid NestedNameSpecifier::dump(const LangOptions &LO) { 264195341Sed print(llvm::errs(), PrintingPolicy(LO)); 265193326Sed} 266219077Sdim 267219077Sdimunsigned 268219077SdimNestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) { 269219077Sdim assert(Qualifier && "Expected a non-NULL qualifier"); 270219077Sdim 271219077Sdim // Location of the trailing '::'. 272219077Sdim unsigned Length = sizeof(unsigned); 273219077Sdim 274219077Sdim switch (Qualifier->getKind()) { 275219077Sdim case NestedNameSpecifier::Global: 276219077Sdim // Nothing more to add. 277219077Sdim break; 278219077Sdim 279219077Sdim case NestedNameSpecifier::Identifier: 280219077Sdim case NestedNameSpecifier::Namespace: 281219077Sdim case NestedNameSpecifier::NamespaceAlias: 282219077Sdim // The location of the identifier or namespace name. 283219077Sdim Length += sizeof(unsigned); 284219077Sdim break; 285219077Sdim 286219077Sdim case NestedNameSpecifier::TypeSpecWithTemplate: 287219077Sdim case NestedNameSpecifier::TypeSpec: 288219077Sdim // The "void*" that points at the TypeLoc data. 289219077Sdim // Note: the 'template' keyword is part of the TypeLoc. 290219077Sdim Length += sizeof(void *); 291219077Sdim break; 292219077Sdim } 293219077Sdim 294219077Sdim return Length; 295219077Sdim} 296219077Sdim 297219077Sdimunsigned 298219077SdimNestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) { 299219077Sdim unsigned Length = 0; 300219077Sdim for (; Qualifier; Qualifier = Qualifier->getPrefix()) 301219077Sdim Length += getLocalDataLength(Qualifier); 302219077Sdim return Length; 303219077Sdim} 304219077Sdim 305219077Sdimnamespace { 306219077Sdim /// \brief Load a (possibly unaligned) source location from a given address 307219077Sdim /// and offset. 308219077Sdim SourceLocation LoadSourceLocation(void *Data, unsigned Offset) { 309219077Sdim unsigned Raw; 310219077Sdim memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(unsigned)); 311219077Sdim return SourceLocation::getFromRawEncoding(Raw); 312219077Sdim } 313219077Sdim 314219077Sdim /// \brief Load a (possibly unaligned) pointer from a given address and 315219077Sdim /// offset. 316219077Sdim void *LoadPointer(void *Data, unsigned Offset) { 317219077Sdim void *Result; 318219077Sdim memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*)); 319219077Sdim return Result; 320219077Sdim } 321219077Sdim} 322219077Sdim 323219077SdimSourceRange NestedNameSpecifierLoc::getSourceRange() const { 324219077Sdim if (!Qualifier) 325219077Sdim return SourceRange(); 326219077Sdim 327219077Sdim NestedNameSpecifierLoc First = *this; 328219077Sdim while (NestedNameSpecifierLoc Prefix = First.getPrefix()) 329219077Sdim First = Prefix; 330219077Sdim 331219077Sdim return SourceRange(First.getLocalSourceRange().getBegin(), 332219077Sdim getLocalSourceRange().getEnd()); 333219077Sdim} 334219077Sdim 335219077SdimSourceRange NestedNameSpecifierLoc::getLocalSourceRange() const { 336219077Sdim if (!Qualifier) 337219077Sdim return SourceRange(); 338219077Sdim 339219077Sdim unsigned Offset = getDataLength(Qualifier->getPrefix()); 340219077Sdim switch (Qualifier->getKind()) { 341219077Sdim case NestedNameSpecifier::Global: 342219077Sdim return LoadSourceLocation(Data, Offset); 343219077Sdim 344219077Sdim case NestedNameSpecifier::Identifier: 345219077Sdim case NestedNameSpecifier::Namespace: 346219077Sdim case NestedNameSpecifier::NamespaceAlias: 347219077Sdim return SourceRange(LoadSourceLocation(Data, Offset), 348219077Sdim LoadSourceLocation(Data, Offset + sizeof(unsigned))); 349219077Sdim 350219077Sdim case NestedNameSpecifier::TypeSpecWithTemplate: 351219077Sdim case NestedNameSpecifier::TypeSpec: { 352219077Sdim // The "void*" that points at the TypeLoc data. 353219077Sdim // Note: the 'template' keyword is part of the TypeLoc. 354219077Sdim void *TypeData = LoadPointer(Data, Offset); 355219077Sdim TypeLoc TL(Qualifier->getAsType(), TypeData); 356219077Sdim return SourceRange(TL.getBeginLoc(), 357219077Sdim LoadSourceLocation(Data, Offset + sizeof(void*))); 358219077Sdim } 359219077Sdim } 360219077Sdim 361219077Sdim return SourceRange(); 362219077Sdim} 363219077Sdim 364219077SdimTypeLoc NestedNameSpecifierLoc::getTypeLoc() const { 365219077Sdim assert((Qualifier->getKind() == NestedNameSpecifier::TypeSpec || 366219077Sdim Qualifier->getKind() == NestedNameSpecifier::TypeSpecWithTemplate) && 367219077Sdim "Nested-name-specifier location is not a type"); 368219077Sdim 369219077Sdim // The "void*" that points at the TypeLoc data. 370219077Sdim unsigned Offset = getDataLength(Qualifier->getPrefix()); 371219077Sdim void *TypeData = LoadPointer(Data, Offset); 372219077Sdim return TypeLoc(Qualifier->getAsType(), TypeData); 373219077Sdim} 374