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