NestedNameSpecifier.cpp revision 344779
1327952Sdim//===- NestedNameSpecifier.cpp - C++ nested name specifiers ---------------===// 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//===----------------------------------------------------------------------===// 14327952Sdim 15193326Sed#include "clang/AST/NestedNameSpecifier.h" 16193326Sed#include "clang/AST/ASTContext.h" 17193326Sed#include "clang/AST/Decl.h" 18219077Sdim#include "clang/AST/DeclCXX.h" 19344779Sdim#include "clang/AST/DeclTemplate.h" 20193326Sed#include "clang/AST/PrettyPrinter.h" 21327952Sdim#include "clang/AST/TemplateName.h" 22193326Sed#include "clang/AST/Type.h" 23219077Sdim#include "clang/AST/TypeLoc.h" 24327952Sdim#include "clang/Basic/LLVM.h" 25327952Sdim#include "clang/Basic/LangOptions.h" 26327952Sdim#include "clang/Basic/SourceLocation.h" 27327952Sdim#include "llvm/ADT/FoldingSet.h" 28327952Sdim#include "llvm/ADT/SmallVector.h" 29327952Sdim#include "llvm/Support/Casting.h" 30327952Sdim#include "llvm/Support/Compiler.h" 31327952Sdim#include "llvm/Support/ErrorHandling.h" 32193326Sed#include "llvm/Support/raw_ostream.h" 33327952Sdim#include <algorithm> 34193326Sed#include <cassert> 35327952Sdim#include <cstdlib> 36327952Sdim#include <cstring> 37193326Sed 38193326Sedusing namespace clang; 39193326Sed 40193326SedNestedNameSpecifier * 41218893SdimNestedNameSpecifier::FindOrInsert(const ASTContext &Context, 42193326Sed const NestedNameSpecifier &Mockup) { 43193326Sed llvm::FoldingSetNodeID ID; 44193326Sed Mockup.Profile(ID); 45193326Sed 46276479Sdim void *InsertPos = nullptr; 47198092Srdivacky NestedNameSpecifier *NNS 48193326Sed = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos); 49193326Sed if (!NNS) { 50314564Sdim NNS = 51314564Sdim new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier(Mockup); 52193326Sed Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos); 53193326Sed } 54193326Sed 55193326Sed return NNS; 56193326Sed} 57193326Sed 58193326SedNestedNameSpecifier * 59218893SdimNestedNameSpecifier::Create(const ASTContext &Context, 60218893Sdim NestedNameSpecifier *Prefix, IdentifierInfo *II) { 61193326Sed assert(II && "Identifier cannot be NULL"); 62198092Srdivacky assert((!Prefix || Prefix->isDependent()) && "Prefix must be dependent"); 63193326Sed 64193326Sed NestedNameSpecifier Mockup; 65193326Sed Mockup.Prefix.setPointer(Prefix); 66219077Sdim Mockup.Prefix.setInt(StoredIdentifier); 67193326Sed Mockup.Specifier = II; 68193326Sed return FindOrInsert(Context, Mockup); 69193326Sed} 70193326Sed 71193326SedNestedNameSpecifier * 72218893SdimNestedNameSpecifier::Create(const ASTContext &Context, 73249423Sdim NestedNameSpecifier *Prefix, 74249423Sdim const NamespaceDecl *NS) { 75193326Sed assert(NS && "Namespace cannot be NULL"); 76198092Srdivacky assert((!Prefix || 77276479Sdim (Prefix->getAsType() == nullptr && 78276479Sdim Prefix->getAsIdentifier() == nullptr)) && 79193326Sed "Broken nested name specifier"); 80193326Sed NestedNameSpecifier Mockup; 81193326Sed Mockup.Prefix.setPointer(Prefix); 82280031Sdim Mockup.Prefix.setInt(StoredDecl); 83249423Sdim Mockup.Specifier = const_cast<NamespaceDecl *>(NS); 84193326Sed return FindOrInsert(Context, Mockup); 85193326Sed} 86193326Sed 87193326SedNestedNameSpecifier * 88218893SdimNestedNameSpecifier::Create(const ASTContext &Context, 89341825Sdim NestedNameSpecifier *Prefix, 90219077Sdim NamespaceAliasDecl *Alias) { 91219077Sdim assert(Alias && "Namespace alias cannot be NULL"); 92219077Sdim assert((!Prefix || 93276479Sdim (Prefix->getAsType() == nullptr && 94276479Sdim Prefix->getAsIdentifier() == nullptr)) && 95219077Sdim "Broken nested name specifier"); 96219077Sdim NestedNameSpecifier Mockup; 97219077Sdim Mockup.Prefix.setPointer(Prefix); 98280031Sdim Mockup.Prefix.setInt(StoredDecl); 99219077Sdim Mockup.Specifier = Alias; 100219077Sdim return FindOrInsert(Context, Mockup); 101219077Sdim} 102219077Sdim 103219077SdimNestedNameSpecifier * 104219077SdimNestedNameSpecifier::Create(const ASTContext &Context, 105218893Sdim NestedNameSpecifier *Prefix, 106218893Sdim bool Template, const Type *T) { 107193326Sed assert(T && "Type cannot be NULL"); 108193326Sed NestedNameSpecifier Mockup; 109193326Sed Mockup.Prefix.setPointer(Prefix); 110219077Sdim Mockup.Prefix.setInt(Template? StoredTypeSpecWithTemplate : StoredTypeSpec); 111218893Sdim Mockup.Specifier = const_cast<Type*>(T); 112193326Sed return FindOrInsert(Context, Mockup); 113193326Sed} 114198092Srdivacky 115198092SrdivackyNestedNameSpecifier * 116218893SdimNestedNameSpecifier::Create(const ASTContext &Context, IdentifierInfo *II) { 117198092Srdivacky assert(II && "Identifier cannot be NULL"); 118198092Srdivacky NestedNameSpecifier Mockup; 119276479Sdim Mockup.Prefix.setPointer(nullptr); 120219077Sdim Mockup.Prefix.setInt(StoredIdentifier); 121198092Srdivacky Mockup.Specifier = II; 122198092Srdivacky return FindOrInsert(Context, Mockup); 123198092Srdivacky} 124198092Srdivacky 125218893SdimNestedNameSpecifier * 126218893SdimNestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) { 127193326Sed if (!Context.GlobalNestedNameSpecifier) 128239462Sdim Context.GlobalNestedNameSpecifier = 129314564Sdim new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier(); 130193326Sed return Context.GlobalNestedNameSpecifier; 131193326Sed} 132193326Sed 133280031SdimNestedNameSpecifier * 134280031SdimNestedNameSpecifier::SuperSpecifier(const ASTContext &Context, 135280031Sdim CXXRecordDecl *RD) { 136280031Sdim NestedNameSpecifier Mockup; 137280031Sdim Mockup.Prefix.setPointer(nullptr); 138280031Sdim Mockup.Prefix.setInt(StoredDecl); 139280031Sdim Mockup.Specifier = RD; 140280031Sdim return FindOrInsert(Context, Mockup); 141280031Sdim} 142280031Sdim 143219077SdimNestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const { 144276479Sdim if (!Specifier) 145219077Sdim return Global; 146219077Sdim 147219077Sdim switch (Prefix.getInt()) { 148219077Sdim case StoredIdentifier: 149219077Sdim return Identifier; 150219077Sdim 151280031Sdim case StoredDecl: { 152280031Sdim NamedDecl *ND = static_cast<NamedDecl *>(Specifier); 153280031Sdim if (isa<CXXRecordDecl>(ND)) 154280031Sdim return Super; 155280031Sdim return isa<NamespaceDecl>(ND) ? Namespace : NamespaceAlias; 156280031Sdim } 157219077Sdim 158219077Sdim case StoredTypeSpec: 159219077Sdim return TypeSpec; 160219077Sdim 161219077Sdim case StoredTypeSpecWithTemplate: 162219077Sdim return TypeSpecWithTemplate; 163219077Sdim } 164219077Sdim 165234353Sdim llvm_unreachable("Invalid NNS Kind!"); 166219077Sdim} 167219077Sdim 168341825Sdim/// Retrieve the namespace stored in this nested name specifier. 169219077SdimNamespaceDecl *NestedNameSpecifier::getAsNamespace() const { 170314564Sdim if (Prefix.getInt() == StoredDecl) 171219077Sdim return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier)); 172219077Sdim 173276479Sdim return nullptr; 174219077Sdim} 175219077Sdim 176341825Sdim/// Retrieve the namespace alias stored in this nested name specifier. 177219077SdimNamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const { 178314564Sdim if (Prefix.getInt() == StoredDecl) 179219077Sdim return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier)); 180219077Sdim 181276479Sdim return nullptr; 182219077Sdim} 183219077Sdim 184341825Sdim/// Retrieve the record declaration stored in this nested name specifier. 185280031SdimCXXRecordDecl *NestedNameSpecifier::getAsRecordDecl() const { 186309124Sdim switch (Prefix.getInt()) { 187309124Sdim case StoredIdentifier: 188309124Sdim return nullptr; 189309124Sdim 190309124Sdim case StoredDecl: 191280031Sdim return dyn_cast<CXXRecordDecl>(static_cast<NamedDecl *>(Specifier)); 192219077Sdim 193309124Sdim case StoredTypeSpec: 194309124Sdim case StoredTypeSpecWithTemplate: 195309124Sdim return getAsType()->getAsCXXRecordDecl(); 196309124Sdim } 197309124Sdim 198309124Sdim llvm_unreachable("Invalid NNS Kind!"); 199280031Sdim} 200280031Sdim 201341825Sdim/// Whether this nested name specifier refers to a dependent 202193326Sed/// type or not. 203193326Sedbool NestedNameSpecifier::isDependent() const { 204193326Sed switch (getKind()) { 205193326Sed case Identifier: 206193326Sed // Identifier specifiers always represent dependent types 207193326Sed return true; 208193326Sed 209193326Sed case Namespace: 210219077Sdim case NamespaceAlias: 211193326Sed case Global: 212193326Sed return false; 213193326Sed 214280031Sdim case Super: { 215280031Sdim CXXRecordDecl *RD = static_cast<CXXRecordDecl *>(Specifier); 216280031Sdim for (const auto &Base : RD->bases()) 217280031Sdim if (Base.getType()->isDependentType()) 218280031Sdim return true; 219280031Sdim 220280031Sdim return false; 221280031Sdim } 222280031Sdim 223193326Sed case TypeSpec: 224193326Sed case TypeSpecWithTemplate: 225193326Sed return getAsType()->isDependentType(); 226193326Sed } 227193326Sed 228234353Sdim llvm_unreachable("Invalid NNS Kind!"); 229193326Sed} 230193326Sed 231341825Sdim/// Whether this nested name specifier refers to a dependent 232224145Sdim/// type or not. 233224145Sdimbool NestedNameSpecifier::isInstantiationDependent() const { 234224145Sdim switch (getKind()) { 235224145Sdim case Identifier: 236224145Sdim // Identifier specifiers always represent dependent types 237224145Sdim return true; 238341825Sdim 239224145Sdim case Namespace: 240224145Sdim case NamespaceAlias: 241224145Sdim case Global: 242280031Sdim case Super: 243224145Sdim return false; 244280031Sdim 245224145Sdim case TypeSpec: 246224145Sdim case TypeSpecWithTemplate: 247224145Sdim return getAsType()->isInstantiationDependentType(); 248224145Sdim } 249234353Sdim 250234353Sdim llvm_unreachable("Invalid NNS Kind!"); 251224145Sdim} 252224145Sdim 253218893Sdimbool NestedNameSpecifier::containsUnexpandedParameterPack() const { 254218893Sdim switch (getKind()) { 255218893Sdim case Identifier: 256218893Sdim return getPrefix() && getPrefix()->containsUnexpandedParameterPack(); 257218893Sdim 258218893Sdim case Namespace: 259219077Sdim case NamespaceAlias: 260218893Sdim case Global: 261280031Sdim case Super: 262218893Sdim return false; 263218893Sdim 264218893Sdim case TypeSpec: 265218893Sdim case TypeSpecWithTemplate: 266218893Sdim return getAsType()->containsUnexpandedParameterPack(); 267218893Sdim } 268218893Sdim 269234353Sdim llvm_unreachable("Invalid NNS Kind!"); 270218893Sdim} 271218893Sdim 272341825Sdim/// Print this nested name specifier to the given output 273193326Sed/// stream. 274344779Sdimvoid NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy, 275344779Sdim bool ResolveTemplateArguments) const { 276193326Sed if (getPrefix()) 277193326Sed getPrefix()->print(OS, Policy); 278193326Sed 279193326Sed switch (getKind()) { 280193326Sed case Identifier: 281193326Sed OS << getAsIdentifier()->getName(); 282193326Sed break; 283193326Sed 284193326Sed case Namespace: 285234353Sdim if (getAsNamespace()->isAnonymousNamespace()) 286234353Sdim return; 287341825Sdim 288219077Sdim OS << getAsNamespace()->getName(); 289193326Sed break; 290193326Sed 291219077Sdim case NamespaceAlias: 292219077Sdim OS << getAsNamespaceAlias()->getName(); 293219077Sdim break; 294219077Sdim 295193326Sed case Global: 296193326Sed break; 297193326Sed 298280031Sdim case Super: 299280031Sdim OS << "__super"; 300280031Sdim break; 301280031Sdim 302193326Sed case TypeSpecWithTemplate: 303193326Sed OS << "template "; 304193326Sed // Fall through to print the type. 305321369Sdim LLVM_FALLTHROUGH; 306193326Sed 307193326Sed case TypeSpec: { 308344779Sdim const auto *Record = 309344779Sdim dyn_cast_or_null<ClassTemplateSpecializationDecl>(getAsRecordDecl()); 310344779Sdim if (ResolveTemplateArguments && Record) { 311344779Sdim // Print the type trait with resolved template parameters. 312344779Sdim Record->printName(OS); 313344779Sdim printTemplateArgumentList(OS, Record->getTemplateArgs().asArray(), 314344779Sdim Policy); 315344779Sdim break; 316344779Sdim } 317218893Sdim const Type *T = getAsType(); 318193326Sed 319193326Sed PrintingPolicy InnerPolicy(Policy); 320198092Srdivacky InnerPolicy.SuppressScope = true; 321198092Srdivacky 322198092Srdivacky // Nested-name-specifiers are intended to contain minimally-qualified 323208600Srdivacky // types. An actual ElaboratedType will not occur, since we'll store 324198092Srdivacky // just the type that is referred to in the nested-name-specifier (e.g., 325198092Srdivacky // a TypedefType, TagType, etc.). However, when we are dealing with 326198092Srdivacky // dependent template-id types (e.g., Outer<T>::template Inner<U>), 327198092Srdivacky // the type requires its own nested-name-specifier for uniqueness, so we 328198092Srdivacky // suppress that nested-name-specifier during printing. 329208600Srdivacky assert(!isa<ElaboratedType>(T) && 330208600Srdivacky "Elaborated type in nested-name-specifier"); 331198092Srdivacky if (const TemplateSpecializationType *SpecType 332198092Srdivacky = dyn_cast<TemplateSpecializationType>(T)) { 333198092Srdivacky // Print the template name without its corresponding 334198092Srdivacky // nested-name-specifier. 335198092Srdivacky SpecType->getTemplateName().print(OS, InnerPolicy, true); 336198092Srdivacky 337198092Srdivacky // Print the template argument list. 338327952Sdim printTemplateArgumentList(OS, SpecType->template_arguments(), 339327952Sdim InnerPolicy); 340198092Srdivacky } else { 341198092Srdivacky // Print the type normally 342249423Sdim QualType(T, 0).print(OS, InnerPolicy); 343198092Srdivacky } 344193326Sed break; 345193326Sed } 346193326Sed } 347193326Sed 348193326Sed OS << "::"; 349193326Sed} 350193326Sed 351344779SdimLLVM_DUMP_METHOD void NestedNameSpecifier::dump(const LangOptions &LO) const { 352344779Sdim dump(llvm::errs(), LO); 353193326Sed} 354219077Sdim 355344779SdimLLVM_DUMP_METHOD void NestedNameSpecifier::dump() const { dump(llvm::errs()); } 356344779Sdim 357344779SdimLLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS) const { 358296417Sdim LangOptions LO; 359344779Sdim dump(OS, LO); 360296417Sdim} 361296417Sdim 362344779SdimLLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS, 363344779Sdim const LangOptions &LO) const { 364344779Sdim print(OS, PrintingPolicy(LO)); 365344779Sdim} 366344779Sdim 367341825Sdimunsigned 368219077SdimNestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) { 369219077Sdim assert(Qualifier && "Expected a non-NULL qualifier"); 370219077Sdim 371219077Sdim // Location of the trailing '::'. 372219077Sdim unsigned Length = sizeof(unsigned); 373219077Sdim 374219077Sdim switch (Qualifier->getKind()) { 375219077Sdim case NestedNameSpecifier::Global: 376219077Sdim // Nothing more to add. 377219077Sdim break; 378219077Sdim 379219077Sdim case NestedNameSpecifier::Identifier: 380219077Sdim case NestedNameSpecifier::Namespace: 381219077Sdim case NestedNameSpecifier::NamespaceAlias: 382280031Sdim case NestedNameSpecifier::Super: 383219077Sdim // The location of the identifier or namespace name. 384219077Sdim Length += sizeof(unsigned); 385219077Sdim break; 386219077Sdim 387219077Sdim case NestedNameSpecifier::TypeSpecWithTemplate: 388219077Sdim case NestedNameSpecifier::TypeSpec: 389219077Sdim // The "void*" that points at the TypeLoc data. 390219077Sdim // Note: the 'template' keyword is part of the TypeLoc. 391219077Sdim Length += sizeof(void *); 392219077Sdim break; 393219077Sdim } 394219077Sdim 395219077Sdim return Length; 396219077Sdim} 397219077Sdim 398341825Sdimunsigned 399219077SdimNestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) { 400219077Sdim unsigned Length = 0; 401219077Sdim for (; Qualifier; Qualifier = Qualifier->getPrefix()) 402219077Sdim Length += getLocalDataLength(Qualifier); 403219077Sdim return Length; 404219077Sdim} 405219077Sdim 406341825Sdim/// Load a (possibly unaligned) source location from a given address 407327952Sdim/// and offset. 408327952Sdimstatic SourceLocation LoadSourceLocation(void *Data, unsigned Offset) { 409327952Sdim unsigned Raw; 410327952Sdim memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(unsigned)); 411327952Sdim return SourceLocation::getFromRawEncoding(Raw); 412327952Sdim} 413341825Sdim 414341825Sdim/// Load a (possibly unaligned) pointer from a given address and 415327952Sdim/// offset. 416327952Sdimstatic void *LoadPointer(void *Data, unsigned Offset) { 417327952Sdim void *Result; 418327952Sdim memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*)); 419327952Sdim return Result; 420219077Sdim} 421219077Sdim 422219077SdimSourceRange NestedNameSpecifierLoc::getSourceRange() const { 423219077Sdim if (!Qualifier) 424219077Sdim return SourceRange(); 425341825Sdim 426219077Sdim NestedNameSpecifierLoc First = *this; 427219077Sdim while (NestedNameSpecifierLoc Prefix = First.getPrefix()) 428219077Sdim First = Prefix; 429341825Sdim 430341825Sdim return SourceRange(First.getLocalSourceRange().getBegin(), 431219077Sdim getLocalSourceRange().getEnd()); 432219077Sdim} 433219077Sdim 434219077SdimSourceRange NestedNameSpecifierLoc::getLocalSourceRange() const { 435219077Sdim if (!Qualifier) 436219077Sdim return SourceRange(); 437341825Sdim 438219077Sdim unsigned Offset = getDataLength(Qualifier->getPrefix()); 439219077Sdim switch (Qualifier->getKind()) { 440219077Sdim case NestedNameSpecifier::Global: 441219077Sdim return LoadSourceLocation(Data, Offset); 442219077Sdim 443219077Sdim case NestedNameSpecifier::Identifier: 444219077Sdim case NestedNameSpecifier::Namespace: 445219077Sdim case NestedNameSpecifier::NamespaceAlias: 446280031Sdim case NestedNameSpecifier::Super: 447219077Sdim return SourceRange(LoadSourceLocation(Data, Offset), 448219077Sdim LoadSourceLocation(Data, Offset + sizeof(unsigned))); 449219077Sdim 450219077Sdim case NestedNameSpecifier::TypeSpecWithTemplate: 451219077Sdim case NestedNameSpecifier::TypeSpec: { 452219077Sdim // The "void*" that points at the TypeLoc data. 453219077Sdim // Note: the 'template' keyword is part of the TypeLoc. 454219077Sdim void *TypeData = LoadPointer(Data, Offset); 455219077Sdim TypeLoc TL(Qualifier->getAsType(), TypeData); 456219077Sdim return SourceRange(TL.getBeginLoc(), 457219077Sdim LoadSourceLocation(Data, Offset + sizeof(void*))); 458219077Sdim } 459219077Sdim } 460234353Sdim 461234353Sdim llvm_unreachable("Invalid NNS Kind!"); 462219077Sdim} 463219077Sdim 464219077SdimTypeLoc NestedNameSpecifierLoc::getTypeLoc() const { 465344779Sdim if (Qualifier->getKind() != NestedNameSpecifier::TypeSpec && 466344779Sdim Qualifier->getKind() != NestedNameSpecifier::TypeSpecWithTemplate) 467344779Sdim return TypeLoc(); 468219077Sdim 469219077Sdim // The "void*" that points at the TypeLoc data. 470219077Sdim unsigned Offset = getDataLength(Qualifier->getPrefix()); 471219077Sdim void *TypeData = LoadPointer(Data, Offset); 472219077Sdim return TypeLoc(Qualifier->getAsType(), TypeData); 473219077Sdim} 474221345Sdim 475327952Sdimstatic void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize, 476221345Sdim unsigned &BufferCapacity) { 477327952Sdim if (Start == End) 478327952Sdim return; 479288943Sdim 480327952Sdim if (BufferSize + (End - Start) > BufferCapacity) { 481327952Sdim // Reallocate the buffer. 482327952Sdim unsigned NewCapacity = std::max( 483327952Sdim (unsigned)(BufferCapacity ? BufferCapacity * 2 : sizeof(void *) * 2), 484327952Sdim (unsigned)(BufferSize + (End - Start))); 485341825Sdim char *NewBuffer = static_cast<char *>(llvm::safe_malloc(NewCapacity)); 486327952Sdim if (BufferCapacity) { 487327952Sdim memcpy(NewBuffer, Buffer, BufferSize); 488327952Sdim free(Buffer); 489221345Sdim } 490327952Sdim Buffer = NewBuffer; 491327952Sdim BufferCapacity = NewCapacity; 492221345Sdim } 493327952Sdim 494327952Sdim memcpy(Buffer + BufferSize, Start, End - Start); 495327952Sdim BufferSize += End-Start; 496327952Sdim} 497341825Sdim 498341825Sdim/// Save a source location to the given buffer. 499327952Sdimstatic void SaveSourceLocation(SourceLocation Loc, char *&Buffer, 500327952Sdim unsigned &BufferSize, unsigned &BufferCapacity) { 501327952Sdim unsigned Raw = Loc.getRawEncoding(); 502327952Sdim Append(reinterpret_cast<char *>(&Raw), 503327952Sdim reinterpret_cast<char *>(&Raw) + sizeof(unsigned), 504327952Sdim Buffer, BufferSize, BufferCapacity); 505327952Sdim} 506341825Sdim 507341825Sdim/// Save a pointer to the given buffer. 508327952Sdimstatic void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize, 509327952Sdim unsigned &BufferCapacity) { 510327952Sdim Append(reinterpret_cast<char *>(&Ptr), 511327952Sdim reinterpret_cast<char *>(&Ptr) + sizeof(void *), 512327952Sdim Buffer, BufferSize, BufferCapacity); 513221345Sdim} 514221345Sdim 515221345SdimNestedNameSpecifierLocBuilder:: 516341825SdimNestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other) 517327952Sdim : Representation(Other.Representation) { 518221345Sdim if (!Other.Buffer) 519221345Sdim return; 520341825Sdim 521221345Sdim if (Other.BufferCapacity == 0) { 522221345Sdim // Shallow copy is okay. 523221345Sdim Buffer = Other.Buffer; 524221345Sdim BufferSize = Other.BufferSize; 525221345Sdim return; 526221345Sdim } 527341825Sdim 528221345Sdim // Deep copy 529276479Sdim Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize, 530276479Sdim BufferCapacity); 531221345Sdim} 532221345Sdim 533221345SdimNestedNameSpecifierLocBuilder & 534221345SdimNestedNameSpecifierLocBuilder:: 535221345Sdimoperator=(const NestedNameSpecifierLocBuilder &Other) { 536221345Sdim Representation = Other.Representation; 537341825Sdim 538221345Sdim if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) { 539221345Sdim // Re-use our storage. 540221345Sdim BufferSize = Other.BufferSize; 541221345Sdim memcpy(Buffer, Other.Buffer, BufferSize); 542221345Sdim return *this; 543221345Sdim } 544341825Sdim 545221345Sdim // Free our storage, if we have any. 546221345Sdim if (BufferCapacity) { 547221345Sdim free(Buffer); 548221345Sdim BufferCapacity = 0; 549221345Sdim } 550341825Sdim 551221345Sdim if (!Other.Buffer) { 552221345Sdim // Empty. 553276479Sdim Buffer = nullptr; 554221345Sdim BufferSize = 0; 555221345Sdim return *this; 556221345Sdim } 557341825Sdim 558221345Sdim if (Other.BufferCapacity == 0) { 559221345Sdim // Shallow copy is okay. 560221345Sdim Buffer = Other.Buffer; 561221345Sdim BufferSize = Other.BufferSize; 562221345Sdim return *this; 563221345Sdim } 564341825Sdim 565221345Sdim // Deep copy. 566344779Sdim BufferSize = 0; 567276479Sdim Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize, 568276479Sdim BufferCapacity); 569221345Sdim return *this; 570221345Sdim} 571221345Sdim 572341825Sdimvoid NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 573341825Sdim SourceLocation TemplateKWLoc, 574341825Sdim TypeLoc TL, 575221345Sdim SourceLocation ColonColonLoc) { 576341825Sdim Representation = NestedNameSpecifier::Create(Context, Representation, 577341825Sdim TemplateKWLoc.isValid(), 578221345Sdim TL.getTypePtr()); 579341825Sdim 580221345Sdim // Push source-location info into the buffer. 581221345Sdim SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity); 582221345Sdim SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 583221345Sdim} 584221345Sdim 585341825Sdimvoid NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 586221345Sdim IdentifierInfo *Identifier, 587341825Sdim SourceLocation IdentifierLoc, 588221345Sdim SourceLocation ColonColonLoc) { 589341825Sdim Representation = NestedNameSpecifier::Create(Context, Representation, 590221345Sdim Identifier); 591341825Sdim 592221345Sdim // Push source-location info into the buffer. 593221345Sdim SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity); 594221345Sdim SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 595221345Sdim} 596221345Sdim 597341825Sdimvoid NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 598221345Sdim NamespaceDecl *Namespace, 599341825Sdim SourceLocation NamespaceLoc, 600221345Sdim SourceLocation ColonColonLoc) { 601341825Sdim Representation = NestedNameSpecifier::Create(Context, Representation, 602221345Sdim Namespace); 603341825Sdim 604221345Sdim // Push source-location info into the buffer. 605221345Sdim SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity); 606221345Sdim SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 607221345Sdim} 608221345Sdim 609221345Sdimvoid NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 610221345Sdim NamespaceAliasDecl *Alias, 611341825Sdim SourceLocation AliasLoc, 612221345Sdim SourceLocation ColonColonLoc) { 613221345Sdim Representation = NestedNameSpecifier::Create(Context, Representation, Alias); 614341825Sdim 615221345Sdim // Push source-location info into the buffer. 616221345Sdim SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity); 617221345Sdim SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 618221345Sdim} 619221345Sdim 620341825Sdimvoid NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context, 621221345Sdim SourceLocation ColonColonLoc) { 622221345Sdim assert(!Representation && "Already have a nested-name-specifier!?"); 623221345Sdim Representation = NestedNameSpecifier::GlobalSpecifier(Context); 624341825Sdim 625221345Sdim // Push source-location info into the buffer. 626221345Sdim SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 627221345Sdim} 628221345Sdim 629280031Sdimvoid NestedNameSpecifierLocBuilder::MakeSuper(ASTContext &Context, 630280031Sdim CXXRecordDecl *RD, 631280031Sdim SourceLocation SuperLoc, 632280031Sdim SourceLocation ColonColonLoc) { 633280031Sdim Representation = NestedNameSpecifier::SuperSpecifier(Context, RD); 634280031Sdim 635280031Sdim // Push source-location info into the buffer. 636280031Sdim SaveSourceLocation(SuperLoc, Buffer, BufferSize, BufferCapacity); 637280031Sdim SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 638280031Sdim} 639280031Sdim 640341825Sdimvoid NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context, 641341825Sdim NestedNameSpecifier *Qualifier, 642221345Sdim SourceRange R) { 643221345Sdim Representation = Qualifier; 644341825Sdim 645341825Sdim // Construct bogus (but well-formed) source information for the 646221345Sdim // nested-name-specifier. 647221345Sdim BufferSize = 0; 648226633Sdim SmallVector<NestedNameSpecifier *, 4> Stack; 649221345Sdim for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix()) 650221345Sdim Stack.push_back(NNS); 651221345Sdim while (!Stack.empty()) { 652261991Sdim NestedNameSpecifier *NNS = Stack.pop_back_val(); 653221345Sdim switch (NNS->getKind()) { 654221345Sdim case NestedNameSpecifier::Identifier: 655221345Sdim case NestedNameSpecifier::Namespace: 656221345Sdim case NestedNameSpecifier::NamespaceAlias: 657221345Sdim SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity); 658221345Sdim break; 659341825Sdim 660221345Sdim case NestedNameSpecifier::TypeSpec: 661221345Sdim case NestedNameSpecifier::TypeSpecWithTemplate: { 662221345Sdim TypeSourceInfo *TSInfo 663221345Sdim = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0), 664221345Sdim R.getBegin()); 665341825Sdim SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize, 666221345Sdim BufferCapacity); 667221345Sdim break; 668221345Sdim } 669341825Sdim 670221345Sdim case NestedNameSpecifier::Global: 671280031Sdim case NestedNameSpecifier::Super: 672221345Sdim break; 673221345Sdim } 674341825Sdim 675221345Sdim // Save the location of the '::'. 676341825Sdim SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(), 677221345Sdim Buffer, BufferSize, BufferCapacity); 678221345Sdim } 679221345Sdim} 680221345Sdim 681221345Sdimvoid NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) { 682221345Sdim if (BufferCapacity) 683221345Sdim free(Buffer); 684221345Sdim 685221345Sdim if (!Other) { 686276479Sdim Representation = nullptr; 687221345Sdim BufferSize = 0; 688221345Sdim return; 689221345Sdim } 690341825Sdim 691341825Sdim // Rather than copying the data (which is wasteful), "adopt" the 692221345Sdim // pointer (which points into the ASTContext) but set the capacity to zero to 693221345Sdim // indicate that we don't own it. 694221345Sdim Representation = Other.getNestedNameSpecifier(); 695221345Sdim Buffer = static_cast<char *>(Other.getOpaqueData()); 696221345Sdim BufferSize = Other.getDataLength(); 697221345Sdim BufferCapacity = 0; 698221345Sdim} 699221345Sdim 700341825SdimNestedNameSpecifierLoc 701221345SdimNestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext &Context) const { 702221345Sdim if (!Representation) 703221345Sdim return NestedNameSpecifierLoc(); 704341825Sdim 705221345Sdim // If we adopted our data pointer from elsewhere in the AST context, there's 706221345Sdim // no need to copy the memory. 707221345Sdim if (BufferCapacity == 0) 708221345Sdim return NestedNameSpecifierLoc(Representation, Buffer); 709341825Sdim 710221345Sdim // FIXME: After copying the source-location information, should we free 711221345Sdim // our (temporary) buffer and adopt the ASTContext-allocated memory? 712221345Sdim // Doing so would optimize repeated calls to getWithLocInContext(). 713314564Sdim void *Mem = Context.Allocate(BufferSize, alignof(void *)); 714221345Sdim memcpy(Mem, Buffer, BufferSize); 715221345Sdim return NestedNameSpecifierLoc(Representation, Mem); 716221345Sdim} 717