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/DeclCXX.h" 18#include "clang/AST/PrettyPrinter.h" 19#include "clang/AST/Type.h" 20#include "clang/AST/TypeLoc.h" 21#include "llvm/Support/raw_ostream.h" 22#include <cassert> 23 24using namespace clang; 25 26NestedNameSpecifier * 27NestedNameSpecifier::FindOrInsert(const ASTContext &Context, 28 const NestedNameSpecifier &Mockup) { 29 llvm::FoldingSetNodeID ID; 30 Mockup.Profile(ID); 31 32 void *InsertPos = 0; 33 NestedNameSpecifier *NNS 34 = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos); 35 if (!NNS) { 36 NNS = new (Context, 4) NestedNameSpecifier(Mockup); 37 Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos); 38 } 39 40 return NNS; 41} 42 43NestedNameSpecifier * 44NestedNameSpecifier::Create(const ASTContext &Context, 45 NestedNameSpecifier *Prefix, IdentifierInfo *II) { 46 assert(II && "Identifier cannot be NULL"); 47 assert((!Prefix || Prefix->isDependent()) && "Prefix must be dependent"); 48 49 NestedNameSpecifier Mockup; 50 Mockup.Prefix.setPointer(Prefix); 51 Mockup.Prefix.setInt(StoredIdentifier); 52 Mockup.Specifier = II; 53 return FindOrInsert(Context, Mockup); 54} 55 56NestedNameSpecifier * 57NestedNameSpecifier::Create(const ASTContext &Context, 58 NestedNameSpecifier *Prefix, NamespaceDecl *NS) { 59 assert(NS && "Namespace cannot be NULL"); 60 assert((!Prefix || 61 (Prefix->getAsType() == 0 && Prefix->getAsIdentifier() == 0)) && 62 "Broken nested name specifier"); 63 NestedNameSpecifier Mockup; 64 Mockup.Prefix.setPointer(Prefix); 65 Mockup.Prefix.setInt(StoredNamespaceOrAlias); 66 Mockup.Specifier = NS; 67 return FindOrInsert(Context, Mockup); 68} 69 70NestedNameSpecifier * 71NestedNameSpecifier::Create(const ASTContext &Context, 72 NestedNameSpecifier *Prefix, 73 NamespaceAliasDecl *Alias) { 74 assert(Alias && "Namespace alias cannot be NULL"); 75 assert((!Prefix || 76 (Prefix->getAsType() == 0 && Prefix->getAsIdentifier() == 0)) && 77 "Broken nested name specifier"); 78 NestedNameSpecifier Mockup; 79 Mockup.Prefix.setPointer(Prefix); 80 Mockup.Prefix.setInt(StoredNamespaceOrAlias); 81 Mockup.Specifier = Alias; 82 return FindOrInsert(Context, Mockup); 83} 84 85NestedNameSpecifier * 86NestedNameSpecifier::Create(const ASTContext &Context, 87 NestedNameSpecifier *Prefix, 88 bool Template, const Type *T) { 89 assert(T && "Type cannot be NULL"); 90 NestedNameSpecifier Mockup; 91 Mockup.Prefix.setPointer(Prefix); 92 Mockup.Prefix.setInt(Template? StoredTypeSpecWithTemplate : StoredTypeSpec); 93 Mockup.Specifier = const_cast<Type*>(T); 94 return FindOrInsert(Context, Mockup); 95} 96 97NestedNameSpecifier * 98NestedNameSpecifier::Create(const ASTContext &Context, IdentifierInfo *II) { 99 assert(II && "Identifier cannot be NULL"); 100 NestedNameSpecifier Mockup; 101 Mockup.Prefix.setPointer(0); 102 Mockup.Prefix.setInt(StoredIdentifier); 103 Mockup.Specifier = II; 104 return FindOrInsert(Context, Mockup); 105} 106 107NestedNameSpecifier * 108NestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) { 109 if (!Context.GlobalNestedNameSpecifier) 110 Context.GlobalNestedNameSpecifier = new (Context, 4) NestedNameSpecifier(); 111 return Context.GlobalNestedNameSpecifier; 112} 113 114NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const { 115 if (Specifier == 0) 116 return Global; 117 118 switch (Prefix.getInt()) { 119 case StoredIdentifier: 120 return Identifier; 121 122 case StoredNamespaceOrAlias: 123 return isa<NamespaceDecl>(static_cast<NamedDecl *>(Specifier))? Namespace 124 : NamespaceAlias; 125 126 case StoredTypeSpec: 127 return TypeSpec; 128 129 case StoredTypeSpecWithTemplate: 130 return TypeSpecWithTemplate; 131 } 132 133 llvm_unreachable("Invalid NNS Kind!"); 134} 135 136/// \brief Retrieve the namespace stored in this nested name 137/// specifier. 138NamespaceDecl *NestedNameSpecifier::getAsNamespace() const { 139 if (Prefix.getInt() == StoredNamespaceOrAlias) 140 return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier)); 141 142 return 0; 143} 144 145/// \brief Retrieve the namespace alias stored in this nested name 146/// specifier. 147NamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const { 148 if (Prefix.getInt() == StoredNamespaceOrAlias) 149 return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier)); 150 151 return 0; 152} 153 154 155/// \brief Whether this nested name specifier refers to a dependent 156/// type or not. 157bool NestedNameSpecifier::isDependent() const { 158 switch (getKind()) { 159 case Identifier: 160 // Identifier specifiers always represent dependent types 161 return true; 162 163 case Namespace: 164 case NamespaceAlias: 165 case Global: 166 return false; 167 168 case TypeSpec: 169 case TypeSpecWithTemplate: 170 return getAsType()->isDependentType(); 171 } 172 173 llvm_unreachable("Invalid NNS Kind!"); 174} 175 176/// \brief Whether this nested name specifier refers to a dependent 177/// type or not. 178bool NestedNameSpecifier::isInstantiationDependent() const { 179 switch (getKind()) { 180 case Identifier: 181 // Identifier specifiers always represent dependent types 182 return true; 183 184 case Namespace: 185 case NamespaceAlias: 186 case Global: 187 return false; 188 189 case TypeSpec: 190 case TypeSpecWithTemplate: 191 return getAsType()->isInstantiationDependentType(); 192 } 193 194 llvm_unreachable("Invalid NNS Kind!"); 195} 196 197bool NestedNameSpecifier::containsUnexpandedParameterPack() const { 198 switch (getKind()) { 199 case Identifier: 200 return getPrefix() && getPrefix()->containsUnexpandedParameterPack(); 201 202 case Namespace: 203 case NamespaceAlias: 204 case Global: 205 return false; 206 207 case TypeSpec: 208 case TypeSpecWithTemplate: 209 return getAsType()->containsUnexpandedParameterPack(); 210 } 211 212 llvm_unreachable("Invalid NNS Kind!"); 213} 214 215/// \brief Print this nested name specifier to the given output 216/// stream. 217void 218NestedNameSpecifier::print(raw_ostream &OS, 219 const PrintingPolicy &Policy) const { 220 if (getPrefix()) 221 getPrefix()->print(OS, Policy); 222 223 switch (getKind()) { 224 case Identifier: 225 OS << getAsIdentifier()->getName(); 226 break; 227 228 case Namespace: 229 if (getAsNamespace()->isAnonymousNamespace()) 230 return; 231 232 OS << getAsNamespace()->getName(); 233 break; 234 235 case NamespaceAlias: 236 OS << getAsNamespaceAlias()->getName(); 237 break; 238 239 case Global: 240 break; 241 242 case TypeSpecWithTemplate: 243 OS << "template "; 244 // Fall through to print the type. 245 246 case TypeSpec: { 247 std::string TypeStr; 248 const Type *T = getAsType(); 249 250 PrintingPolicy InnerPolicy(Policy); 251 InnerPolicy.SuppressScope = true; 252 253 // Nested-name-specifiers are intended to contain minimally-qualified 254 // types. An actual ElaboratedType will not occur, since we'll store 255 // just the type that is referred to in the nested-name-specifier (e.g., 256 // a TypedefType, TagType, etc.). However, when we are dealing with 257 // dependent template-id types (e.g., Outer<T>::template Inner<U>), 258 // the type requires its own nested-name-specifier for uniqueness, so we 259 // suppress that nested-name-specifier during printing. 260 assert(!isa<ElaboratedType>(T) && 261 "Elaborated type in nested-name-specifier"); 262 if (const TemplateSpecializationType *SpecType 263 = dyn_cast<TemplateSpecializationType>(T)) { 264 // Print the template name without its corresponding 265 // nested-name-specifier. 266 SpecType->getTemplateName().print(OS, InnerPolicy, true); 267 268 // Print the template argument list. 269 TypeStr = TemplateSpecializationType::PrintTemplateArgumentList( 270 SpecType->getArgs(), 271 SpecType->getNumArgs(), 272 InnerPolicy); 273 } else { 274 // Print the type normally 275 TypeStr = QualType(T, 0).getAsString(InnerPolicy); 276 } 277 OS << TypeStr; 278 break; 279 } 280 } 281 282 OS << "::"; 283} 284 285void NestedNameSpecifier::dump(const LangOptions &LO) { 286 print(llvm::errs(), PrintingPolicy(LO)); 287} 288 289unsigned 290NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) { 291 assert(Qualifier && "Expected a non-NULL qualifier"); 292 293 // Location of the trailing '::'. 294 unsigned Length = sizeof(unsigned); 295 296 switch (Qualifier->getKind()) { 297 case NestedNameSpecifier::Global: 298 // Nothing more to add. 299 break; 300 301 case NestedNameSpecifier::Identifier: 302 case NestedNameSpecifier::Namespace: 303 case NestedNameSpecifier::NamespaceAlias: 304 // The location of the identifier or namespace name. 305 Length += sizeof(unsigned); 306 break; 307 308 case NestedNameSpecifier::TypeSpecWithTemplate: 309 case NestedNameSpecifier::TypeSpec: 310 // The "void*" that points at the TypeLoc data. 311 // Note: the 'template' keyword is part of the TypeLoc. 312 Length += sizeof(void *); 313 break; 314 } 315 316 return Length; 317} 318 319unsigned 320NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) { 321 unsigned Length = 0; 322 for (; Qualifier; Qualifier = Qualifier->getPrefix()) 323 Length += getLocalDataLength(Qualifier); 324 return Length; 325} 326 327namespace { 328 /// \brief Load a (possibly unaligned) source location from a given address 329 /// and offset. 330 SourceLocation LoadSourceLocation(void *Data, unsigned Offset) { 331 unsigned Raw; 332 memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(unsigned)); 333 return SourceLocation::getFromRawEncoding(Raw); 334 } 335 336 /// \brief Load a (possibly unaligned) pointer from a given address and 337 /// offset. 338 void *LoadPointer(void *Data, unsigned Offset) { 339 void *Result; 340 memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*)); 341 return Result; 342 } 343} 344 345SourceRange NestedNameSpecifierLoc::getSourceRange() const { 346 if (!Qualifier) 347 return SourceRange(); 348 349 NestedNameSpecifierLoc First = *this; 350 while (NestedNameSpecifierLoc Prefix = First.getPrefix()) 351 First = Prefix; 352 353 return SourceRange(First.getLocalSourceRange().getBegin(), 354 getLocalSourceRange().getEnd()); 355} 356 357SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const { 358 if (!Qualifier) 359 return SourceRange(); 360 361 unsigned Offset = getDataLength(Qualifier->getPrefix()); 362 switch (Qualifier->getKind()) { 363 case NestedNameSpecifier::Global: 364 return LoadSourceLocation(Data, Offset); 365 366 case NestedNameSpecifier::Identifier: 367 case NestedNameSpecifier::Namespace: 368 case NestedNameSpecifier::NamespaceAlias: 369 return SourceRange(LoadSourceLocation(Data, Offset), 370 LoadSourceLocation(Data, Offset + sizeof(unsigned))); 371 372 case NestedNameSpecifier::TypeSpecWithTemplate: 373 case NestedNameSpecifier::TypeSpec: { 374 // The "void*" that points at the TypeLoc data. 375 // Note: the 'template' keyword is part of the TypeLoc. 376 void *TypeData = LoadPointer(Data, Offset); 377 TypeLoc TL(Qualifier->getAsType(), TypeData); 378 return SourceRange(TL.getBeginLoc(), 379 LoadSourceLocation(Data, Offset + sizeof(void*))); 380 } 381 } 382 383 llvm_unreachable("Invalid NNS Kind!"); 384} 385 386TypeLoc NestedNameSpecifierLoc::getTypeLoc() const { 387 assert((Qualifier->getKind() == NestedNameSpecifier::TypeSpec || 388 Qualifier->getKind() == NestedNameSpecifier::TypeSpecWithTemplate) && 389 "Nested-name-specifier location is not a type"); 390 391 // The "void*" that points at the TypeLoc data. 392 unsigned Offset = getDataLength(Qualifier->getPrefix()); 393 void *TypeData = LoadPointer(Data, Offset); 394 return TypeLoc(Qualifier->getAsType(), TypeData); 395} 396 397namespace { 398 void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize, 399 unsigned &BufferCapacity) { 400 if (BufferSize + (End - Start) > BufferCapacity) { 401 // Reallocate the buffer. 402 unsigned NewCapacity 403 = std::max((unsigned)(BufferCapacity? BufferCapacity * 2 404 : sizeof(void*) * 2), 405 (unsigned)(BufferSize + (End - Start))); 406 char *NewBuffer = static_cast<char *>(malloc(NewCapacity)); 407 memcpy(NewBuffer, Buffer, BufferSize); 408 409 if (BufferCapacity) 410 free(Buffer); 411 Buffer = NewBuffer; 412 BufferCapacity = NewCapacity; 413 } 414 415 memcpy(Buffer + BufferSize, Start, End - Start); 416 BufferSize += End-Start; 417 } 418 419 /// \brief Save a source location to the given buffer. 420 void SaveSourceLocation(SourceLocation Loc, char *&Buffer, 421 unsigned &BufferSize, unsigned &BufferCapacity) { 422 unsigned Raw = Loc.getRawEncoding(); 423 Append(reinterpret_cast<char *>(&Raw), 424 reinterpret_cast<char *>(&Raw) + sizeof(unsigned), 425 Buffer, BufferSize, BufferCapacity); 426 } 427 428 /// \brief Save a pointer to the given buffer. 429 void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize, 430 unsigned &BufferCapacity) { 431 Append(reinterpret_cast<char *>(&Ptr), 432 reinterpret_cast<char *>(&Ptr) + sizeof(void *), 433 Buffer, BufferSize, BufferCapacity); 434 } 435} 436 437NestedNameSpecifierLocBuilder:: 438NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other) 439 : Representation(Other.Representation), Buffer(0), 440 BufferSize(0), BufferCapacity(0) 441{ 442 if (!Other.Buffer) 443 return; 444 445 if (Other.BufferCapacity == 0) { 446 // Shallow copy is okay. 447 Buffer = Other.Buffer; 448 BufferSize = Other.BufferSize; 449 return; 450 } 451 452 // Deep copy 453 BufferSize = Other.BufferSize; 454 BufferCapacity = Other.BufferSize; 455 Buffer = static_cast<char *>(malloc(BufferCapacity)); 456 memcpy(Buffer, Other.Buffer, BufferSize); 457} 458 459NestedNameSpecifierLocBuilder & 460NestedNameSpecifierLocBuilder:: 461operator=(const NestedNameSpecifierLocBuilder &Other) { 462 Representation = Other.Representation; 463 464 if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) { 465 // Re-use our storage. 466 BufferSize = Other.BufferSize; 467 memcpy(Buffer, Other.Buffer, BufferSize); 468 return *this; 469 } 470 471 // Free our storage, if we have any. 472 if (BufferCapacity) { 473 free(Buffer); 474 BufferCapacity = 0; 475 } 476 477 if (!Other.Buffer) { 478 // Empty. 479 Buffer = 0; 480 BufferSize = 0; 481 return *this; 482 } 483 484 if (Other.BufferCapacity == 0) { 485 // Shallow copy is okay. 486 Buffer = Other.Buffer; 487 BufferSize = Other.BufferSize; 488 return *this; 489 } 490 491 // Deep copy. 492 BufferSize = Other.BufferSize; 493 BufferCapacity = BufferSize; 494 Buffer = static_cast<char *>(malloc(BufferSize)); 495 memcpy(Buffer, Other.Buffer, BufferSize); 496 return *this; 497} 498 499void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 500 SourceLocation TemplateKWLoc, 501 TypeLoc TL, 502 SourceLocation ColonColonLoc) { 503 Representation = NestedNameSpecifier::Create(Context, Representation, 504 TemplateKWLoc.isValid(), 505 TL.getTypePtr()); 506 507 // Push source-location info into the buffer. 508 SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity); 509 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 510} 511 512void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 513 IdentifierInfo *Identifier, 514 SourceLocation IdentifierLoc, 515 SourceLocation ColonColonLoc) { 516 Representation = NestedNameSpecifier::Create(Context, Representation, 517 Identifier); 518 519 // Push source-location info into the buffer. 520 SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity); 521 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 522} 523 524void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 525 NamespaceDecl *Namespace, 526 SourceLocation NamespaceLoc, 527 SourceLocation ColonColonLoc) { 528 Representation = NestedNameSpecifier::Create(Context, Representation, 529 Namespace); 530 531 // Push source-location info into the buffer. 532 SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity); 533 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 534} 535 536void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 537 NamespaceAliasDecl *Alias, 538 SourceLocation AliasLoc, 539 SourceLocation ColonColonLoc) { 540 Representation = NestedNameSpecifier::Create(Context, Representation, Alias); 541 542 // Push source-location info into the buffer. 543 SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity); 544 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 545} 546 547void NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context, 548 SourceLocation ColonColonLoc) { 549 assert(!Representation && "Already have a nested-name-specifier!?"); 550 Representation = NestedNameSpecifier::GlobalSpecifier(Context); 551 552 // Push source-location info into the buffer. 553 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 554} 555 556void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context, 557 NestedNameSpecifier *Qualifier, 558 SourceRange R) { 559 Representation = Qualifier; 560 561 // Construct bogus (but well-formed) source information for the 562 // nested-name-specifier. 563 BufferSize = 0; 564 SmallVector<NestedNameSpecifier *, 4> Stack; 565 for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix()) 566 Stack.push_back(NNS); 567 while (!Stack.empty()) { 568 NestedNameSpecifier *NNS = Stack.back(); 569 Stack.pop_back(); 570 switch (NNS->getKind()) { 571 case NestedNameSpecifier::Identifier: 572 case NestedNameSpecifier::Namespace: 573 case NestedNameSpecifier::NamespaceAlias: 574 SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity); 575 break; 576 577 case NestedNameSpecifier::TypeSpec: 578 case NestedNameSpecifier::TypeSpecWithTemplate: { 579 TypeSourceInfo *TSInfo 580 = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0), 581 R.getBegin()); 582 SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize, 583 BufferCapacity); 584 break; 585 } 586 587 case NestedNameSpecifier::Global: 588 break; 589 } 590 591 // Save the location of the '::'. 592 SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(), 593 Buffer, BufferSize, BufferCapacity); 594 } 595} 596 597void NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) { 598 if (BufferCapacity) 599 free(Buffer); 600 601 if (!Other) { 602 Representation = 0; 603 BufferSize = 0; 604 return; 605 } 606 607 // Rather than copying the data (which is wasteful), "adopt" the 608 // pointer (which points into the ASTContext) but set the capacity to zero to 609 // indicate that we don't own it. 610 Representation = Other.getNestedNameSpecifier(); 611 Buffer = static_cast<char *>(Other.getOpaqueData()); 612 BufferSize = Other.getDataLength(); 613 BufferCapacity = 0; 614} 615 616NestedNameSpecifierLoc 617NestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext &Context) const { 618 if (!Representation) 619 return NestedNameSpecifierLoc(); 620 621 // If we adopted our data pointer from elsewhere in the AST context, there's 622 // no need to copy the memory. 623 if (BufferCapacity == 0) 624 return NestedNameSpecifierLoc(Representation, Buffer); 625 626 // FIXME: After copying the source-location information, should we free 627 // our (temporary) buffer and adopt the ASTContext-allocated memory? 628 // Doing so would optimize repeated calls to getWithLocInContext(). 629 void *Mem = Context.Allocate(BufferSize, llvm::alignOf<void *>()); 630 memcpy(Mem, Buffer, BufferSize); 631 return NestedNameSpecifierLoc(Representation, Mem); 632} 633 634