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