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