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