clang API Documentation
00001 //===--- NestedNameSpecifier.cpp - C++ nested name specifiers -----*- C++ -*-=// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines the NestedNameSpecifier class, which represents 00011 // a C++ nested-name-specifier. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 #include "clang/AST/NestedNameSpecifier.h" 00015 #include "clang/AST/ASTContext.h" 00016 #include "clang/AST/Decl.h" 00017 #include "clang/AST/DeclCXX.h" 00018 #include "clang/AST/PrettyPrinter.h" 00019 #include "clang/AST/Type.h" 00020 #include "clang/AST/TypeLoc.h" 00021 #include "llvm/Support/AlignOf.h" 00022 #include "llvm/Support/raw_ostream.h" 00023 #include <cassert> 00024 00025 using namespace clang; 00026 00027 NestedNameSpecifier * 00028 NestedNameSpecifier::FindOrInsert(const ASTContext &Context, 00029 const NestedNameSpecifier &Mockup) { 00030 llvm::FoldingSetNodeID ID; 00031 Mockup.Profile(ID); 00032 00033 void *InsertPos = nullptr; 00034 NestedNameSpecifier *NNS 00035 = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos); 00036 if (!NNS) { 00037 NNS = new (Context, llvm::alignOf<NestedNameSpecifier>()) 00038 NestedNameSpecifier(Mockup); 00039 Context.NestedNameSpecifiers.InsertNode(NNS, InsertPos); 00040 } 00041 00042 return NNS; 00043 } 00044 00045 NestedNameSpecifier * 00046 NestedNameSpecifier::Create(const ASTContext &Context, 00047 NestedNameSpecifier *Prefix, IdentifierInfo *II) { 00048 assert(II && "Identifier cannot be NULL"); 00049 assert((!Prefix || Prefix->isDependent()) && "Prefix must be dependent"); 00050 00051 NestedNameSpecifier Mockup; 00052 Mockup.Prefix.setPointer(Prefix); 00053 Mockup.Prefix.setInt(StoredIdentifier); 00054 Mockup.Specifier = II; 00055 return FindOrInsert(Context, Mockup); 00056 } 00057 00058 NestedNameSpecifier * 00059 NestedNameSpecifier::Create(const ASTContext &Context, 00060 NestedNameSpecifier *Prefix, 00061 const NamespaceDecl *NS) { 00062 assert(NS && "Namespace cannot be NULL"); 00063 assert((!Prefix || 00064 (Prefix->getAsType() == nullptr && 00065 Prefix->getAsIdentifier() == nullptr)) && 00066 "Broken nested name specifier"); 00067 NestedNameSpecifier Mockup; 00068 Mockup.Prefix.setPointer(Prefix); 00069 Mockup.Prefix.setInt(StoredDecl); 00070 Mockup.Specifier = const_cast<NamespaceDecl *>(NS); 00071 return FindOrInsert(Context, Mockup); 00072 } 00073 00074 NestedNameSpecifier * 00075 NestedNameSpecifier::Create(const ASTContext &Context, 00076 NestedNameSpecifier *Prefix, 00077 NamespaceAliasDecl *Alias) { 00078 assert(Alias && "Namespace alias cannot be NULL"); 00079 assert((!Prefix || 00080 (Prefix->getAsType() == nullptr && 00081 Prefix->getAsIdentifier() == nullptr)) && 00082 "Broken nested name specifier"); 00083 NestedNameSpecifier Mockup; 00084 Mockup.Prefix.setPointer(Prefix); 00085 Mockup.Prefix.setInt(StoredDecl); 00086 Mockup.Specifier = Alias; 00087 return FindOrInsert(Context, Mockup); 00088 } 00089 00090 NestedNameSpecifier * 00091 NestedNameSpecifier::Create(const ASTContext &Context, 00092 NestedNameSpecifier *Prefix, 00093 bool Template, const Type *T) { 00094 assert(T && "Type cannot be NULL"); 00095 NestedNameSpecifier Mockup; 00096 Mockup.Prefix.setPointer(Prefix); 00097 Mockup.Prefix.setInt(Template? StoredTypeSpecWithTemplate : StoredTypeSpec); 00098 Mockup.Specifier = const_cast<Type*>(T); 00099 return FindOrInsert(Context, Mockup); 00100 } 00101 00102 NestedNameSpecifier * 00103 NestedNameSpecifier::Create(const ASTContext &Context, IdentifierInfo *II) { 00104 assert(II && "Identifier cannot be NULL"); 00105 NestedNameSpecifier Mockup; 00106 Mockup.Prefix.setPointer(nullptr); 00107 Mockup.Prefix.setInt(StoredIdentifier); 00108 Mockup.Specifier = II; 00109 return FindOrInsert(Context, Mockup); 00110 } 00111 00112 NestedNameSpecifier * 00113 NestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) { 00114 if (!Context.GlobalNestedNameSpecifier) 00115 Context.GlobalNestedNameSpecifier = 00116 new (Context, llvm::alignOf<NestedNameSpecifier>()) 00117 NestedNameSpecifier(); 00118 return Context.GlobalNestedNameSpecifier; 00119 } 00120 00121 NestedNameSpecifier * 00122 NestedNameSpecifier::SuperSpecifier(const ASTContext &Context, 00123 CXXRecordDecl *RD) { 00124 NestedNameSpecifier Mockup; 00125 Mockup.Prefix.setPointer(nullptr); 00126 Mockup.Prefix.setInt(StoredDecl); 00127 Mockup.Specifier = RD; 00128 return FindOrInsert(Context, Mockup); 00129 } 00130 00131 NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const { 00132 if (!Specifier) 00133 return Global; 00134 00135 switch (Prefix.getInt()) { 00136 case StoredIdentifier: 00137 return Identifier; 00138 00139 case StoredDecl: { 00140 NamedDecl *ND = static_cast<NamedDecl *>(Specifier); 00141 if (isa<CXXRecordDecl>(ND)) 00142 return Super; 00143 return isa<NamespaceDecl>(ND) ? Namespace : NamespaceAlias; 00144 } 00145 00146 case StoredTypeSpec: 00147 return TypeSpec; 00148 00149 case StoredTypeSpecWithTemplate: 00150 return TypeSpecWithTemplate; 00151 } 00152 00153 llvm_unreachable("Invalid NNS Kind!"); 00154 } 00155 00156 /// \brief Retrieve the namespace stored in this nested name specifier. 00157 NamespaceDecl *NestedNameSpecifier::getAsNamespace() const { 00158 if (Prefix.getInt() == StoredDecl) 00159 return dyn_cast<NamespaceDecl>(static_cast<NamedDecl *>(Specifier)); 00160 00161 return nullptr; 00162 } 00163 00164 /// \brief Retrieve the namespace alias stored in this nested name specifier. 00165 NamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const { 00166 if (Prefix.getInt() == StoredDecl) 00167 return dyn_cast<NamespaceAliasDecl>(static_cast<NamedDecl *>(Specifier)); 00168 00169 return nullptr; 00170 } 00171 00172 /// \brief Retrieve the record declaration stored in this nested name specifier. 00173 CXXRecordDecl *NestedNameSpecifier::getAsRecordDecl() const { 00174 if (Prefix.getInt() == StoredDecl) 00175 return dyn_cast<CXXRecordDecl>(static_cast<NamedDecl *>(Specifier)); 00176 00177 return nullptr; 00178 } 00179 00180 /// \brief Whether this nested name specifier refers to a dependent 00181 /// type or not. 00182 bool NestedNameSpecifier::isDependent() const { 00183 switch (getKind()) { 00184 case Identifier: 00185 // Identifier specifiers always represent dependent types 00186 return true; 00187 00188 case Namespace: 00189 case NamespaceAlias: 00190 case Global: 00191 return false; 00192 00193 case Super: { 00194 CXXRecordDecl *RD = static_cast<CXXRecordDecl *>(Specifier); 00195 for (const auto &Base : RD->bases()) 00196 if (Base.getType()->isDependentType()) 00197 return true; 00198 00199 return false; 00200 } 00201 00202 case TypeSpec: 00203 case TypeSpecWithTemplate: 00204 return getAsType()->isDependentType(); 00205 } 00206 00207 llvm_unreachable("Invalid NNS Kind!"); 00208 } 00209 00210 /// \brief Whether this nested name specifier refers to a dependent 00211 /// type or not. 00212 bool NestedNameSpecifier::isInstantiationDependent() const { 00213 switch (getKind()) { 00214 case Identifier: 00215 // Identifier specifiers always represent dependent types 00216 return true; 00217 00218 case Namespace: 00219 case NamespaceAlias: 00220 case Global: 00221 case Super: 00222 return false; 00223 00224 case TypeSpec: 00225 case TypeSpecWithTemplate: 00226 return getAsType()->isInstantiationDependentType(); 00227 } 00228 00229 llvm_unreachable("Invalid NNS Kind!"); 00230 } 00231 00232 bool NestedNameSpecifier::containsUnexpandedParameterPack() const { 00233 switch (getKind()) { 00234 case Identifier: 00235 return getPrefix() && getPrefix()->containsUnexpandedParameterPack(); 00236 00237 case Namespace: 00238 case NamespaceAlias: 00239 case Global: 00240 case Super: 00241 return false; 00242 00243 case TypeSpec: 00244 case TypeSpecWithTemplate: 00245 return getAsType()->containsUnexpandedParameterPack(); 00246 } 00247 00248 llvm_unreachable("Invalid NNS Kind!"); 00249 } 00250 00251 /// \brief Print this nested name specifier to the given output 00252 /// stream. 00253 void 00254 NestedNameSpecifier::print(raw_ostream &OS, 00255 const PrintingPolicy &Policy) const { 00256 if (getPrefix()) 00257 getPrefix()->print(OS, Policy); 00258 00259 switch (getKind()) { 00260 case Identifier: 00261 OS << getAsIdentifier()->getName(); 00262 break; 00263 00264 case Namespace: 00265 if (getAsNamespace()->isAnonymousNamespace()) 00266 return; 00267 00268 OS << getAsNamespace()->getName(); 00269 break; 00270 00271 case NamespaceAlias: 00272 OS << getAsNamespaceAlias()->getName(); 00273 break; 00274 00275 case Global: 00276 break; 00277 00278 case Super: 00279 OS << "__super"; 00280 break; 00281 00282 case TypeSpecWithTemplate: 00283 OS << "template "; 00284 // Fall through to print the type. 00285 00286 case TypeSpec: { 00287 const Type *T = getAsType(); 00288 00289 PrintingPolicy InnerPolicy(Policy); 00290 InnerPolicy.SuppressScope = true; 00291 00292 // Nested-name-specifiers are intended to contain minimally-qualified 00293 // types. An actual ElaboratedType will not occur, since we'll store 00294 // just the type that is referred to in the nested-name-specifier (e.g., 00295 // a TypedefType, TagType, etc.). However, when we are dealing with 00296 // dependent template-id types (e.g., Outer<T>::template Inner<U>), 00297 // the type requires its own nested-name-specifier for uniqueness, so we 00298 // suppress that nested-name-specifier during printing. 00299 assert(!isa<ElaboratedType>(T) && 00300 "Elaborated type in nested-name-specifier"); 00301 if (const TemplateSpecializationType *SpecType 00302 = dyn_cast<TemplateSpecializationType>(T)) { 00303 // Print the template name without its corresponding 00304 // nested-name-specifier. 00305 SpecType->getTemplateName().print(OS, InnerPolicy, true); 00306 00307 // Print the template argument list. 00308 TemplateSpecializationType::PrintTemplateArgumentList( 00309 OS, SpecType->getArgs(), SpecType->getNumArgs(), InnerPolicy); 00310 } else { 00311 // Print the type normally 00312 QualType(T, 0).print(OS, InnerPolicy); 00313 } 00314 break; 00315 } 00316 } 00317 00318 OS << "::"; 00319 } 00320 00321 void NestedNameSpecifier::dump(const LangOptions &LO) { 00322 print(llvm::errs(), PrintingPolicy(LO)); 00323 } 00324 00325 unsigned 00326 NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) { 00327 assert(Qualifier && "Expected a non-NULL qualifier"); 00328 00329 // Location of the trailing '::'. 00330 unsigned Length = sizeof(unsigned); 00331 00332 switch (Qualifier->getKind()) { 00333 case NestedNameSpecifier::Global: 00334 // Nothing more to add. 00335 break; 00336 00337 case NestedNameSpecifier::Identifier: 00338 case NestedNameSpecifier::Namespace: 00339 case NestedNameSpecifier::NamespaceAlias: 00340 case NestedNameSpecifier::Super: 00341 // The location of the identifier or namespace name. 00342 Length += sizeof(unsigned); 00343 break; 00344 00345 case NestedNameSpecifier::TypeSpecWithTemplate: 00346 case NestedNameSpecifier::TypeSpec: 00347 // The "void*" that points at the TypeLoc data. 00348 // Note: the 'template' keyword is part of the TypeLoc. 00349 Length += sizeof(void *); 00350 break; 00351 } 00352 00353 return Length; 00354 } 00355 00356 unsigned 00357 NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) { 00358 unsigned Length = 0; 00359 for (; Qualifier; Qualifier = Qualifier->getPrefix()) 00360 Length += getLocalDataLength(Qualifier); 00361 return Length; 00362 } 00363 00364 namespace { 00365 /// \brief Load a (possibly unaligned) source location from a given address 00366 /// and offset. 00367 SourceLocation LoadSourceLocation(void *Data, unsigned Offset) { 00368 unsigned Raw; 00369 memcpy(&Raw, static_cast<char *>(Data) + Offset, sizeof(unsigned)); 00370 return SourceLocation::getFromRawEncoding(Raw); 00371 } 00372 00373 /// \brief Load a (possibly unaligned) pointer from a given address and 00374 /// offset. 00375 void *LoadPointer(void *Data, unsigned Offset) { 00376 void *Result; 00377 memcpy(&Result, static_cast<char *>(Data) + Offset, sizeof(void*)); 00378 return Result; 00379 } 00380 } 00381 00382 SourceRange NestedNameSpecifierLoc::getSourceRange() const { 00383 if (!Qualifier) 00384 return SourceRange(); 00385 00386 NestedNameSpecifierLoc First = *this; 00387 while (NestedNameSpecifierLoc Prefix = First.getPrefix()) 00388 First = Prefix; 00389 00390 return SourceRange(First.getLocalSourceRange().getBegin(), 00391 getLocalSourceRange().getEnd()); 00392 } 00393 00394 SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const { 00395 if (!Qualifier) 00396 return SourceRange(); 00397 00398 unsigned Offset = getDataLength(Qualifier->getPrefix()); 00399 switch (Qualifier->getKind()) { 00400 case NestedNameSpecifier::Global: 00401 return LoadSourceLocation(Data, Offset); 00402 00403 case NestedNameSpecifier::Identifier: 00404 case NestedNameSpecifier::Namespace: 00405 case NestedNameSpecifier::NamespaceAlias: 00406 case NestedNameSpecifier::Super: 00407 return SourceRange(LoadSourceLocation(Data, Offset), 00408 LoadSourceLocation(Data, Offset + sizeof(unsigned))); 00409 00410 case NestedNameSpecifier::TypeSpecWithTemplate: 00411 case NestedNameSpecifier::TypeSpec: { 00412 // The "void*" that points at the TypeLoc data. 00413 // Note: the 'template' keyword is part of the TypeLoc. 00414 void *TypeData = LoadPointer(Data, Offset); 00415 TypeLoc TL(Qualifier->getAsType(), TypeData); 00416 return SourceRange(TL.getBeginLoc(), 00417 LoadSourceLocation(Data, Offset + sizeof(void*))); 00418 } 00419 } 00420 00421 llvm_unreachable("Invalid NNS Kind!"); 00422 } 00423 00424 TypeLoc NestedNameSpecifierLoc::getTypeLoc() const { 00425 assert((Qualifier->getKind() == NestedNameSpecifier::TypeSpec || 00426 Qualifier->getKind() == NestedNameSpecifier::TypeSpecWithTemplate) && 00427 "Nested-name-specifier location is not a type"); 00428 00429 // The "void*" that points at the TypeLoc data. 00430 unsigned Offset = getDataLength(Qualifier->getPrefix()); 00431 void *TypeData = LoadPointer(Data, Offset); 00432 return TypeLoc(Qualifier->getAsType(), TypeData); 00433 } 00434 00435 namespace { 00436 void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize, 00437 unsigned &BufferCapacity) { 00438 if (BufferSize + (End - Start) > BufferCapacity) { 00439 // Reallocate the buffer. 00440 unsigned NewCapacity 00441 = std::max((unsigned)(BufferCapacity? BufferCapacity * 2 00442 : sizeof(void*) * 2), 00443 (unsigned)(BufferSize + (End - Start))); 00444 char *NewBuffer = static_cast<char *>(malloc(NewCapacity)); 00445 memcpy(NewBuffer, Buffer, BufferSize); 00446 00447 if (BufferCapacity) 00448 free(Buffer); 00449 Buffer = NewBuffer; 00450 BufferCapacity = NewCapacity; 00451 } 00452 00453 memcpy(Buffer + BufferSize, Start, End - Start); 00454 BufferSize += End-Start; 00455 } 00456 00457 /// \brief Save a source location to the given buffer. 00458 void SaveSourceLocation(SourceLocation Loc, char *&Buffer, 00459 unsigned &BufferSize, unsigned &BufferCapacity) { 00460 unsigned Raw = Loc.getRawEncoding(); 00461 Append(reinterpret_cast<char *>(&Raw), 00462 reinterpret_cast<char *>(&Raw) + sizeof(unsigned), 00463 Buffer, BufferSize, BufferCapacity); 00464 } 00465 00466 /// \brief Save a pointer to the given buffer. 00467 void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize, 00468 unsigned &BufferCapacity) { 00469 Append(reinterpret_cast<char *>(&Ptr), 00470 reinterpret_cast<char *>(&Ptr) + sizeof(void *), 00471 Buffer, BufferSize, BufferCapacity); 00472 } 00473 } 00474 00475 NestedNameSpecifierLocBuilder:: 00476 NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other) 00477 : Representation(Other.Representation), Buffer(nullptr), 00478 BufferSize(0), BufferCapacity(0) 00479 { 00480 if (!Other.Buffer) 00481 return; 00482 00483 if (Other.BufferCapacity == 0) { 00484 // Shallow copy is okay. 00485 Buffer = Other.Buffer; 00486 BufferSize = Other.BufferSize; 00487 return; 00488 } 00489 00490 // Deep copy 00491 Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize, 00492 BufferCapacity); 00493 } 00494 00495 NestedNameSpecifierLocBuilder & 00496 NestedNameSpecifierLocBuilder:: 00497 operator=(const NestedNameSpecifierLocBuilder &Other) { 00498 Representation = Other.Representation; 00499 00500 if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) { 00501 // Re-use our storage. 00502 BufferSize = Other.BufferSize; 00503 memcpy(Buffer, Other.Buffer, BufferSize); 00504 return *this; 00505 } 00506 00507 // Free our storage, if we have any. 00508 if (BufferCapacity) { 00509 free(Buffer); 00510 BufferCapacity = 0; 00511 } 00512 00513 if (!Other.Buffer) { 00514 // Empty. 00515 Buffer = nullptr; 00516 BufferSize = 0; 00517 return *this; 00518 } 00519 00520 if (Other.BufferCapacity == 0) { 00521 // Shallow copy is okay. 00522 Buffer = Other.Buffer; 00523 BufferSize = Other.BufferSize; 00524 return *this; 00525 } 00526 00527 // Deep copy. 00528 Append(Other.Buffer, Other.Buffer + Other.BufferSize, Buffer, BufferSize, 00529 BufferCapacity); 00530 return *this; 00531 } 00532 00533 void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 00534 SourceLocation TemplateKWLoc, 00535 TypeLoc TL, 00536 SourceLocation ColonColonLoc) { 00537 Representation = NestedNameSpecifier::Create(Context, Representation, 00538 TemplateKWLoc.isValid(), 00539 TL.getTypePtr()); 00540 00541 // Push source-location info into the buffer. 00542 SavePointer(TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity); 00543 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 00544 } 00545 00546 void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 00547 IdentifierInfo *Identifier, 00548 SourceLocation IdentifierLoc, 00549 SourceLocation ColonColonLoc) { 00550 Representation = NestedNameSpecifier::Create(Context, Representation, 00551 Identifier); 00552 00553 // Push source-location info into the buffer. 00554 SaveSourceLocation(IdentifierLoc, Buffer, BufferSize, BufferCapacity); 00555 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 00556 } 00557 00558 void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 00559 NamespaceDecl *Namespace, 00560 SourceLocation NamespaceLoc, 00561 SourceLocation ColonColonLoc) { 00562 Representation = NestedNameSpecifier::Create(Context, Representation, 00563 Namespace); 00564 00565 // Push source-location info into the buffer. 00566 SaveSourceLocation(NamespaceLoc, Buffer, BufferSize, BufferCapacity); 00567 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 00568 } 00569 00570 void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, 00571 NamespaceAliasDecl *Alias, 00572 SourceLocation AliasLoc, 00573 SourceLocation ColonColonLoc) { 00574 Representation = NestedNameSpecifier::Create(Context, Representation, Alias); 00575 00576 // Push source-location info into the buffer. 00577 SaveSourceLocation(AliasLoc, Buffer, BufferSize, BufferCapacity); 00578 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 00579 } 00580 00581 void NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context, 00582 SourceLocation ColonColonLoc) { 00583 assert(!Representation && "Already have a nested-name-specifier!?"); 00584 Representation = NestedNameSpecifier::GlobalSpecifier(Context); 00585 00586 // Push source-location info into the buffer. 00587 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 00588 } 00589 00590 void NestedNameSpecifierLocBuilder::MakeSuper(ASTContext &Context, 00591 CXXRecordDecl *RD, 00592 SourceLocation SuperLoc, 00593 SourceLocation ColonColonLoc) { 00594 Representation = NestedNameSpecifier::SuperSpecifier(Context, RD); 00595 00596 // Push source-location info into the buffer. 00597 SaveSourceLocation(SuperLoc, Buffer, BufferSize, BufferCapacity); 00598 SaveSourceLocation(ColonColonLoc, Buffer, BufferSize, BufferCapacity); 00599 } 00600 00601 void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context, 00602 NestedNameSpecifier *Qualifier, 00603 SourceRange R) { 00604 Representation = Qualifier; 00605 00606 // Construct bogus (but well-formed) source information for the 00607 // nested-name-specifier. 00608 BufferSize = 0; 00609 SmallVector<NestedNameSpecifier *, 4> Stack; 00610 for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix()) 00611 Stack.push_back(NNS); 00612 while (!Stack.empty()) { 00613 NestedNameSpecifier *NNS = Stack.pop_back_val(); 00614 switch (NNS->getKind()) { 00615 case NestedNameSpecifier::Identifier: 00616 case NestedNameSpecifier::Namespace: 00617 case NestedNameSpecifier::NamespaceAlias: 00618 SaveSourceLocation(R.getBegin(), Buffer, BufferSize, BufferCapacity); 00619 break; 00620 00621 case NestedNameSpecifier::TypeSpec: 00622 case NestedNameSpecifier::TypeSpecWithTemplate: { 00623 TypeSourceInfo *TSInfo 00624 = Context.getTrivialTypeSourceInfo(QualType(NNS->getAsType(), 0), 00625 R.getBegin()); 00626 SavePointer(TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize, 00627 BufferCapacity); 00628 break; 00629 } 00630 00631 case NestedNameSpecifier::Global: 00632 case NestedNameSpecifier::Super: 00633 break; 00634 } 00635 00636 // Save the location of the '::'. 00637 SaveSourceLocation(Stack.empty()? R.getEnd() : R.getBegin(), 00638 Buffer, BufferSize, BufferCapacity); 00639 } 00640 } 00641 00642 void NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) { 00643 if (BufferCapacity) 00644 free(Buffer); 00645 00646 if (!Other) { 00647 Representation = nullptr; 00648 BufferSize = 0; 00649 return; 00650 } 00651 00652 // Rather than copying the data (which is wasteful), "adopt" the 00653 // pointer (which points into the ASTContext) but set the capacity to zero to 00654 // indicate that we don't own it. 00655 Representation = Other.getNestedNameSpecifier(); 00656 Buffer = static_cast<char *>(Other.getOpaqueData()); 00657 BufferSize = Other.getDataLength(); 00658 BufferCapacity = 0; 00659 } 00660 00661 NestedNameSpecifierLoc 00662 NestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext &Context) const { 00663 if (!Representation) 00664 return NestedNameSpecifierLoc(); 00665 00666 // If we adopted our data pointer from elsewhere in the AST context, there's 00667 // no need to copy the memory. 00668 if (BufferCapacity == 0) 00669 return NestedNameSpecifierLoc(Representation, Buffer); 00670 00671 // FIXME: After copying the source-location information, should we free 00672 // our (temporary) buffer and adopt the ASTContext-allocated memory? 00673 // Doing so would optimize repeated calls to getWithLocInContext(). 00674 void *Mem = Context.Allocate(BufferSize, llvm::alignOf<void *>()); 00675 memcpy(Mem, Buffer, BufferSize); 00676 return NestedNameSpecifierLoc(Representation, Mem); 00677 }