File: | clang/lib/AST/NestedNameSpecifier.cpp |
Warning: | line 493, column 3 Null pointer passed to 1st parameter expecting 'nonnull' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===- NestedNameSpecifier.h - C++ nested name specifiers -------*- C++ -*-===// | |||
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 | #ifndef LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H | |||
15 | #define LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H | |||
16 | ||||
17 | #include "clang/Basic/Diagnostic.h" | |||
18 | #include "clang/Basic/SourceLocation.h" | |||
19 | #include "llvm/ADT/FoldingSet.h" | |||
20 | #include "llvm/ADT/PointerIntPair.h" | |||
21 | #include "llvm/Support/Compiler.h" | |||
22 | #include <cstdint> | |||
23 | #include <cstdlib> | |||
24 | #include <utility> | |||
25 | ||||
26 | namespace clang { | |||
27 | ||||
28 | class ASTContext; | |||
29 | class CXXRecordDecl; | |||
30 | class IdentifierInfo; | |||
31 | class LangOptions; | |||
32 | class NamespaceAliasDecl; | |||
33 | class NamespaceDecl; | |||
34 | struct PrintingPolicy; | |||
35 | class Type; | |||
36 | class TypeLoc; | |||
37 | ||||
38 | /// Represents a C++ nested name specifier, such as | |||
39 | /// "\::std::vector<int>::". | |||
40 | /// | |||
41 | /// C++ nested name specifiers are the prefixes to qualified | |||
42 | /// names. For example, "foo::" in "foo::x" is a nested name | |||
43 | /// specifier. Nested name specifiers are made up of a sequence of | |||
44 | /// specifiers, each of which can be a namespace, type, identifier | |||
45 | /// (for dependent names), decltype specifier, or the global specifier ('::'). | |||
46 | /// The last two specifiers can only appear at the start of a | |||
47 | /// nested-namespace-specifier. | |||
48 | class NestedNameSpecifier : public llvm::FoldingSetNode { | |||
49 | /// Enumeration describing | |||
50 | enum StoredSpecifierKind { | |||
51 | StoredIdentifier = 0, | |||
52 | StoredDecl = 1, | |||
53 | StoredTypeSpec = 2, | |||
54 | StoredTypeSpecWithTemplate = 3 | |||
55 | }; | |||
56 | ||||
57 | /// The nested name specifier that precedes this nested name | |||
58 | /// specifier. | |||
59 | /// | |||
60 | /// The pointer is the nested-name-specifier that precedes this | |||
61 | /// one. The integer stores one of the first four values of type | |||
62 | /// SpecifierKind. | |||
63 | llvm::PointerIntPair<NestedNameSpecifier *, 2, StoredSpecifierKind> Prefix; | |||
64 | ||||
65 | /// The last component in the nested name specifier, which | |||
66 | /// can be an identifier, a declaration, or a type. | |||
67 | /// | |||
68 | /// When the pointer is NULL, this specifier represents the global | |||
69 | /// specifier '::'. Otherwise, the pointer is one of | |||
70 | /// IdentifierInfo*, Namespace*, or Type*, depending on the kind of | |||
71 | /// specifier as encoded within the prefix. | |||
72 | void* Specifier = nullptr; | |||
73 | ||||
74 | public: | |||
75 | /// The kind of specifier that completes this nested name | |||
76 | /// specifier. | |||
77 | enum SpecifierKind { | |||
78 | /// An identifier, stored as an IdentifierInfo*. | |||
79 | Identifier, | |||
80 | ||||
81 | /// A namespace, stored as a NamespaceDecl*. | |||
82 | Namespace, | |||
83 | ||||
84 | /// A namespace alias, stored as a NamespaceAliasDecl*. | |||
85 | NamespaceAlias, | |||
86 | ||||
87 | /// A type, stored as a Type*. | |||
88 | TypeSpec, | |||
89 | ||||
90 | /// A type that was preceded by the 'template' keyword, | |||
91 | /// stored as a Type*. | |||
92 | TypeSpecWithTemplate, | |||
93 | ||||
94 | /// The global specifier '::'. There is no stored value. | |||
95 | Global, | |||
96 | ||||
97 | /// Microsoft's '__super' specifier, stored as a CXXRecordDecl* of | |||
98 | /// the class it appeared in. | |||
99 | Super | |||
100 | }; | |||
101 | ||||
102 | private: | |||
103 | /// Builds the global specifier. | |||
104 | NestedNameSpecifier() : Prefix(nullptr, StoredIdentifier) {} | |||
105 | ||||
106 | /// Copy constructor used internally to clone nested name | |||
107 | /// specifiers. | |||
108 | NestedNameSpecifier(const NestedNameSpecifier &Other) = default; | |||
109 | ||||
110 | /// Either find or insert the given nested name specifier | |||
111 | /// mockup in the given context. | |||
112 | static NestedNameSpecifier *FindOrInsert(const ASTContext &Context, | |||
113 | const NestedNameSpecifier &Mockup); | |||
114 | ||||
115 | public: | |||
116 | NestedNameSpecifier &operator=(const NestedNameSpecifier &) = delete; | |||
117 | ||||
118 | /// Builds a specifier combining a prefix and an identifier. | |||
119 | /// | |||
120 | /// The prefix must be dependent, since nested name specifiers | |||
121 | /// referencing an identifier are only permitted when the identifier | |||
122 | /// cannot be resolved. | |||
123 | static NestedNameSpecifier *Create(const ASTContext &Context, | |||
124 | NestedNameSpecifier *Prefix, | |||
125 | IdentifierInfo *II); | |||
126 | ||||
127 | /// Builds a nested name specifier that names a namespace. | |||
128 | static NestedNameSpecifier *Create(const ASTContext &Context, | |||
129 | NestedNameSpecifier *Prefix, | |||
130 | const NamespaceDecl *NS); | |||
131 | ||||
132 | /// Builds a nested name specifier that names a namespace alias. | |||
133 | static NestedNameSpecifier *Create(const ASTContext &Context, | |||
134 | NestedNameSpecifier *Prefix, | |||
135 | NamespaceAliasDecl *Alias); | |||
136 | ||||
137 | /// Builds a nested name specifier that names a type. | |||
138 | static NestedNameSpecifier *Create(const ASTContext &Context, | |||
139 | NestedNameSpecifier *Prefix, | |||
140 | bool Template, const Type *T); | |||
141 | ||||
142 | /// Builds a specifier that consists of just an identifier. | |||
143 | /// | |||
144 | /// The nested-name-specifier is assumed to be dependent, but has no | |||
145 | /// prefix because the prefix is implied by something outside of the | |||
146 | /// nested name specifier, e.g., in "x->Base::f", the "x" has a dependent | |||
147 | /// type. | |||
148 | static NestedNameSpecifier *Create(const ASTContext &Context, | |||
149 | IdentifierInfo *II); | |||
150 | ||||
151 | /// Returns the nested name specifier representing the global | |||
152 | /// scope. | |||
153 | static NestedNameSpecifier *GlobalSpecifier(const ASTContext &Context); | |||
154 | ||||
155 | /// Returns the nested name specifier representing the __super scope | |||
156 | /// for the given CXXRecordDecl. | |||
157 | static NestedNameSpecifier *SuperSpecifier(const ASTContext &Context, | |||
158 | CXXRecordDecl *RD); | |||
159 | ||||
160 | /// Return the prefix of this nested name specifier. | |||
161 | /// | |||
162 | /// The prefix contains all of the parts of the nested name | |||
163 | /// specifier that preced this current specifier. For example, for a | |||
164 | /// nested name specifier that represents "foo::bar::", the current | |||
165 | /// specifier will contain "bar::" and the prefix will contain | |||
166 | /// "foo::". | |||
167 | NestedNameSpecifier *getPrefix() const { return Prefix.getPointer(); } | |||
168 | ||||
169 | /// Determine what kind of nested name specifier is stored. | |||
170 | SpecifierKind getKind() const; | |||
171 | ||||
172 | /// Retrieve the identifier stored in this nested name | |||
173 | /// specifier. | |||
174 | IdentifierInfo *getAsIdentifier() const { | |||
175 | if (Prefix.getInt() == StoredIdentifier) | |||
176 | return (IdentifierInfo *)Specifier; | |||
177 | ||||
178 | return nullptr; | |||
179 | } | |||
180 | ||||
181 | /// Retrieve the namespace stored in this nested name | |||
182 | /// specifier. | |||
183 | NamespaceDecl *getAsNamespace() const; | |||
184 | ||||
185 | /// Retrieve the namespace alias stored in this nested name | |||
186 | /// specifier. | |||
187 | NamespaceAliasDecl *getAsNamespaceAlias() const; | |||
188 | ||||
189 | /// Retrieve the record declaration stored in this nested name | |||
190 | /// specifier. | |||
191 | CXXRecordDecl *getAsRecordDecl() const; | |||
192 | ||||
193 | /// Retrieve the type stored in this nested name specifier. | |||
194 | const Type *getAsType() const { | |||
195 | if (Prefix.getInt() == StoredTypeSpec || | |||
196 | Prefix.getInt() == StoredTypeSpecWithTemplate) | |||
197 | return (const Type *)Specifier; | |||
198 | ||||
199 | return nullptr; | |||
200 | } | |||
201 | ||||
202 | /// Whether this nested name specifier refers to a dependent | |||
203 | /// type or not. | |||
204 | bool isDependent() const; | |||
205 | ||||
206 | /// Whether this nested name specifier involves a template | |||
207 | /// parameter. | |||
208 | bool isInstantiationDependent() const; | |||
209 | ||||
210 | /// Whether this nested-name-specifier contains an unexpanded | |||
211 | /// parameter pack (for C++11 variadic templates). | |||
212 | bool containsUnexpandedParameterPack() const; | |||
213 | ||||
214 | /// Print this nested name specifier to the given output stream. If | |||
215 | /// `ResolveTemplateArguments` is true, we'll print actual types, e.g. | |||
216 | /// `ns::SomeTemplate<int, MyClass>` instead of | |||
217 | /// `ns::SomeTemplate<Container::value_type, T>`. | |||
218 | void print(raw_ostream &OS, const PrintingPolicy &Policy, | |||
219 | bool ResolveTemplateArguments = false) const; | |||
220 | ||||
221 | void Profile(llvm::FoldingSetNodeID &ID) const { | |||
222 | ID.AddPointer(Prefix.getOpaqueValue()); | |||
223 | ID.AddPointer(Specifier); | |||
224 | } | |||
225 | ||||
226 | /// Dump the nested name specifier to standard output to aid | |||
227 | /// in debugging. | |||
228 | void dump(const LangOptions &LO) const; | |||
229 | void dump() const; | |||
230 | void dump(llvm::raw_ostream &OS) const; | |||
231 | void dump(llvm::raw_ostream &OS, const LangOptions &LO) const; | |||
232 | }; | |||
233 | ||||
234 | /// A C++ nested-name-specifier augmented with source location | |||
235 | /// information. | |||
236 | class NestedNameSpecifierLoc { | |||
237 | NestedNameSpecifier *Qualifier = nullptr; | |||
238 | void *Data = nullptr; | |||
239 | ||||
240 | /// Determines the data length for the last component in the | |||
241 | /// given nested-name-specifier. | |||
242 | static unsigned getLocalDataLength(NestedNameSpecifier *Qualifier); | |||
243 | ||||
244 | /// Determines the data length for the entire | |||
245 | /// nested-name-specifier. | |||
246 | static unsigned getDataLength(NestedNameSpecifier *Qualifier); | |||
247 | ||||
248 | public: | |||
249 | /// Construct an empty nested-name-specifier. | |||
250 | NestedNameSpecifierLoc() = default; | |||
251 | ||||
252 | /// Construct a nested-name-specifier with source location information | |||
253 | /// from | |||
254 | NestedNameSpecifierLoc(NestedNameSpecifier *Qualifier, void *Data) | |||
255 | : Qualifier(Qualifier), Data(Data) {} | |||
256 | ||||
257 | /// Evaluates true when this nested-name-specifier location is | |||
258 | /// non-empty. | |||
259 | explicit operator bool() const { return Qualifier; } | |||
260 | ||||
261 | /// Evaluates true when this nested-name-specifier location is | |||
262 | /// empty. | |||
263 | bool hasQualifier() const { return Qualifier; } | |||
264 | ||||
265 | /// Retrieve the nested-name-specifier to which this instance | |||
266 | /// refers. | |||
267 | NestedNameSpecifier *getNestedNameSpecifier() const { | |||
268 | return Qualifier; | |||
269 | } | |||
270 | ||||
271 | /// Retrieve the opaque pointer that refers to source-location data. | |||
272 | void *getOpaqueData() const { return Data; } | |||
273 | ||||
274 | /// Retrieve the source range covering the entirety of this | |||
275 | /// nested-name-specifier. | |||
276 | /// | |||
277 | /// For example, if this instance refers to a nested-name-specifier | |||
278 | /// \c \::std::vector<int>::, the returned source range would cover | |||
279 | /// from the initial '::' to the last '::'. | |||
280 | SourceRange getSourceRange() const LLVM_READONLY__attribute__((__pure__)); | |||
281 | ||||
282 | /// Retrieve the source range covering just the last part of | |||
283 | /// this nested-name-specifier, not including the prefix. | |||
284 | /// | |||
285 | /// For example, if this instance refers to a nested-name-specifier | |||
286 | /// \c \::std::vector<int>::, the returned source range would cover | |||
287 | /// from "vector" to the last '::'. | |||
288 | SourceRange getLocalSourceRange() const; | |||
289 | ||||
290 | /// Retrieve the location of the beginning of this | |||
291 | /// nested-name-specifier. | |||
292 | SourceLocation getBeginLoc() const { | |||
293 | return getSourceRange().getBegin(); | |||
294 | } | |||
295 | ||||
296 | /// Retrieve the location of the end of this | |||
297 | /// nested-name-specifier. | |||
298 | SourceLocation getEndLoc() const { | |||
299 | return getSourceRange().getEnd(); | |||
300 | } | |||
301 | ||||
302 | /// Retrieve the location of the beginning of this | |||
303 | /// component of the nested-name-specifier. | |||
304 | SourceLocation getLocalBeginLoc() const { | |||
305 | return getLocalSourceRange().getBegin(); | |||
306 | } | |||
307 | ||||
308 | /// Retrieve the location of the end of this component of the | |||
309 | /// nested-name-specifier. | |||
310 | SourceLocation getLocalEndLoc() const { | |||
311 | return getLocalSourceRange().getEnd(); | |||
312 | } | |||
313 | ||||
314 | /// Return the prefix of this nested-name-specifier. | |||
315 | /// | |||
316 | /// For example, if this instance refers to a nested-name-specifier | |||
317 | /// \c \::std::vector<int>::, the prefix is \c \::std::. Note that the | |||
318 | /// returned prefix may be empty, if this is the first component of | |||
319 | /// the nested-name-specifier. | |||
320 | NestedNameSpecifierLoc getPrefix() const { | |||
321 | if (!Qualifier) | |||
322 | return *this; | |||
323 | ||||
324 | return NestedNameSpecifierLoc(Qualifier->getPrefix(), Data); | |||
325 | } | |||
326 | ||||
327 | /// For a nested-name-specifier that refers to a type, | |||
328 | /// retrieve the type with source-location information. | |||
329 | TypeLoc getTypeLoc() const; | |||
330 | ||||
331 | /// Determines the data length for the entire | |||
332 | /// nested-name-specifier. | |||
333 | unsigned getDataLength() const { return getDataLength(Qualifier); } | |||
334 | ||||
335 | friend bool operator==(NestedNameSpecifierLoc X, | |||
336 | NestedNameSpecifierLoc Y) { | |||
337 | return X.Qualifier == Y.Qualifier && X.Data == Y.Data; | |||
338 | } | |||
339 | ||||
340 | friend bool operator!=(NestedNameSpecifierLoc X, | |||
341 | NestedNameSpecifierLoc Y) { | |||
342 | return !(X == Y); | |||
343 | } | |||
344 | }; | |||
345 | ||||
346 | /// Class that aids in the construction of nested-name-specifiers along | |||
347 | /// with source-location information for all of the components of the | |||
348 | /// nested-name-specifier. | |||
349 | class NestedNameSpecifierLocBuilder { | |||
350 | /// The current representation of the nested-name-specifier we're | |||
351 | /// building. | |||
352 | NestedNameSpecifier *Representation = nullptr; | |||
353 | ||||
354 | /// Buffer used to store source-location information for the | |||
355 | /// nested-name-specifier. | |||
356 | /// | |||
357 | /// Note that we explicitly manage the buffer (rather than using a | |||
358 | /// SmallVector) because \c Declarator expects it to be possible to memcpy() | |||
359 | /// a \c CXXScopeSpec, and CXXScopeSpec uses a NestedNameSpecifierLocBuilder. | |||
360 | char *Buffer = nullptr; | |||
| ||||
361 | ||||
362 | /// The size of the buffer used to store source-location information | |||
363 | /// for the nested-name-specifier. | |||
364 | unsigned BufferSize = 0; | |||
365 | ||||
366 | /// The capacity of the buffer used to store source-location | |||
367 | /// information for the nested-name-specifier. | |||
368 | unsigned BufferCapacity = 0; | |||
369 | ||||
370 | public: | |||
371 | NestedNameSpecifierLocBuilder() = default; | |||
372 | NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other); | |||
373 | ||||
374 | NestedNameSpecifierLocBuilder & | |||
375 | operator=(const NestedNameSpecifierLocBuilder &Other); | |||
376 | ||||
377 | ~NestedNameSpecifierLocBuilder() { | |||
378 | if (BufferCapacity) | |||
379 | free(Buffer); | |||
380 | } | |||
381 | ||||
382 | /// Retrieve the representation of the nested-name-specifier. | |||
383 | NestedNameSpecifier *getRepresentation() const { return Representation; } | |||
384 | ||||
385 | /// Extend the current nested-name-specifier by another | |||
386 | /// nested-name-specifier component of the form 'type::'. | |||
387 | /// | |||
388 | /// \param Context The AST context in which this nested-name-specifier | |||
389 | /// resides. | |||
390 | /// | |||
391 | /// \param TemplateKWLoc The location of the 'template' keyword, if present. | |||
392 | /// | |||
393 | /// \param TL The TypeLoc that describes the type preceding the '::'. | |||
394 | /// | |||
395 | /// \param ColonColonLoc The location of the trailing '::'. | |||
396 | void Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL, | |||
397 | SourceLocation ColonColonLoc); | |||
398 | ||||
399 | /// Extend the current nested-name-specifier by another | |||
400 | /// nested-name-specifier component of the form 'identifier::'. | |||
401 | /// | |||
402 | /// \param Context The AST context in which this nested-name-specifier | |||
403 | /// resides. | |||
404 | /// | |||
405 | /// \param Identifier The identifier. | |||
406 | /// | |||
407 | /// \param IdentifierLoc The location of the identifier. | |||
408 | /// | |||
409 | /// \param ColonColonLoc The location of the trailing '::'. | |||
410 | void Extend(ASTContext &Context, IdentifierInfo *Identifier, | |||
411 | SourceLocation IdentifierLoc, SourceLocation ColonColonLoc); | |||
412 | ||||
413 | /// Extend the current nested-name-specifier by another | |||
414 | /// nested-name-specifier component of the form 'namespace::'. | |||
415 | /// | |||
416 | /// \param Context The AST context in which this nested-name-specifier | |||
417 | /// resides. | |||
418 | /// | |||
419 | /// \param Namespace The namespace. | |||
420 | /// | |||
421 | /// \param NamespaceLoc The location of the namespace name. | |||
422 | /// | |||
423 | /// \param ColonColonLoc The location of the trailing '::'. | |||
424 | void Extend(ASTContext &Context, NamespaceDecl *Namespace, | |||
425 | SourceLocation NamespaceLoc, SourceLocation ColonColonLoc); | |||
426 | ||||
427 | /// Extend the current nested-name-specifier by another | |||
428 | /// nested-name-specifier component of the form 'namespace-alias::'. | |||
429 | /// | |||
430 | /// \param Context The AST context in which this nested-name-specifier | |||
431 | /// resides. | |||
432 | /// | |||
433 | /// \param Alias The namespace alias. | |||
434 | /// | |||
435 | /// \param AliasLoc The location of the namespace alias | |||
436 | /// name. | |||
437 | /// | |||
438 | /// \param ColonColonLoc The location of the trailing '::'. | |||
439 | void Extend(ASTContext &Context, NamespaceAliasDecl *Alias, | |||
440 | SourceLocation AliasLoc, SourceLocation ColonColonLoc); | |||
441 | ||||
442 | /// Turn this (empty) nested-name-specifier into the global | |||
443 | /// nested-name-specifier '::'. | |||
444 | void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc); | |||
445 | ||||
446 | /// Turns this (empty) nested-name-specifier into '__super' | |||
447 | /// nested-name-specifier. | |||
448 | /// | |||
449 | /// \param Context The AST context in which this nested-name-specifier | |||
450 | /// resides. | |||
451 | /// | |||
452 | /// \param RD The declaration of the class in which nested-name-specifier | |||
453 | /// appeared. | |||
454 | /// | |||
455 | /// \param SuperLoc The location of the '__super' keyword. | |||
456 | /// name. | |||
457 | /// | |||
458 | /// \param ColonColonLoc The location of the trailing '::'. | |||
459 | void MakeSuper(ASTContext &Context, CXXRecordDecl *RD, | |||
460 | SourceLocation SuperLoc, SourceLocation ColonColonLoc); | |||
461 | ||||
462 | /// Make a new nested-name-specifier from incomplete source-location | |||
463 | /// information. | |||
464 | /// | |||
465 | /// This routine should be used very, very rarely, in cases where we | |||
466 | /// need to synthesize a nested-name-specifier. Most code should instead use | |||
467 | /// \c Adopt() with a proper \c NestedNameSpecifierLoc. | |||
468 | void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier, | |||
469 | SourceRange R); | |||
470 | ||||
471 | /// Adopt an existing nested-name-specifier (with source-range | |||
472 | /// information). | |||
473 | void Adopt(NestedNameSpecifierLoc Other); | |||
474 | ||||
475 | /// Retrieve the source range covered by this nested-name-specifier. | |||
476 | SourceRange getSourceRange() const LLVM_READONLY__attribute__((__pure__)) { | |||
477 | return NestedNameSpecifierLoc(Representation, Buffer).getSourceRange(); | |||
478 | } | |||
479 | ||||
480 | /// Retrieve a nested-name-specifier with location information, | |||
481 | /// copied into the given AST context. | |||
482 | /// | |||
483 | /// \param Context The context into which this nested-name-specifier will be | |||
484 | /// copied. | |||
485 | NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const; | |||
486 | ||||
487 | /// Retrieve a nested-name-specifier with location | |||
488 | /// information based on the information in this builder. | |||
489 | /// | |||
490 | /// This loc will contain references to the builder's internal data and may | |||
491 | /// be invalidated by any change to the builder. | |||
492 | NestedNameSpecifierLoc getTemporary() const { | |||
493 | return NestedNameSpecifierLoc(Representation, Buffer); | |||
494 | } | |||
495 | ||||
496 | /// Clear out this builder, and prepare it to build another | |||
497 | /// nested-name-specifier with source-location information. | |||
498 | void Clear() { | |||
499 | Representation = nullptr; | |||
500 | BufferSize = 0; | |||
501 | } | |||
502 | ||||
503 | /// Retrieve the underlying buffer. | |||
504 | /// | |||
505 | /// \returns A pair containing a pointer to the buffer of source-location | |||
506 | /// data and the size of the source-location data that resides in that | |||
507 | /// buffer. | |||
508 | std::pair<char *, unsigned> getBuffer() const { | |||
509 | return std::make_pair(Buffer, BufferSize); | |||
510 | } | |||
511 | }; | |||
512 | ||||
513 | /// Insertion operator for diagnostics. This allows sending | |||
514 | /// NestedNameSpecifiers into a diagnostic with <<. | |||
515 | inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, | |||
516 | NestedNameSpecifier *NNS) { | |||
517 | DB.AddTaggedVal(reinterpret_cast<intptr_t>(NNS), | |||
518 | DiagnosticsEngine::ak_nestednamespec); | |||
519 | return DB; | |||
520 | } | |||
521 | ||||
522 | } // namespace clang | |||
523 | ||||
524 | #endif // LLVM_CLANG_AST_NESTEDNAMESPECIFIER_H |
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 | } |