1327952Sdim//===- NestedNameSpecifier.cpp - C++ nested name specifiers ---------------===// 2193326Sed// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6193326Sed// 7193326Sed//===----------------------------------------------------------------------===// 8193326Sed// 9193326Sed// This file defines the NestedNameSpecifier class, which represents 10193326Sed// a C++ nested-name-specifier. 11193326Sed// 12193326Sed//===----------------------------------------------------------------------===// 13327952Sdim 14193326Sed#include "clang/AST/NestedNameSpecifier.h" 15193326Sed#include "clang/AST/ASTContext.h" 16193326Sed#include "clang/AST/Decl.h" 17219077Sdim#include "clang/AST/DeclCXX.h" 18344779Sdim#include "clang/AST/DeclTemplate.h" 19193326Sed#include "clang/AST/PrettyPrinter.h" 20327952Sdim#include "clang/AST/TemplateName.h" 21193326Sed#include "clang/AST/Type.h" 22219077Sdim#include "clang/AST/TypeLoc.h" 23327952Sdim#include "clang/Basic/LLVM.h" 24327952Sdim#include "clang/Basic/LangOptions.h" 25327952Sdim#include "clang/Basic/SourceLocation.h" 26327952Sdim#include "llvm/ADT/FoldingSet.h" 27327952Sdim#include "llvm/ADT/SmallVector.h" 28327952Sdim#include "llvm/Support/Casting.h" 29327952Sdim#include "llvm/Support/Compiler.h" 30327952Sdim#include "llvm/Support/ErrorHandling.h" 31193326Sed#include "llvm/Support/raw_ostream.h" 32327952Sdim#include <algorithm> 33193326Sed#include <cassert> 34327952Sdim#include <cstdlib> 35327952Sdim#include <cstring> 36193326Sed 37193326Sedusing namespace clang; 38193326Sed 39193326SedNestedNameSpecifier * 40218893SdimNestedNameSpecifier::FindOrInsert(const ASTContext &Context, 41193326Sed const NestedNameSpecifier &Mockup) { 42193326Sed llvm::FoldingSetNodeID ID; 43193326Sed Mockup.Profile(ID); 44193326Sed 45276479Sdim void *InsertPos = nullptr; 46198092Srdivacky NestedNameSpecifier *NNS 47193326Sed = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos); 48193326Sed if (!NNS) { 49314564Sdim NNS = 50314564Sdim new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier(Mockup); 51193326Sed Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos); 52193326Sed } 53193326Sed 54193326Sed return NNS; 55193326Sed} 56193326Sed 57193326SedNestedNameSpecifier * 58218893SdimNestedNameSpecifier::Create(const ASTContext &Context, 59218893Sdim NestedNameSpecifier *Prefix, IdentifierInfo *II) { 60193326Sed assert(II && "Identifier cannot be NULL"); 61198092Srdivacky assert((!Prefix || Prefix->isDependent()) && "Prefix must be dependent"); 62193326Sed 63193326Sed NestedNameSpecifier Mockup; 64193326Sed Mockup.Prefix.setPointer(Prefix); 65219077Sdim Mockup.Prefix.setInt(StoredIdentifier); 66193326Sed Mockup.Specifier = II; 67193326Sed return FindOrInsert(Context, Mockup); 68193326Sed} 69193326Sed 70193326SedNestedNameSpecifier * 71218893SdimNestedNameSpecifier::Create(const ASTContext &Context, 72249423Sdim NestedNameSpecifier *Prefix, 73249423Sdim const NamespaceDecl *NS) { 74193326Sed assert(NS && "Namespace cannot be NULL"); 75198092Srdivacky assert((!Prefix || 76276479Sdim (Prefix->getAsType() == nullptr && 77276479Sdim Prefix->getAsIdentifier() == nullptr)) && 78193326Sed "Broken nested name specifier"); 79193326Sed NestedNameSpecifier Mockup; 80193326Sed Mockup.Prefix.setPointer(Prefix); 81280031Sdim Mockup.Prefix.setInt(StoredDecl); 82249423Sdim Mockup.Specifier = const_cast<NamespaceDecl *>(NS); 83193326Sed return FindOrInsert(Context, Mockup); 84193326Sed} 85193326Sed 86193326SedNestedNameSpecifier * 87218893SdimNestedNameSpecifier::Create(const ASTContext &Context, 88341825Sdim NestedNameSpecifier *Prefix, 89219077Sdim NamespaceAliasDecl *Alias) { 90219077Sdim assert(Alias && "Namespace alias cannot be NULL"); 91219077Sdim assert((!Prefix || 92276479Sdim (Prefix->getAsType() == nullptr && 93276479Sdim Prefix->getAsIdentifier() == nullptr)) && 94219077Sdim "Broken nested name specifier"); 95219077Sdim NestedNameSpecifier Mockup; 96219077Sdim Mockup.Prefix.setPointer(Prefix); 97280031Sdim Mockup.Prefix.setInt(StoredDecl); 98219077Sdim Mockup.Specifier = Alias; 99219077Sdim return FindOrInsert(Context, Mockup); 100219077Sdim} 101219077Sdim 102219077SdimNestedNameSpecifier * 103219077SdimNestedNameSpecifier::Create(const ASTContext &Context, 104218893Sdim NestedNameSpecifier *Prefix, 105218893Sdim bool Template, const Type *T) { 106193326Sed assert(T && "Type cannot be NULL"); 107193326Sed NestedNameSpecifier Mockup; 108193326Sed Mockup.Prefix.setPointer(Prefix); 109219077Sdim Mockup.Prefix.setInt(Template? StoredTypeSpecWithTemplate : StoredTypeSpec); 110218893Sdim Mockup.Specifier = const_cast<Type*>(T); 111193326Sed return FindOrInsert(Context, Mockup); 112193326Sed} 113198092Srdivacky 114198092SrdivackyNestedNameSpecifier * 115218893SdimNestedNameSpecifier::Create(const ASTContext &Context, IdentifierInfo *II) { 116198092Srdivacky assert(II && "Identifier cannot be NULL"); 117198092Srdivacky NestedNameSpecifier Mockup; 118276479Sdim Mockup.Prefix.setPointer(nullptr); 119219077Sdim Mockup.Prefix.setInt(StoredIdentifier); 120198092Srdivacky Mockup.Specifier = II; 121198092Srdivacky return FindOrInsert(Context, Mockup); 122198092Srdivacky} 123198092Srdivacky 124218893SdimNestedNameSpecifier * 125218893SdimNestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) { 126193326Sed if (!Context.GlobalNestedNameSpecifier) 127239462Sdim Context.GlobalNestedNameSpecifier = 128314564Sdim new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier(); 129193326Sed return Context.GlobalNestedNameSpecifier; 130193326Sed} 131193326Sed 132280031SdimNestedNameSpecifier * 133280031SdimNestedNameSpecifier::SuperSpecifier(const ASTContext &Context, 134280031Sdim CXXRecordDecl *RD) { 135280031Sdim NestedNameSpecifier Mockup; 136280031Sdim Mockup.Prefix.setPointer(nullptr); 137280031Sdim Mockup.Prefix.setInt(StoredDecl); 138280031Sdim Mockup.Specifier = RD; 139280031Sdim return FindOrInsert(Context, Mockup); 140280031Sdim} 141280031Sdim 142219077SdimNestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const { 143276479Sdim if (!Specifier) 144219077Sdim return Global; 145219077Sdim 146219077Sdim switch (Prefix.getInt()) { 147219077Sdim case StoredIdentifier: 148219077Sdim return Identifier; 149219077Sdim 150280031Sdim case StoredDecl: { 151280031Sdim NamedDecl *ND = static_cast<NamedDecl *>(Specifier); 152280031Sdim if (isa<CXXRecordDecl>(ND)) 153280031Sdim return Super; 154280031Sdim return isa<NamespaceDecl>(ND) ? Namespace : NamespaceAlias; 155280031Sdim } 156219077Sdim 157219077Sdim case StoredTypeSpec: 158219077Sdim return TypeSpec; 159219077Sdim 160219077Sdim case StoredTypeSpecWithTemplate: 161219077Sdim return TypeSpecWithTemplate; 162219077Sdim } 163219077Sdim 164234353Sdim llvm_unreachable("Invalid NNS Kind!"); 165219077Sdim} 166219077Sdim 167341825Sdim/// Retrieve the namespace stored in this nested name specifier. 168219077SdimNamespaceDecl *NestedNameSpecifier::getAsNamespace() const { 169314564Sdim if (Prefix.getInt() == StoredDecl) 170219077Sdim return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier)); 171219077Sdim 172276479Sdim return nullptr; 173219077Sdim} 174219077Sdim 175341825Sdim/// Retrieve the namespace alias stored in this nested name specifier. 176219077SdimNamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const { 177314564Sdim if (Prefix.getInt() == StoredDecl) 178219077Sdim return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier)); 179219077Sdim 180276479Sdim return nullptr; 181219077Sdim} 182219077Sdim 183341825Sdim/// Retrieve the record declaration stored in this nested name specifier. 184280031SdimCXXRecordDecl *NestedNameSpecifier::getAsRecordDecl() const { 185309124Sdim switch (Prefix.getInt()) { 186309124Sdim case StoredIdentifier: 187309124Sdim return nullptr; 188309124Sdim 189309124Sdim case StoredDecl: 190280031Sdim return dyn_cast<CXXRecordDecl>(static_cast<NamedDecl *>(Specifier)); 191219077Sdim 192309124Sdim case StoredTypeSpec: 193309124Sdim case StoredTypeSpecWithTemplate: 194309124Sdim return getAsType()->getAsCXXRecordDecl(); 195309124Sdim } 196309124Sdim 197309124Sdim llvm_unreachable("Invalid NNS Kind!"); 198280031Sdim} 199280031Sdim 200341825Sdim/// Whether this nested name specifier refers to a dependent 201193326Sed/// type or not. 202193326Sedbool NestedNameSpecifier::isDependent() const { 203193326Sed switch (getKind()) { 204193326Sed case Identifier: 205193326Sed // Identifier specifiers always represent dependent types 206193326Sed return true; 207193326Sed 208193326Sed case Namespace: 209219077Sdim case NamespaceAlias: 210193326Sed case Global: 211193326Sed return false; 212193326Sed 213280031Sdim case Super: { 214280031Sdim CXXRecordDecl *RD = static_cast<CXXRecordDecl *>(Specifier); 215280031Sdim for (const auto &Base : RD->bases()) 216280031Sdim if (Base.getType()->isDependentType()) 217280031Sdim return true; 218280031Sdim 219280031Sdim return false; 220280031Sdim } 221280031Sdim 222193326Sed case TypeSpec: 223193326Sed case TypeSpecWithTemplate: 224193326Sed return getAsType()->isDependentType(); 225193326Sed } 226193326Sed 227234353Sdim llvm_unreachable("Invalid NNS Kind!"); 228193326Sed} 229193326Sed 230341825Sdim/// Whether this nested name specifier refers to a dependent 231224145Sdim/// type or not. 232224145Sdimbool NestedNameSpecifier::isInstantiationDependent() const { 233224145Sdim switch (getKind()) { 234224145Sdim case Identifier: 235224145Sdim // Identifier specifiers always represent dependent types 236224145Sdim return true; 237341825Sdim 238224145Sdim case Namespace: 239224145Sdim case NamespaceAlias: 240224145Sdim case Global: 241280031Sdim case Super: 242224145Sdim return false; 243280031Sdim 244224145Sdim case TypeSpec: 245224145Sdim case TypeSpecWithTemplate: 246224145Sdim return getAsType()->isInstantiationDependentType(); 247224145Sdim } 248234353Sdim 249234353Sdim llvm_unreachable("Invalid NNS Kind!"); 250224145Sdim} 251224145Sdim 252218893Sdimbool NestedNameSpecifier::containsUnexpandedParameterPack() const { 253218893Sdim switch (getKind()) { 254218893Sdim case Identifier: 255218893Sdim return getPrefix() && getPrefix()->containsUnexpandedParameterPack(); 256218893Sdim 257218893Sdim case Namespace: 258219077Sdim case NamespaceAlias: 259218893Sdim case Global: 260280031Sdim case Super: 261218893Sdim return false; 262218893Sdim 263218893Sdim case TypeSpec: 264218893Sdim case TypeSpecWithTemplate: 265218893Sdim return getAsType()->containsUnexpandedParameterPack(); 266218893Sdim } 267218893Sdim 268234353Sdim llvm_unreachable("Invalid NNS Kind!"); 269218893Sdim} 270218893Sdim 271341825Sdim/// Print this nested name specifier to the given output 272193326Sed/// stream. 273344779Sdimvoid NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy, 274344779Sdim bool ResolveTemplateArguments) const { 275193326Sed if (getPrefix()) 276193326Sed getPrefix()->print(OS, Policy); 277193326Sed 278193326Sed switch (getKind()) { 279193326Sed case Identifier: 280193326Sed OS << getAsIdentifier()->getName(); 281193326Sed break; 282193326Sed 283193326Sed case Namespace: 284234353Sdim if (getAsNamespace()->isAnonymousNamespace()) 285234353Sdim return; 286341825Sdim 287219077Sdim OS << getAsNamespace()->getName(); 288193326Sed break; 289193326Sed 290219077Sdim case NamespaceAlias: 291219077Sdim OS << getAsNamespaceAlias()->getName(); 292219077Sdim break; 293219077Sdim 294193326Sed case Global: 295193326Sed break; 296193326Sed 297280031Sdim case Super: 298280031Sdim OS << "__super"; 299280031Sdim break; 300280031Sdim 301193326Sed case TypeSpecWithTemplate: 302193326Sed OS << "template "; 303193326Sed // Fall through to print the type. 304321369Sdim LLVM_FALLTHROUGH; 305193326Sed 306193326Sed case TypeSpec: { 307344779Sdim const auto *Record = 308344779Sdim dyn_cast_or_null<ClassTemplateSpecializationDecl>(getAsRecordDecl()); 309344779Sdim if (ResolveTemplateArguments && Record) { 310344779Sdim // Print the type trait with resolved template parameters. 311344779Sdim Record->printName(OS); 312344779Sdim printTemplateArgumentList(OS, Record->getTemplateArgs().asArray(), 313344779Sdim Policy); 314344779Sdim break; 315344779Sdim } 316218893Sdim const Type *T = getAsType(); 317193326Sed 318193326Sed PrintingPolicy InnerPolicy(Policy); 319198092Srdivacky InnerPolicy.SuppressScope = true; 320198092Srdivacky 321198092Srdivacky // Nested-name-specifiers are intended to contain minimally-qualified 322208600Srdivacky // types. An actual ElaboratedType will not occur, since we'll store 323198092Srdivacky // just the type that is referred to in the nested-name-specifier (e.g., 324198092Srdivacky // a TypedefType, TagType, etc.). However, when we are dealing with 325198092Srdivacky // dependent template-id types (e.g., Outer<T>::template Inner<U>), 326198092Srdivacky // the type requires its own nested-name-specifier for uniqueness, so we 327198092Srdivacky // suppress that nested-name-specifier during printing. 328208600Srdivacky assert(!isa<ElaboratedType>(T) && 329208600Srdivacky "Elaborated type in nested-name-specifier"); 330198092Srdivacky if (const TemplateSpecializationType *SpecType 331198092Srdivacky = dyn_cast<TemplateSpecializationType>(T)) { 332198092Srdivacky // Print the template name without its corresponding 333198092Srdivacky // nested-name-specifier. 334198092Srdivacky SpecType->getTemplateName().print(OS, InnerPolicy, true); 335198092Srdivacky 336198092Srdivacky // Print the template argument list. 337327952Sdim printTemplateArgumentList(OS, SpecType->template_arguments(), 338327952Sdim InnerPolicy); 339198092Srdivacky } else { 340198092Srdivacky // Print the type normally 341249423Sdim QualType(T, 0).print(OS, InnerPolicy); 342198092Srdivacky } 343193326Sed break; 344193326Sed } 345193326Sed } 346193326Sed 347193326Sed OS << "::"; 348193326Sed} 349193326Sed 350344779SdimLLVM_DUMP_METHOD void NestedNameSpecifier::dump(const LangOptions &LO) const { 351344779Sdim dump(llvm::errs(), LO); 352193326Sed} 353219077Sdim 354344779SdimLLVM_DUMP_METHOD void NestedNameSpecifier::dump() const { dump(llvm::errs()); } 355344779Sdim 356344779SdimLLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS) const { 357296417Sdim LangOptions LO; 358344779Sdim dump(OS, LO); 359296417Sdim} 360296417Sdim 361344779SdimLLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS, 362344779Sdim const LangOptions &LO) const { 363344779Sdim print(OS, PrintingPolicy(LO)); 364344779Sdim} 365344779Sdim 366341825Sdimunsigned 367219077SdimNestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) { 368219077Sdim assert(Qualifier && "Expected a non-NULL qualifier"); 369219077Sdim 370219077Sdim // Location of the trailing '::'. 371219077Sdim unsigned Length = sizeof(unsigned); 372219077Sdim 373219077Sdim switch (Qualifier->getKind()) { 374219077Sdim case NestedNameSpecifier::Global: 375219077Sdim // Nothing more to add. 376219077Sdim break; 377219077Sdim 378219077Sdim case NestedNameSpecifier::Identifier: 379219077Sdim case NestedNameSpecifier::Namespace: 380219077Sdim case NestedNameSpecifier::NamespaceAlias: 381280031Sdim case NestedNameSpecifier::Super: 382219077Sdim // The location of the identifier or namespace name. 383219077Sdim Length += sizeof(unsigned); 384219077Sdim break; 385219077Sdim 386219077Sdim case NestedNameSpecifier::TypeSpecWithTemplate: 387219077Sdim case NestedNameSpecifier::TypeSpec: 388219077Sdim // The "void*" that points at the TypeLoc data. 389219077Sdim // Note: the 'template' keyword is part of the TypeLoc. 390219077Sdim Length += sizeof(void *); 391219077Sdim break; 392219077Sdim } 393219077Sdim 394219077Sdim return Length; 395219077Sdim} 396219077Sdim 397341825Sdimunsigned 398219077SdimNestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) { 399219077Sdim unsigned Length = 0; 400219077Sdim for (; Qualifier; Qualifier = Qualifier->getPrefix()) 401219077Sdim Length += getLocalDataLength(Qualifier); 402219077Sdim return Length; 403219077Sdim} 404219077Sdim 405341825Sdim/// Load a (possibly unaligned) source location from a given address 406327952Sdim/// and offset. 407327952Sdimstatic SourceLocation LoadSourceLocation(void *Data, unsigned Offset) { 408327952Sdim unsigned Raw; 409327952Sdim memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(unsigned)); 410327952Sdim return SourceLocation::getFromRawEncoding(Raw); 411327952Sdim} 412341825Sdim 413341825Sdim/// Load a (possibly unaligned) pointer from a given address and 414327952Sdim/// offset. 415327952Sdimstatic void *LoadPointer(void *Data, unsigned Offset) { 416327952Sdim void *Result; 417327952Sdim memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*)); 418327952Sdim return Result; 419219077Sdim} 420219077Sdim 421219077SdimSourceRange NestedNameSpecifierLoc::getSourceRange() const { 422219077Sdim if (!Qualifier) 423219077Sdim return SourceRange(); 424341825Sdim 425219077Sdim NestedNameSpecifierLoc First = *this; 426219077Sdim while (NestedNameSpecifierLoc Prefix = First.getPrefix()) 427219077Sdim First = Prefix; 428341825Sdim 429341825Sdim return SourceRange(First.getLocalSourceRange().getBegin(), 430219077Sdim getLocalSourceRange().getEnd()); 431219077Sdim} 432219077Sdim 433219077SdimSourceRange NestedNameSpecifierLoc::getLocalSourceRange() const { 434219077Sdim if (!Qualifier) 435219077Sdim return SourceRange(); 436341825Sdim 437219077Sdim unsigned Offset = getDataLength(Qualifier->getPrefix()); 438219077Sdim switch (Qualifier->getKind()) { 439219077Sdim case NestedNameSpecifier::Global: 440219077Sdim return LoadSourceLocation(Data, Offset); 441219077Sdim 442219077Sdim case NestedNameSpecifier::Identifier: 443219077Sdim case NestedNameSpecifier::Namespace: 444219077Sdim case NestedNameSpecifier::NamespaceAlias: 445280031Sdim case NestedNameSpecifier::Super: 446219077Sdim return SourceRange(LoadSourceLocation(Data, Offset), 447219077Sdim LoadSourceLocation(Data, Offset + sizeof(unsigned))); 448219077Sdim 449219077Sdim case NestedNameSpecifier::TypeSpecWithTemplate: 450219077Sdim case NestedNameSpecifier::TypeSpec: { 451219077Sdim // The "void*" that points at the TypeLoc data. 452219077Sdim // Note: the 'template' keyword is part of the TypeLoc. 453219077Sdim void *TypeData = LoadPointer(Data, Offset); 454219077Sdim TypeLoc TL(Qualifier->getAsType(), TypeData); 455219077Sdim return SourceRange(TL.getBeginLoc(), 456219077Sdim LoadSourceLocation(Data, Offset + sizeof(void*))); 457219077Sdim } 458219077Sdim } 459234353Sdim 460234353Sdim llvm_unreachable("Invalid NNS Kind!"); 461219077Sdim} 462219077Sdim 463219077SdimTypeLoc NestedNameSpecifierLoc::getTypeLoc() const { 464344779Sdim if (Qualifier->getKind() != NestedNameSpecifier::TypeSpec && 465344779Sdim Qualifier->getKind() != NestedNameSpecifier::TypeSpecWithTemplate) 466344779Sdim return TypeLoc(); 467219077Sdim 468219077Sdim // The "void*" that points at the TypeLoc data. 469219077Sdim unsigned Offset = getDataLength(Qualifier->getPrefix()); 470219077Sdim void *TypeData = LoadPointer(Data, Offset); 471219077Sdim return TypeLoc(Qualifier->getAsType(), TypeData); 472219077Sdim} 473221345Sdim 474327952Sdimstatic void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize, 475360784Sdim unsigned &BufferCapacity) { 476327952Sdim if (Start == End) 477327952Sdim return; 478288943Sdim 479327952Sdim if (BufferSize + (End - Start) > BufferCapacity) { 480327952Sdim // Reallocate the buffer. 481327952Sdim unsigned NewCapacity = std::max( 482327952Sdim (unsigned)(BufferCapacity ? BufferCapacity * 2 : sizeof(void *) * 2), 483327952Sdim (unsigned)(BufferSize + (End - Start))); 484341825Sdim char *NewBuffer = static_cast<char *>(llvm::safe_malloc(NewCapacity)); 485327952Sdim if (BufferCapacity) { 486327952Sdim memcpy(NewBuffer, Buffer, BufferSize); 487327952Sdim free(Buffer); 488221345Sdim } 489327952Sdim Buffer = NewBuffer; 490327952Sdim BufferCapacity = NewCapacity; 491221345Sdim } 492360784Sdim assert(Buffer && Start && End && End > Start && "Illegal memory buffer copy"); 493327952Sdim memcpy(Buffer + BufferSize, Start, End - Start); 494360784Sdim BufferSize += End - Start; 495327952Sdim} 496341825Sdim 497341825Sdim/// Save a source location to the given buffer. 498327952Sdimstatic void SaveSourceLocation(SourceLocation Loc, char *&Buffer, 499327952Sdim unsigned &BufferSize, unsigned &BufferCapacity) { 500327952Sdim unsigned Raw = Loc.getRawEncoding(); 501327952Sdim Append(reinterpret_cast<char *>(&Raw), 502327952Sdim reinterpret_cast<char *>(&Raw) + sizeof(unsigned), 503327952Sdim Buffer, BufferSize, BufferCapacity); 504327952Sdim} 505341825Sdim 506341825Sdim/// Save a pointer to the given buffer. 507327952Sdimstatic void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize, 508327952Sdim unsigned &BufferCapacity) { 509327952Sdim Append(reinterpret_cast<char *>(&Ptr), 510327952Sdim reinterpret_cast<char *>(&Ptr) + sizeof(void *), 511327952Sdim Buffer, BufferSize, BufferCapacity); 512221345Sdim} 513221345Sdim 514221345SdimNestedNameSpecifierLocBuilder:: 515341825SdimNestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other) 516327952Sdim : Representation(Other.Representation) { 517221345Sdim if (!Other.Buffer) 518221345Sdim return; 519341825Sdim 520221345Sdim if (Other.BufferCapacity == 0) { 521221345Sdim // Shallow copy is okay. 522221345Sdim Buffer = Other.Buffer; 523221345Sdim BufferSize = Other.BufferSize; 524221345Sdim return; 525221345Sdim } 526341825Sdim 527221345Sdim // Deep copy 528276479Sdim Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize, 529276479Sdim BufferCapacity); 530221345Sdim} 531221345Sdim 532221345SdimNestedNameSpecifierLocBuilder & 533221345SdimNestedNameSpecifierLocBuilder:: 534221345Sdimoperator=(const NestedNameSpecifierLocBuilder &Other) { 535221345Sdim Representation = Other.Representation; 536341825Sdim 537221345Sdim if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) { 538221345Sdim // Re-use our storage. 539221345Sdim BufferSize = Other.BufferSize; 540221345Sdim memcpy(Buffer, Other.Buffer, BufferSize); 541221345Sdim return *this; 542221345Sdim } 543341825Sdim 544221345Sdim // Free our storage, if we have any. 545221345Sdim if (BufferCapacity) { 546221345Sdim free(Buffer); 547221345Sdim BufferCapacity = 0; 548221345Sdim } 549341825Sdim 550221345Sdim if (!Other.Buffer) { 551221345Sdim // Empty. 552276479Sdim Buffer = nullptr; 553221345Sdim BufferSize = 0; 554221345Sdim return *this; 555221345Sdim } 556341825Sdim 557221345Sdim if (Other.BufferCapacity == 0) { 558221345Sdim // Shallow copy is okay. 559221345Sdim Buffer = Other.Buffer; 560221345Sdim BufferSize = Other.BufferSize; 561221345Sdim return *this; 562221345Sdim } 563341825Sdim 564221345Sdim // Deep copy. 565344779Sdim BufferSize = 0; 566276479Sdim Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize, 567276479Sdim BufferCapacity); 568221345Sdim return *this; 569221345Sdim} 570221345Sdim 571341825Sdimvoid NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 572341825Sdim SourceLocation TemplateKWLoc, 573341825Sdim TypeLoc TL, 574221345Sdim SourceLocation ColonColonLoc) { 575341825Sdim Representation = NestedNameSpecifier::Create(Context, Representation, 576341825Sdim TemplateKWLoc.isValid(), 577221345Sdim TL.getTypePtr()); 578341825Sdim 579221345Sdim // Push source-location info into the buffer. 580221345Sdim SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity); 581221345Sdim SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 582221345Sdim} 583221345Sdim 584341825Sdimvoid NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 585221345Sdim IdentifierInfo *Identifier, 586341825Sdim SourceLocation IdentifierLoc, 587221345Sdim SourceLocation ColonColonLoc) { 588341825Sdim Representation = NestedNameSpecifier::Create(Context, Representation, 589221345Sdim Identifier); 590341825Sdim 591221345Sdim // Push source-location info into the buffer. 592221345Sdim SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity); 593221345Sdim SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 594221345Sdim} 595221345Sdim 596341825Sdimvoid NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 597221345Sdim NamespaceDecl *Namespace, 598341825Sdim SourceLocation NamespaceLoc, 599221345Sdim SourceLocation ColonColonLoc) { 600341825Sdim Representation = NestedNameSpecifier::Create(Context, Representation, 601221345Sdim Namespace); 602341825Sdim 603221345Sdim // Push source-location info into the buffer. 604221345Sdim SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity); 605221345Sdim SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 606221345Sdim} 607221345Sdim 608221345Sdimvoid NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 609221345Sdim NamespaceAliasDecl *Alias, 610341825Sdim SourceLocation AliasLoc, 611221345Sdim SourceLocation ColonColonLoc) { 612221345Sdim Representation = NestedNameSpecifier::Create(Context, Representation, Alias); 613341825Sdim 614221345Sdim // Push source-location info into the buffer. 615221345Sdim SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity); 616221345Sdim SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 617221345Sdim} 618221345Sdim 619341825Sdimvoid NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context, 620221345Sdim SourceLocation ColonColonLoc) { 621221345Sdim assert(!Representation && "Already have a nested-name-specifier!?"); 622221345Sdim Representation = NestedNameSpecifier::GlobalSpecifier(Context); 623341825Sdim 624221345Sdim // Push source-location info into the buffer. 625221345Sdim SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 626221345Sdim} 627221345Sdim 628280031Sdimvoid NestedNameSpecifierLocBuilder::MakeSuper(ASTContext &Context, 629280031Sdim CXXRecordDecl *RD, 630280031Sdim SourceLocation SuperLoc, 631280031Sdim SourceLocation ColonColonLoc) { 632280031Sdim Representation = NestedNameSpecifier::SuperSpecifier(Context, RD); 633280031Sdim 634280031Sdim // Push source-location info into the buffer. 635280031Sdim SaveSourceLocation(SuperLoc, Buffer, BufferSize, BufferCapacity); 636280031Sdim SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 637280031Sdim} 638280031Sdim 639341825Sdimvoid NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context, 640341825Sdim NestedNameSpecifier *Qualifier, 641221345Sdim SourceRange R) { 642221345Sdim Representation = Qualifier; 643341825Sdim 644341825Sdim // Construct bogus (but well-formed) source information for the 645221345Sdim // nested-name-specifier. 646221345Sdim BufferSize = 0; 647226633Sdim SmallVector<NestedNameSpecifier *, 4> Stack; 648221345Sdim for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix()) 649221345Sdim Stack.push_back(NNS); 650221345Sdim while (!Stack.empty()) { 651261991Sdim NestedNameSpecifier *NNS = Stack.pop_back_val(); 652221345Sdim switch (NNS->getKind()) { 653221345Sdim case NestedNameSpecifier::Identifier: 654221345Sdim case NestedNameSpecifier::Namespace: 655221345Sdim case NestedNameSpecifier::NamespaceAlias: 656221345Sdim SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity); 657221345Sdim break; 658341825Sdim 659221345Sdim case NestedNameSpecifier::TypeSpec: 660221345Sdim case NestedNameSpecifier::TypeSpecWithTemplate: { 661221345Sdim TypeSourceInfo *TSInfo 662221345Sdim = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0), 663221345Sdim R.getBegin()); 664341825Sdim SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize, 665221345Sdim BufferCapacity); 666221345Sdim break; 667221345Sdim } 668341825Sdim 669221345Sdim case NestedNameSpecifier::Global: 670280031Sdim case NestedNameSpecifier::Super: 671221345Sdim break; 672221345Sdim } 673341825Sdim 674221345Sdim // Save the location of the '::'. 675341825Sdim SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(), 676221345Sdim Buffer, BufferSize, BufferCapacity); 677221345Sdim } 678221345Sdim} 679221345Sdim 680221345Sdimvoid NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) { 681221345Sdim if (BufferCapacity) 682221345Sdim free(Buffer); 683221345Sdim 684221345Sdim if (!Other) { 685276479Sdim Representation = nullptr; 686221345Sdim BufferSize = 0; 687221345Sdim return; 688221345Sdim } 689341825Sdim 690341825Sdim // Rather than copying the data (which is wasteful), "adopt" the 691221345Sdim // pointer (which points into the ASTContext) but set the capacity to zero to 692221345Sdim // indicate that we don't own it. 693221345Sdim Representation = Other.getNestedNameSpecifier(); 694221345Sdim Buffer = static_cast<char *>(Other.getOpaqueData()); 695221345Sdim BufferSize = Other.getDataLength(); 696221345Sdim BufferCapacity = 0; 697221345Sdim} 698221345Sdim 699341825SdimNestedNameSpecifierLoc 700221345SdimNestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext &Context) const { 701221345Sdim if (!Representation) 702221345Sdim return NestedNameSpecifierLoc(); 703341825Sdim 704221345Sdim // If we adopted our data pointer from elsewhere in the AST context, there's 705221345Sdim // no need to copy the memory. 706221345Sdim if (BufferCapacity == 0) 707221345Sdim return NestedNameSpecifierLoc(Representation, Buffer); 708341825Sdim 709221345Sdim // FIXME: After copying the source-location information, should we free 710221345Sdim // our (temporary) buffer and adopt the ASTContext-allocated memory? 711221345Sdim // Doing so would optimize repeated calls to getWithLocInContext(). 712314564Sdim void *Mem = Context.Allocate(BufferSize, alignof(void *)); 713221345Sdim memcpy(Mem, Buffer, BufferSize); 714221345Sdim return NestedNameSpecifierLoc(Representation, Mem); 715221345Sdim} 716