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