1//===- ExternalASTSource.h - Abstract External AST Interface ----*- 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 ExternalASTSource interface, which enables
10// construction of AST nodes from some external source.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_AST_EXTERNALASTSOURCE_H
15#define LLVM_CLANG_AST_EXTERNALASTSOURCE_H
16
17#include "clang/AST/CharUnits.h"
18#include "clang/AST/DeclBase.h"
19#include "clang/Basic/LLVM.h"
20#include "llvm/ADT/ArrayRef.h"
21#include "llvm/ADT/DenseMap.h"
22#include "llvm/ADT/IntrusiveRefCntPtr.h"
23#include "llvm/ADT/PointerUnion.h"
24#include "llvm/ADT/STLExtras.h"
25#include "llvm/ADT/SmallVector.h"
26#include "llvm/ADT/iterator.h"
27#include "llvm/Support/PointerLikeTypeTraits.h"
28#include <cassert>
29#include <cstddef>
30#include <cstdint>
31#include <iterator>
32#include <optional>
33#include <utility>
34
35namespace clang {
36
37class ASTConsumer;
38class ASTContext;
39class ASTSourceDescriptor;
40class CXXBaseSpecifier;
41class CXXCtorInitializer;
42class CXXRecordDecl;
43class DeclarationName;
44class FieldDecl;
45class IdentifierInfo;
46class NamedDecl;
47class ObjCInterfaceDecl;
48class RecordDecl;
49class Selector;
50class Stmt;
51class TagDecl;
52
53/// Abstract interface for external sources of AST nodes.
54///
55/// External AST sources provide AST nodes constructed from some
56/// external source, such as a precompiled header. External AST
57/// sources can resolve types and declarations from abstract IDs into
58/// actual type and declaration nodes, and read parts of declaration
59/// contexts.
60class ExternalASTSource : public RefCountedBase<ExternalASTSource> {
61 friend class ExternalSemaSource;
62
63 /// Generation number for this external AST source. Must be increased
64 /// whenever we might have added new redeclarations for existing decls.
65 uint32_t CurrentGeneration = 0;
66
67 /// LLVM-style RTTI.
68 static char ID;
69
70public:
71 ExternalASTSource() = default;
72 virtual ~ExternalASTSource();
73
74 /// RAII class for safely pairing a StartedDeserializing call
75 /// with FinishedDeserializing.
76 class Deserializing {
77 ExternalASTSource *Source;
78
79 public:
80 explicit Deserializing(ExternalASTSource *source) : Source(source) {
81 assert(Source);
82 Source->StartedDeserializing();
83 }
84
85 ~Deserializing() {
86 Source->FinishedDeserializing();
87 }
88 };
89
90 /// Get the current generation of this AST source. This number
91 /// is incremented each time the AST source lazily extends an existing
92 /// entity.
93 uint32_t getGeneration() const { return CurrentGeneration; }
94
95 /// Resolve a declaration ID into a declaration, potentially
96 /// building a new declaration.
97 ///
98 /// This method only needs to be implemented if the AST source ever
99 /// passes back decl sets as VisibleDeclaration objects.
100 ///
101 /// The default implementation of this method is a no-op.
102 virtual Decl *GetExternalDecl(uint32_t ID);
103
104 /// Resolve a selector ID into a selector.
105 ///
106 /// This operation only needs to be implemented if the AST source
107 /// returns non-zero for GetNumKnownSelectors().
108 ///
109 /// The default implementation of this method is a no-op.
110 virtual Selector GetExternalSelector(uint32_t ID);
111
112 /// Returns the number of selectors known to the external AST
113 /// source.
114 ///
115 /// The default implementation of this method is a no-op.
116 virtual uint32_t GetNumExternalSelectors();
117
118 /// Resolve the offset of a statement in the decl stream into
119 /// a statement.
120 ///
121 /// This operation is meant to be used via a LazyOffsetPtr. It only
122 /// needs to be implemented if the AST source uses methods like
123 /// FunctionDecl::setLazyBody when building decls.
124 ///
125 /// The default implementation of this method is a no-op.
126 virtual Stmt *GetExternalDeclStmt(uint64_t Offset);
127
128 /// Resolve the offset of a set of C++ constructor initializers in
129 /// the decl stream into an array of initializers.
130 ///
131 /// The default implementation of this method is a no-op.
132 virtual CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset);
133
134 /// Resolve the offset of a set of C++ base specifiers in the decl
135 /// stream into an array of specifiers.
136 ///
137 /// The default implementation of this method is a no-op.
138 virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset);
139
140 /// Update an out-of-date identifier.
141 virtual void updateOutOfDateIdentifier(IdentifierInfo &II) {}
142
143 /// Find all declarations with the given name in the given context,
144 /// and add them to the context by calling SetExternalVisibleDeclsForName
145 /// or SetNoExternalVisibleDeclsForName.
146 /// \return \c true if any declarations might have been found, \c false if
147 /// we definitely have no declarations with tbis name.
148 ///
149 /// The default implementation of this method is a no-op returning \c false.
150 virtual bool
151 FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name);
152
153 /// Ensures that the table of all visible declarations inside this
154 /// context is up to date.
155 ///
156 /// The default implementation of this function is a no-op.
157 virtual void completeVisibleDeclsMap(const DeclContext *DC);
158
159 /// Retrieve the module that corresponds to the given module ID.
160 virtual Module *getModule(unsigned ID) { return nullptr; }
161
162 /// Return a descriptor for the corresponding module, if one exists.
163 virtual std::optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID);
164
165 enum ExtKind { EK_Always, EK_Never, EK_ReplyHazy };
166
167 virtual ExtKind hasExternalDefinitions(const Decl *D);
168
169 /// Finds all declarations lexically contained within the given
170 /// DeclContext, after applying an optional filter predicate.
171 ///
172 /// \param IsKindWeWant a predicate function that returns true if the passed
173 /// declaration kind is one we are looking for.
174 ///
175 /// The default implementation of this method is a no-op.
176 virtual void
177 FindExternalLexicalDecls(const DeclContext *DC,
178 llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
179 SmallVectorImpl<Decl *> &Result);
180
181 /// Finds all declarations lexically contained within the given
182 /// DeclContext.
183 void FindExternalLexicalDecls(const DeclContext *DC,
184 SmallVectorImpl<Decl *> &Result) {
185 FindExternalLexicalDecls(DC, IsKindWeWant: [](Decl::Kind) { return true; }, Result);
186 }
187
188 /// Get the decls that are contained in a file in the Offset/Length
189 /// range. \p Length can be 0 to indicate a point at \p Offset instead of
190 /// a range.
191 virtual void FindFileRegionDecls(FileID File, unsigned Offset,
192 unsigned Length,
193 SmallVectorImpl<Decl *> &Decls);
194
195 /// Gives the external AST source an opportunity to complete
196 /// the redeclaration chain for a declaration. Called each time we
197 /// need the most recent declaration of a declaration after the
198 /// generation count is incremented.
199 virtual void CompleteRedeclChain(const Decl *D);
200
201 /// Gives the external AST source an opportunity to complete
202 /// an incomplete type.
203 virtual void CompleteType(TagDecl *Tag);
204
205 /// Gives the external AST source an opportunity to complete an
206 /// incomplete Objective-C class.
207 ///
208 /// This routine will only be invoked if the "externally completed" bit is
209 /// set on the ObjCInterfaceDecl via the function
210 /// \c ObjCInterfaceDecl::setExternallyCompleted().
211 virtual void CompleteType(ObjCInterfaceDecl *Class);
212
213 /// Loads comment ranges.
214 virtual void ReadComments();
215
216 /// Notify ExternalASTSource that we started deserialization of
217 /// a decl or type so until FinishedDeserializing is called there may be
218 /// decls that are initializing. Must be paired with FinishedDeserializing.
219 ///
220 /// The default implementation of this method is a no-op.
221 virtual void StartedDeserializing();
222
223 /// Notify ExternalASTSource that we finished the deserialization of
224 /// a decl or type. Must be paired with StartedDeserializing.
225 ///
226 /// The default implementation of this method is a no-op.
227 virtual void FinishedDeserializing();
228
229 /// Function that will be invoked when we begin parsing a new
230 /// translation unit involving this external AST source.
231 ///
232 /// The default implementation of this method is a no-op.
233 virtual void StartTranslationUnit(ASTConsumer *Consumer);
234
235 /// Print any statistics that have been gathered regarding
236 /// the external AST source.
237 ///
238 /// The default implementation of this method is a no-op.
239 virtual void PrintStats();
240
241 /// Perform layout on the given record.
242 ///
243 /// This routine allows the external AST source to provide an specific
244 /// layout for a record, overriding the layout that would normally be
245 /// constructed. It is intended for clients who receive specific layout
246 /// details rather than source code (such as LLDB). The client is expected
247 /// to fill in the field offsets, base offsets, virtual base offsets, and
248 /// complete object size.
249 ///
250 /// \param Record The record whose layout is being requested.
251 ///
252 /// \param Size The final size of the record, in bits.
253 ///
254 /// \param Alignment The final alignment of the record, in bits.
255 ///
256 /// \param FieldOffsets The offset of each of the fields within the record,
257 /// expressed in bits. All of the fields must be provided with offsets.
258 ///
259 /// \param BaseOffsets The offset of each of the direct, non-virtual base
260 /// classes. If any bases are not given offsets, the bases will be laid
261 /// out according to the ABI.
262 ///
263 /// \param VirtualBaseOffsets The offset of each of the virtual base classes
264 /// (either direct or not). If any bases are not given offsets, the bases will be laid
265 /// out according to the ABI.
266 ///
267 /// \returns true if the record layout was provided, false otherwise.
268 virtual bool layoutRecordType(
269 const RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,
270 llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets,
271 llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets,
272 llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets);
273
274 //===--------------------------------------------------------------------===//
275 // Queries for performance analysis.
276 //===--------------------------------------------------------------------===//
277
278 struct MemoryBufferSizes {
279 size_t malloc_bytes;
280 size_t mmap_bytes;
281
282 MemoryBufferSizes(size_t malloc_bytes, size_t mmap_bytes)
283 : malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {}
284 };
285
286 /// Return the amount of memory used by memory buffers, breaking down
287 /// by heap-backed versus mmap'ed memory.
288 MemoryBufferSizes getMemoryBufferSizes() const {
289 MemoryBufferSizes sizes(0, 0);
290 getMemoryBufferSizes(sizes);
291 return sizes;
292 }
293
294 virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const;
295
296 /// LLVM-style RTTI.
297 /// \{
298 virtual bool isA(const void *ClassID) const { return ClassID == &ID; }
299 static bool classof(const ExternalASTSource *S) { return S->isA(ClassID: &ID); }
300 /// \}
301
302protected:
303 static DeclContextLookupResult
304 SetExternalVisibleDeclsForName(const DeclContext *DC,
305 DeclarationName Name,
306 ArrayRef<NamedDecl*> Decls);
307
308 static DeclContextLookupResult
309 SetNoExternalVisibleDeclsForName(const DeclContext *DC,
310 DeclarationName Name);
311
312 /// Increment the current generation.
313 uint32_t incrementGeneration(ASTContext &C);
314};
315
316/// A lazy pointer to an AST node (of base type T) that resides
317/// within an external AST source.
318///
319/// The AST node is identified within the external AST source by a
320/// 63-bit offset, and can be retrieved via an operation on the
321/// external AST source itself.
322template<typename T, typename OffsT, T* (ExternalASTSource::*Get)(OffsT Offset)>
323struct LazyOffsetPtr {
324 /// Either a pointer to an AST node or the offset within the
325 /// external AST source where the AST node can be found.
326 ///
327 /// If the low bit is clear, a pointer to the AST node. If the low
328 /// bit is set, the upper 63 bits are the offset.
329 mutable uint64_t Ptr = 0;
330
331public:
332 LazyOffsetPtr() = default;
333 explicit LazyOffsetPtr(T *Ptr) : Ptr(reinterpret_cast<uint64_t>(Ptr)) {}
334
335 explicit LazyOffsetPtr(uint64_t Offset) : Ptr((Offset << 1) | 0x01) {
336 assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits");
337 if (Offset == 0)
338 Ptr = 0;
339 }
340
341 LazyOffsetPtr &operator=(T *Ptr) {
342 this->Ptr = reinterpret_cast<uint64_t>(Ptr);
343 return *this;
344 }
345
346 LazyOffsetPtr &operator=(uint64_t Offset) {
347 assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits");
348 if (Offset == 0)
349 Ptr = 0;
350 else
351 Ptr = (Offset << 1) | 0x01;
352
353 return *this;
354 }
355
356 /// Whether this pointer is non-NULL.
357 ///
358 /// This operation does not require the AST node to be deserialized.
359 explicit operator bool() const { return Ptr != 0; }
360
361 /// Whether this pointer is non-NULL.
362 ///
363 /// This operation does not require the AST node to be deserialized.
364 bool isValid() const { return Ptr != 0; }
365
366 /// Whether this pointer is currently stored as an offset.
367 bool isOffset() const { return Ptr & 0x01; }
368
369 /// Retrieve the pointer to the AST node that this lazy pointer points to.
370 ///
371 /// \param Source the external AST source.
372 ///
373 /// \returns a pointer to the AST node.
374 T *get(ExternalASTSource *Source) const {
375 if (isOffset()) {
376 assert(Source &&
377 "Cannot deserialize a lazy pointer without an AST source");
378 Ptr = reinterpret_cast<uint64_t>((Source->*Get)(Ptr >> 1));
379 }
380 return reinterpret_cast<T*>(Ptr);
381 }
382
383 /// Retrieve the address of the AST node pointer. Deserializes the pointee if
384 /// necessary.
385 T **getAddressOfPointer(ExternalASTSource *Source) const {
386 // Ensure the integer is in pointer form.
387 (void)get(Source);
388 return reinterpret_cast<T**>(&Ptr);
389 }
390};
391
392/// A lazy value (of type T) that is within an AST node of type Owner,
393/// where the value might change in later generations of the external AST
394/// source.
395template<typename Owner, typename T, void (ExternalASTSource::*Update)(Owner)>
396struct LazyGenerationalUpdatePtr {
397 /// A cache of the value of this pointer, in the most recent generation in
398 /// which we queried it.
399 struct LazyData {
400 ExternalASTSource *ExternalSource;
401 uint32_t LastGeneration = 0;
402 T LastValue;
403
404 LazyData(ExternalASTSource *Source, T Value)
405 : ExternalSource(Source), LastValue(Value) {}
406 };
407
408 // Our value is represented as simply T if there is no external AST source.
409 using ValueType = llvm::PointerUnion<T, LazyData*>;
410 ValueType Value;
411
412 LazyGenerationalUpdatePtr(ValueType V) : Value(V) {}
413
414 // Defined in ASTContext.h
415 static ValueType makeValue(const ASTContext &Ctx, T Value);
416
417public:
418 explicit LazyGenerationalUpdatePtr(const ASTContext &Ctx, T Value = T())
419 : Value(makeValue(Ctx, Value)) {}
420
421 /// Create a pointer that is not potentially updated by later generations of
422 /// the external AST source.
423 enum NotUpdatedTag { NotUpdated };
424 LazyGenerationalUpdatePtr(NotUpdatedTag, T Value = T())
425 : Value(Value) {}
426
427 /// Forcibly set this pointer (which must be lazy) as needing updates.
428 void markIncomplete() {
429 Value.template get<LazyData *>()->LastGeneration = 0;
430 }
431
432 /// Set the value of this pointer, in the current generation.
433 void set(T NewValue) {
434 if (auto *LazyVal = Value.template dyn_cast<LazyData *>()) {
435 LazyVal->LastValue = NewValue;
436 return;
437 }
438 Value = NewValue;
439 }
440
441 /// Set the value of this pointer, for this and all future generations.
442 void setNotUpdated(T NewValue) { Value = NewValue; }
443
444 /// Get the value of this pointer, updating its owner if necessary.
445 T get(Owner O) {
446 if (auto *LazyVal = Value.template dyn_cast<LazyData *>()) {
447 if (LazyVal->LastGeneration != LazyVal->ExternalSource->getGeneration()) {
448 LazyVal->LastGeneration = LazyVal->ExternalSource->getGeneration();
449 (LazyVal->ExternalSource->*Update)(O);
450 }
451 return LazyVal->LastValue;
452 }
453 return Value.template get<T>();
454 }
455
456 /// Get the most recently computed value of this pointer without updating it.
457 T getNotUpdated() const {
458 if (auto *LazyVal = Value.template dyn_cast<LazyData *>())
459 return LazyVal->LastValue;
460 return Value.template get<T>();
461 }
462
463 void *getOpaqueValue() { return Value.getOpaqueValue(); }
464 static LazyGenerationalUpdatePtr getFromOpaqueValue(void *Ptr) {
465 return LazyGenerationalUpdatePtr(ValueType::getFromOpaqueValue(Ptr));
466 }
467};
468
469} // namespace clang
470
471namespace llvm {
472
473/// Specialize PointerLikeTypeTraits to allow LazyGenerationalUpdatePtr to be
474/// placed into a PointerUnion.
475template<typename Owner, typename T,
476 void (clang::ExternalASTSource::*Update)(Owner)>
477struct PointerLikeTypeTraits<
478 clang::LazyGenerationalUpdatePtr<Owner, T, Update>> {
479 using Ptr = clang::LazyGenerationalUpdatePtr<Owner, T, Update>;
480
481 static void *getAsVoidPointer(Ptr P) { return P.getOpaqueValue(); }
482 static Ptr getFromVoidPointer(void *P) { return Ptr::getFromOpaqueValue(P); }
483
484 static constexpr int NumLowBitsAvailable =
485 PointerLikeTypeTraits<T>::NumLowBitsAvailable - 1;
486};
487
488} // namespace llvm
489
490namespace clang {
491
492/// Represents a lazily-loaded vector of data.
493///
494/// The lazily-loaded vector of data contains data that is partially loaded
495/// from an external source and partially added by local translation. The
496/// items loaded from the external source are loaded lazily, when needed for
497/// iteration over the complete vector.
498template<typename T, typename Source,
499 void (Source::*Loader)(SmallVectorImpl<T>&),
500 unsigned LoadedStorage = 2, unsigned LocalStorage = 4>
501class LazyVector {
502 SmallVector<T, LoadedStorage> Loaded;
503 SmallVector<T, LocalStorage> Local;
504
505public:
506 /// Iteration over the elements in the vector.
507 ///
508 /// In a complete iteration, the iterator walks the range [-M, N),
509 /// where negative values are used to indicate elements
510 /// loaded from the external source while non-negative values are used to
511 /// indicate elements added via \c push_back().
512 /// However, to provide iteration in source order (for, e.g., chained
513 /// precompiled headers), dereferencing the iterator flips the negative
514 /// values (corresponding to loaded entities), so that position -M
515 /// corresponds to element 0 in the loaded entities vector, position -M+1
516 /// corresponds to element 1 in the loaded entities vector, etc. This
517 /// gives us a reasonably efficient, source-order walk.
518 ///
519 /// We define this as a wrapping iterator around an int. The
520 /// iterator_adaptor_base class forwards the iterator methods to basic integer
521 /// arithmetic.
522 class iterator
523 : public llvm::iterator_adaptor_base<
524 iterator, int, std::random_access_iterator_tag, T, int, T *, T &> {
525 friend class LazyVector;
526
527 LazyVector *Self;
528
529 iterator(LazyVector *Self, int Position)
530 : iterator::iterator_adaptor_base(Position), Self(Self) {}
531
532 bool isLoaded() const { return this->I < 0; }
533
534 public:
535 iterator() : iterator(nullptr, 0) {}
536
537 typename iterator::reference operator*() const {
538 if (isLoaded())
539 return Self->Loaded.end()[this->I];
540 return Self->Local.begin()[this->I];
541 }
542 };
543
544 iterator begin(Source *source, bool LocalOnly = false) {
545 if (LocalOnly)
546 return iterator(this, 0);
547
548 if (source)
549 (source->*Loader)(Loaded);
550 return iterator(this, -(int)Loaded.size());
551 }
552
553 iterator end() {
554 return iterator(this, Local.size());
555 }
556
557 void push_back(const T& LocalValue) {
558 Local.push_back(LocalValue);
559 }
560
561 void erase(iterator From, iterator To) {
562 if (From.isLoaded() && To.isLoaded()) {
563 Loaded.erase(&*From, &*To);
564 return;
565 }
566
567 if (From.isLoaded()) {
568 Loaded.erase(&*From, Loaded.end());
569 From = begin(source: nullptr, LocalOnly: true);
570 }
571
572 Local.erase(&*From, &*To);
573 }
574};
575
576/// A lazy pointer to a statement.
577using LazyDeclStmtPtr =
578 LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt>;
579
580/// A lazy pointer to a declaration.
581using LazyDeclPtr =
582 LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl>;
583
584/// A lazy pointer to a set of CXXCtorInitializers.
585using LazyCXXCtorInitializersPtr =
586 LazyOffsetPtr<CXXCtorInitializer *, uint64_t,
587 &ExternalASTSource::GetExternalCXXCtorInitializers>;
588
589/// A lazy pointer to a set of CXXBaseSpecifiers.
590using LazyCXXBaseSpecifiersPtr =
591 LazyOffsetPtr<CXXBaseSpecifier, uint64_t,
592 &ExternalASTSource::GetExternalCXXBaseSpecifiers>;
593
594} // namespace clang
595
596#endif // LLVM_CLANG_AST_EXTERNALASTSOURCE_H
597

source code of clang/include/clang/AST/ExternalASTSource.h