1//===- NestedNameSpecifier.cpp - C++ nested name specifiers ---------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the NestedNameSpecifier class, which represents
10// a C++ nested-name-specifier.
11//
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/DeclTemplate.h"
19#include "clang/AST/DependenceFlags.h"
20#include "clang/AST/PrettyPrinter.h"
21#include "clang/AST/TemplateName.h"
22#include "clang/AST/Type.h"
23#include "clang/AST/TypeLoc.h"
24#include "clang/Basic/LLVM.h"
25#include "clang/Basic/LangOptions.h"
26#include "clang/Basic/SourceLocation.h"
27#include "llvm/ADT/FoldingSet.h"
28#include "llvm/Support/Compiler.h"
29#include "llvm/Support/ErrorHandling.h"
30#include "llvm/Support/raw_ostream.h"
31#include <algorithm>
32#include <cassert>
33#include <cstdlib>
34#include <cstring>
35
36using namespace clang;
37
38NestedNameSpecifier *
39NestedNameSpecifier::FindOrInsert(const ASTContext &Context,
40 const NestedNameSpecifier &Mockup) {
41 llvm::FoldingSetNodeID ID;
42 Mockup.Profile(ID);
43
44 void *InsertPos = nullptr;
45 NestedNameSpecifier *NNS
46 = Context.NestedNameSpecifiers.FindNodeOrInsertPos(ID, InsertPos);
47 if (!NNS) {
48 NNS =
49 new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier(Mockup);
50 Context.NestedNameSpecifiers.InsertNode(N: NNS, InsertPos);
51 }
52
53 return NNS;
54}
55
56NestedNameSpecifier *NestedNameSpecifier::Create(const ASTContext &Context,
57 NestedNameSpecifier *Prefix,
58 const IdentifierInfo *II) {
59 assert(II && "Identifier cannot be NULL");
60 assert((!Prefix || Prefix->isDependent()) && "Prefix must be dependent");
61
62 NestedNameSpecifier Mockup;
63 Mockup.Prefix.setPointer(Prefix);
64 Mockup.Prefix.setInt(StoredIdentifier);
65 Mockup.Specifier = const_cast<IdentifierInfo *>(II);
66 return FindOrInsert(Context, Mockup);
67}
68
69NestedNameSpecifier *
70NestedNameSpecifier::Create(const ASTContext &Context,
71 NestedNameSpecifier *Prefix,
72 const NamespaceDecl *NS) {
73 assert(NS && "Namespace cannot be NULL");
74 assert((!Prefix ||
75 (Prefix->getAsType() == nullptr &&
76 Prefix->getAsIdentifier() == nullptr)) &&
77 "Broken nested name specifier");
78 NestedNameSpecifier Mockup;
79 Mockup.Prefix.setPointer(Prefix);
80 Mockup.Prefix.setInt(StoredDecl);
81 Mockup.Specifier = const_cast<NamespaceDecl *>(NS);
82 return FindOrInsert(Context, Mockup);
83}
84
85NestedNameSpecifier *
86NestedNameSpecifier::Create(const ASTContext &Context,
87 NestedNameSpecifier *Prefix,
88 const NamespaceAliasDecl *Alias) {
89 assert(Alias && "Namespace alias cannot be NULL");
90 assert((!Prefix ||
91 (Prefix->getAsType() == nullptr &&
92 Prefix->getAsIdentifier() == nullptr)) &&
93 "Broken nested name specifier");
94 NestedNameSpecifier Mockup;
95 Mockup.Prefix.setPointer(Prefix);
96 Mockup.Prefix.setInt(StoredDecl);
97 Mockup.Specifier = const_cast<NamespaceAliasDecl *>(Alias);
98 return FindOrInsert(Context, Mockup);
99}
100
101NestedNameSpecifier *NestedNameSpecifier::Create(const ASTContext &Context,
102 NestedNameSpecifier *Prefix,
103 const Type *T) {
104 assert(T && "Type cannot be NULL");
105 NestedNameSpecifier Mockup;
106 Mockup.Prefix.setPointer(Prefix);
107 Mockup.Prefix.setInt(StoredTypeSpec);
108 Mockup.Specifier = const_cast<Type*>(T);
109 return FindOrInsert(Context, Mockup);
110}
111
112NestedNameSpecifier *NestedNameSpecifier::Create(const ASTContext &Context,
113 const IdentifierInfo *II) {
114 assert(II && "Identifier cannot be NULL");
115 NestedNameSpecifier Mockup;
116 Mockup.Prefix.setPointer(nullptr);
117 Mockup.Prefix.setInt(StoredIdentifier);
118 Mockup.Specifier = const_cast<IdentifierInfo *>(II);
119 return FindOrInsert(Context, Mockup);
120}
121
122NestedNameSpecifier *
123NestedNameSpecifier::GlobalSpecifier(const ASTContext &Context) {
124 if (!Context.GlobalNestedNameSpecifier)
125 Context.GlobalNestedNameSpecifier =
126 new (Context, alignof(NestedNameSpecifier)) NestedNameSpecifier();
127 return Context.GlobalNestedNameSpecifier;
128}
129
130NestedNameSpecifier *
131NestedNameSpecifier::SuperSpecifier(const ASTContext &Context,
132 CXXRecordDecl *RD) {
133 NestedNameSpecifier Mockup;
134 Mockup.Prefix.setPointer(nullptr);
135 Mockup.Prefix.setInt(StoredDecl);
136 Mockup.Specifier = RD;
137 return FindOrInsert(Context, Mockup);
138}
139
140NestedNameSpecifier::SpecifierKind NestedNameSpecifier::getKind() const {
141 if (!Specifier)
142 return Global;
143
144 switch (Prefix.getInt()) {
145 case StoredIdentifier:
146 return Identifier;
147
148 case StoredDecl: {
149 NamedDecl *ND = static_cast<NamedDecl *>(Specifier);
150 if (isa<CXXRecordDecl>(Val: ND))
151 return Super;
152 return isa<NamespaceDecl>(Val: ND) ? Namespace : NamespaceAlias;
153 }
154
155 case StoredTypeSpec:
156 return TypeSpec;
157 }
158
159 llvm_unreachable("Invalid NNS Kind!");
160}
161
162/// Retrieve the namespace stored in this nested name specifier.
163NamespaceDecl *NestedNameSpecifier::getAsNamespace() const {
164 if (Prefix.getInt() == StoredDecl)
165 return dyn_cast<NamespaceDecl>(Val: static_cast<NamedDecl *>(Specifier));
166
167 return nullptr;
168}
169
170/// Retrieve the namespace alias stored in this nested name specifier.
171NamespaceAliasDecl *NestedNameSpecifier::getAsNamespaceAlias() const {
172 if (Prefix.getInt() == StoredDecl)
173 return dyn_cast<NamespaceAliasDecl>(Val: static_cast<NamedDecl *>(Specifier));
174
175 return nullptr;
176}
177
178/// Retrieve the record declaration stored in this nested name specifier.
179CXXRecordDecl *NestedNameSpecifier::getAsRecordDecl() const {
180 switch (Prefix.getInt()) {
181 case StoredIdentifier:
182 return nullptr;
183
184 case StoredDecl:
185 return dyn_cast<CXXRecordDecl>(Val: static_cast<NamedDecl *>(Specifier));
186
187 case StoredTypeSpec:
188 return getAsType()->getAsCXXRecordDecl();
189 }
190
191 llvm_unreachable("Invalid NNS Kind!");
192}
193
194NestedNameSpecifierDependence NestedNameSpecifier::getDependence() const {
195 switch (getKind()) {
196 case Identifier: {
197 // Identifier specifiers always represent dependent types
198 auto F = NestedNameSpecifierDependence::Dependent |
199 NestedNameSpecifierDependence::Instantiation;
200 // Prefix can contain unexpanded template parameters.
201 if (getPrefix())
202 return F | getPrefix()->getDependence();
203 return F;
204 }
205
206 case Namespace:
207 case NamespaceAlias:
208 case Global:
209 return NestedNameSpecifierDependence::None;
210
211 case Super: {
212 CXXRecordDecl *RD = static_cast<CXXRecordDecl *>(Specifier);
213 for (const auto &Base : RD->bases())
214 if (Base.getType()->isDependentType())
215 // FIXME: must also be instantiation-dependent.
216 return NestedNameSpecifierDependence::Dependent;
217 return NestedNameSpecifierDependence::None;
218 }
219
220 case TypeSpec: {
221 NestedNameSpecifierDependence Dep =
222 toNestedNameSpecifierDependendence(D: getAsType()->getDependence());
223 if (NestedNameSpecifier *Prefix = getPrefix())
224 Dep |=
225 Prefix->getDependence() & ~NestedNameSpecifierDependence::Dependent;
226 return Dep;
227 }
228 }
229 llvm_unreachable("Invalid NNS Kind!");
230}
231
232bool NestedNameSpecifier::isDependent() const {
233 return getDependence() & NestedNameSpecifierDependence::Dependent;
234}
235
236bool NestedNameSpecifier::isInstantiationDependent() const {
237 return getDependence() & NestedNameSpecifierDependence::Instantiation;
238}
239
240bool NestedNameSpecifier::containsUnexpandedParameterPack() const {
241 return getDependence() & NestedNameSpecifierDependence::UnexpandedPack;
242}
243
244bool NestedNameSpecifier::containsErrors() const {
245 return getDependence() & NestedNameSpecifierDependence::Error;
246}
247
248const Type *
249NestedNameSpecifier::translateToType(const ASTContext &Context) const {
250 NestedNameSpecifier *Prefix = getPrefix();
251 switch (getKind()) {
252 case SpecifierKind::Identifier:
253 return Context
254 .getDependentNameType(Keyword: ElaboratedTypeKeyword::None, NNS: Prefix,
255 Name: getAsIdentifier())
256 .getTypePtr();
257 case SpecifierKind::TypeSpec: {
258 const Type *T = getAsType();
259 switch (T->getTypeClass()) {
260 case Type::DependentTemplateSpecialization: {
261 const auto *DT = cast<DependentTemplateSpecializationType>(Val: T);
262 const DependentTemplateStorage &DTN = DT->getDependentTemplateName();
263 return Context
264 .getDependentTemplateSpecializationType(
265 Keyword: ElaboratedTypeKeyword::None,
266 Name: {Prefix, DTN.getName(), DTN.hasTemplateKeyword()},
267 Args: DT->template_arguments())
268 .getTypePtr();
269 }
270 case Type::Record:
271 case Type::TemplateSpecialization:
272 case Type::Using:
273 case Type::Enum:
274 case Type::Typedef:
275 case Type::UnresolvedUsing:
276 return Context
277 .getElaboratedType(Keyword: ElaboratedTypeKeyword::None, NNS: Prefix,
278 NamedType: QualType(T, 0))
279 .getTypePtr();
280 default:
281 assert(Prefix == nullptr && "unexpected type with elaboration");
282 return T;
283 }
284 }
285 case SpecifierKind::Global:
286 case SpecifierKind::Namespace:
287 case SpecifierKind::NamespaceAlias:
288 case SpecifierKind::Super:
289 // These are not representable as types.
290 return nullptr;
291 }
292 llvm_unreachable("Unhandled SpecifierKind enum");
293}
294
295/// Print this nested name specifier to the given output
296/// stream.
297void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy,
298 bool ResolveTemplateArguments,
299 bool PrintFinalScopeResOp) const {
300 if (getPrefix())
301 getPrefix()->print(OS, Policy);
302
303 switch (getKind()) {
304 case Identifier:
305 OS << getAsIdentifier()->getName();
306 break;
307
308 case Namespace:
309 if (getAsNamespace()->isAnonymousNamespace())
310 return;
311
312 OS << getAsNamespace()->getName();
313 break;
314
315 case NamespaceAlias:
316 OS << getAsNamespaceAlias()->getName();
317 break;
318
319 case Global:
320 OS << "::";
321 return;
322
323 case Super:
324 OS << "__super";
325 break;
326
327 case TypeSpec: {
328 PrintingPolicy InnerPolicy(Policy);
329 InnerPolicy.SuppressScope = true;
330 InnerPolicy.SuppressTagKeyword = true;
331 QualType(getAsType(), 0).print(OS, Policy: InnerPolicy);
332 break;
333 }
334 }
335
336 if (PrintFinalScopeResOp)
337 OS << "::";
338}
339
340LLVM_DUMP_METHOD void NestedNameSpecifier::dump(const LangOptions &LO) const {
341 dump(OS&: llvm::errs(), LO);
342}
343
344LLVM_DUMP_METHOD void NestedNameSpecifier::dump() const { dump(OS&: llvm::errs()); }
345
346LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS) const {
347 LangOptions LO;
348 dump(OS, LO);
349}
350
351LLVM_DUMP_METHOD void NestedNameSpecifier::dump(llvm::raw_ostream &OS,
352 const LangOptions &LO) const {
353 print(OS, Policy: PrintingPolicy(LO));
354}
355
356unsigned
357NestedNameSpecifierLoc::getLocalDataLength(NestedNameSpecifier *Qualifier) {
358 assert(Qualifier && "Expected a non-NULL qualifier");
359
360 // Location of the trailing '::'.
361 unsigned Length = sizeof(SourceLocation::UIntTy);
362
363 switch (Qualifier->getKind()) {
364 case NestedNameSpecifier::Global:
365 // Nothing more to add.
366 break;
367
368 case NestedNameSpecifier::Identifier:
369 case NestedNameSpecifier::Namespace:
370 case NestedNameSpecifier::NamespaceAlias:
371 case NestedNameSpecifier::Super:
372 // The location of the identifier or namespace name.
373 Length += sizeof(SourceLocation::UIntTy);
374 break;
375
376 case NestedNameSpecifier::TypeSpec:
377 // The "void*" that points at the TypeLoc data.
378 // Note: the 'template' keyword is part of the TypeLoc.
379 Length += sizeof(void *);
380 break;
381 }
382
383 return Length;
384}
385
386unsigned
387NestedNameSpecifierLoc::getDataLength(NestedNameSpecifier *Qualifier) {
388 unsigned Length = 0;
389 for (; Qualifier; Qualifier = Qualifier->getPrefix())
390 Length += getLocalDataLength(Qualifier);
391 return Length;
392}
393
394/// Load a (possibly unaligned) source location from a given address
395/// and offset.
396static SourceLocation LoadSourceLocation(void *Data, unsigned Offset) {
397 SourceLocation::UIntTy Raw;
398 memcpy(dest: &Raw, src: static_cast<char *>(Data) + Offset, n: sizeof(Raw));
399 return SourceLocation::getFromRawEncoding(Encoding: Raw);
400}
401
402/// Load a (possibly unaligned) pointer from a given address and
403/// offset.
404static void *LoadPointer(void *Data, unsigned Offset) {
405 void *Result;
406 memcpy(dest: &Result, src: static_cast<char *>(Data) + Offset, n: sizeof(void*));
407 return Result;
408}
409
410SourceRange NestedNameSpecifierLoc::getLocalSourceRange() const {
411 if (!Qualifier)
412 return SourceRange();
413
414 unsigned Offset = getDataLength(Qualifier: Qualifier->getPrefix());
415 switch (Qualifier->getKind()) {
416 case NestedNameSpecifier::Global:
417 return LoadSourceLocation(Data, Offset);
418
419 case NestedNameSpecifier::Identifier:
420 case NestedNameSpecifier::Namespace:
421 case NestedNameSpecifier::NamespaceAlias:
422 case NestedNameSpecifier::Super:
423 return SourceRange(
424 LoadSourceLocation(Data, Offset),
425 LoadSourceLocation(Data, Offset: Offset + sizeof(SourceLocation::UIntTy)));
426
427 case NestedNameSpecifier::TypeSpec: {
428 // The "void*" that points at the TypeLoc data.
429 // Note: the 'template' keyword is part of the TypeLoc.
430 void *TypeData = LoadPointer(Data, Offset);
431 TypeLoc TL(Qualifier->getAsType(), TypeData);
432 return SourceRange(TL.getBeginLoc(),
433 LoadSourceLocation(Data, Offset: Offset + sizeof(void*)));
434 }
435 }
436
437 llvm_unreachable("Invalid NNS Kind!");
438}
439
440TypeLoc NestedNameSpecifierLoc::getTypeLoc() const {
441 if (Qualifier->getKind() != NestedNameSpecifier::TypeSpec)
442 return TypeLoc();
443
444 // The "void*" that points at the TypeLoc data.
445 unsigned Offset = getDataLength(Qualifier: Qualifier->getPrefix());
446 void *TypeData = LoadPointer(Data, Offset);
447 return TypeLoc(Qualifier->getAsType(), TypeData);
448}
449
450static void Append(char *Start, char *End, char *&Buffer, unsigned &BufferSize,
451 unsigned &BufferCapacity) {
452 if (Start == End)
453 return;
454
455 if (BufferSize + (End - Start) > BufferCapacity) {
456 // Reallocate the buffer.
457 unsigned NewCapacity = std::max(
458 a: (unsigned)(BufferCapacity ? BufferCapacity * 2 : sizeof(void *) * 2),
459 b: (unsigned)(BufferSize + (End - Start)));
460 if (!BufferCapacity) {
461 char *NewBuffer = static_cast<char *>(llvm::safe_malloc(Sz: NewCapacity));
462 if (Buffer)
463 memcpy(dest: NewBuffer, src: Buffer, n: BufferSize);
464 Buffer = NewBuffer;
465 } else {
466 Buffer = static_cast<char *>(llvm::safe_realloc(Ptr: Buffer, Sz: NewCapacity));
467 }
468 BufferCapacity = NewCapacity;
469 }
470 assert(Buffer && Start && End && End > Start && "Illegal memory buffer copy");
471 memcpy(dest: Buffer + BufferSize, src: Start, n: End - Start);
472 BufferSize += End - Start;
473}
474
475/// Save a source location to the given buffer.
476static void SaveSourceLocation(SourceLocation Loc, char *&Buffer,
477 unsigned &BufferSize, unsigned &BufferCapacity) {
478 SourceLocation::UIntTy Raw = Loc.getRawEncoding();
479 Append(Start: reinterpret_cast<char *>(&Raw),
480 End: reinterpret_cast<char *>(&Raw) + sizeof(Raw), Buffer, BufferSize,
481 BufferCapacity);
482}
483
484/// Save a pointer to the given buffer.
485static void SavePointer(void *Ptr, char *&Buffer, unsigned &BufferSize,
486 unsigned &BufferCapacity) {
487 Append(Start: reinterpret_cast<char *>(&Ptr),
488 End: reinterpret_cast<char *>(&Ptr) + sizeof(void *),
489 Buffer, BufferSize, BufferCapacity);
490}
491
492NestedNameSpecifierLocBuilder::
493NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other)
494 : Representation(Other.Representation) {
495 if (!Other.Buffer)
496 return;
497
498 if (Other.BufferCapacity == 0) {
499 // Shallow copy is okay.
500 Buffer = Other.Buffer;
501 BufferSize = Other.BufferSize;
502 return;
503 }
504
505 // Deep copy
506 Append(Start: Other.Buffer, End: Other.Buffer + Other.BufferSize, Buffer, BufferSize,
507 BufferCapacity);
508}
509
510NestedNameSpecifierLocBuilder &
511NestedNameSpecifierLocBuilder::
512operator=(const NestedNameSpecifierLocBuilder &Other) {
513 Representation = Other.Representation;
514
515 if (Buffer && Other.Buffer && BufferCapacity >= Other.BufferSize) {
516 // Re-use our storage.
517 BufferSize = Other.BufferSize;
518 memcpy(dest: Buffer, src: Other.Buffer, n: BufferSize);
519 return *this;
520 }
521
522 // Free our storage, if we have any.
523 if (BufferCapacity) {
524 free(ptr: Buffer);
525 BufferCapacity = 0;
526 }
527
528 if (!Other.Buffer) {
529 // Empty.
530 Buffer = nullptr;
531 BufferSize = 0;
532 return *this;
533 }
534
535 if (Other.BufferCapacity == 0) {
536 // Shallow copy is okay.
537 Buffer = Other.Buffer;
538 BufferSize = Other.BufferSize;
539 return *this;
540 }
541
542 // Deep copy.
543 BufferSize = 0;
544 Append(Start: Other.Buffer, End: Other.Buffer + Other.BufferSize, Buffer, BufferSize,
545 BufferCapacity);
546 return *this;
547}
548
549void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context, TypeLoc TL,
550 SourceLocation ColonColonLoc) {
551 Representation =
552 NestedNameSpecifier::Create(Context, Prefix: Representation, T: TL.getTypePtr());
553
554 // Push source-location info into the buffer.
555 SavePointer(Ptr: TL.getOpaqueData(), Buffer, BufferSize, BufferCapacity);
556 SaveSourceLocation(Loc: ColonColonLoc, Buffer, BufferSize, BufferCapacity);
557}
558
559void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
560 IdentifierInfo *Identifier,
561 SourceLocation IdentifierLoc,
562 SourceLocation ColonColonLoc) {
563 Representation = NestedNameSpecifier::Create(Context, Prefix: Representation,
564 II: Identifier);
565
566 // Push source-location info into the buffer.
567 SaveSourceLocation(Loc: IdentifierLoc, Buffer, BufferSize, BufferCapacity);
568 SaveSourceLocation(Loc: ColonColonLoc, Buffer, BufferSize, BufferCapacity);
569}
570
571void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
572 NamespaceDecl *Namespace,
573 SourceLocation NamespaceLoc,
574 SourceLocation ColonColonLoc) {
575 Representation = NestedNameSpecifier::Create(Context, Prefix: Representation,
576 NS: Namespace);
577
578 // Push source-location info into the buffer.
579 SaveSourceLocation(Loc: NamespaceLoc, Buffer, BufferSize, BufferCapacity);
580 SaveSourceLocation(Loc: ColonColonLoc, Buffer, BufferSize, BufferCapacity);
581}
582
583void NestedNameSpecifierLocBuilder::Extend(ASTContext &Context,
584 NamespaceAliasDecl *Alias,
585 SourceLocation AliasLoc,
586 SourceLocation ColonColonLoc) {
587 Representation = NestedNameSpecifier::Create(Context, Prefix: Representation, Alias);
588
589 // Push source-location info into the buffer.
590 SaveSourceLocation(Loc: AliasLoc, Buffer, BufferSize, BufferCapacity);
591 SaveSourceLocation(Loc: ColonColonLoc, Buffer, BufferSize, BufferCapacity);
592}
593
594void NestedNameSpecifierLocBuilder::MakeGlobal(ASTContext &Context,
595 SourceLocation ColonColonLoc) {
596 assert(!Representation && "Already have a nested-name-specifier!?");
597 Representation = NestedNameSpecifier::GlobalSpecifier(Context);
598
599 // Push source-location info into the buffer.
600 SaveSourceLocation(Loc: ColonColonLoc, Buffer, BufferSize, BufferCapacity);
601}
602
603void NestedNameSpecifierLocBuilder::MakeSuper(ASTContext &Context,
604 CXXRecordDecl *RD,
605 SourceLocation SuperLoc,
606 SourceLocation ColonColonLoc) {
607 Representation = NestedNameSpecifier::SuperSpecifier(Context, RD);
608
609 // Push source-location info into the buffer.
610 SaveSourceLocation(Loc: SuperLoc, Buffer, BufferSize, BufferCapacity);
611 SaveSourceLocation(Loc: ColonColonLoc, Buffer, BufferSize, BufferCapacity);
612}
613
614void NestedNameSpecifierLocBuilder::MakeTrivial(ASTContext &Context,
615 NestedNameSpecifier *Qualifier,
616 SourceRange R) {
617 Representation = Qualifier;
618
619 // Construct bogus (but well-formed) source information for the
620 // nested-name-specifier.
621 BufferSize = 0;
622 SmallVector<NestedNameSpecifier *, 4> Stack;
623 for (NestedNameSpecifier *NNS = Qualifier; NNS; NNS = NNS->getPrefix())
624 Stack.push_back(Elt: NNS);
625 while (!Stack.empty()) {
626 NestedNameSpecifier *NNS = Stack.pop_back_val();
627 switch (NNS->getKind()) {
628 case NestedNameSpecifier::Identifier:
629 case NestedNameSpecifier::Namespace:
630 case NestedNameSpecifier::NamespaceAlias:
631 SaveSourceLocation(Loc: R.getBegin(), Buffer, BufferSize, BufferCapacity);
632 break;
633
634 case NestedNameSpecifier::TypeSpec: {
635 TypeSourceInfo *TSInfo
636 = Context.getTrivialTypeSourceInfo(T: QualType(NNS->getAsType(), 0),
637 Loc: R.getBegin());
638 SavePointer(Ptr: TSInfo->getTypeLoc().getOpaqueData(), Buffer, BufferSize,
639 BufferCapacity);
640 break;
641 }
642
643 case NestedNameSpecifier::Global:
644 case NestedNameSpecifier::Super:
645 break;
646 }
647
648 // Save the location of the '::'.
649 SaveSourceLocation(Loc: Stack.empty()? R.getEnd() : R.getBegin(),
650 Buffer, BufferSize, BufferCapacity);
651 }
652}
653
654void NestedNameSpecifierLocBuilder::Adopt(NestedNameSpecifierLoc Other) {
655 if (BufferCapacity)
656 free(ptr: Buffer);
657
658 if (!Other) {
659 Representation = nullptr;
660 BufferSize = 0;
661 return;
662 }
663
664 // Rather than copying the data (which is wasteful), "adopt" the
665 // pointer (which points into the ASTContext) but set the capacity to zero to
666 // indicate that we don't own it.
667 Representation = Other.getNestedNameSpecifier();
668 Buffer = static_cast<char *>(Other.getOpaqueData());
669 BufferSize = Other.getDataLength();
670 BufferCapacity = 0;
671}
672
673NestedNameSpecifierLoc
674NestedNameSpecifierLocBuilder::getWithLocInContext(ASTContext &Context) const {
675 if (!Representation)
676 return NestedNameSpecifierLoc();
677
678 // If we adopted our data pointer from elsewhere in the AST context, there's
679 // no need to copy the memory.
680 if (BufferCapacity == 0)
681 return NestedNameSpecifierLoc(Representation, Buffer);
682
683 // FIXME: After copying the source-location information, should we free
684 // our (temporary) buffer and adopt the ASTContext-allocated memory?
685 // Doing so would optimize repeated calls to getWithLocInContext().
686 void *Mem = Context.Allocate(Size: BufferSize, Align: alignof(void *));
687 memcpy(dest: Mem, src: Buffer, n: BufferSize);
688 return NestedNameSpecifierLoc(Representation, Mem);
689}
690

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of clang/lib/AST/NestedNameSpecifier.cpp