1//===--- ExternalSemaSource.h - External Sema 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 ExternalSemaSource interface.
10//
11//===----------------------------------------------------------------------===//
12#ifndef LLVM_CLANG_SEMA_EXTERNALSEMASOURCE_H
13#define LLVM_CLANG_SEMA_EXTERNALSEMASOURCE_H
14
15#include "clang/AST/ExternalASTSource.h"
16#include "clang/AST/Type.h"
17#include "clang/Sema/TypoCorrection.h"
18#include "clang/Sema/Weak.h"
19#include "llvm/ADT/MapVector.h"
20#include <utility>
21
22namespace llvm {
23template <class T, unsigned n> class SmallSetVector;
24}
25
26namespace clang {
27
28class CXXConstructorDecl;
29class CXXRecordDecl;
30class DeclaratorDecl;
31class LookupResult;
32class Scope;
33class Sema;
34class TypedefNameDecl;
35class ValueDecl;
36class VarDecl;
37struct LateParsedTemplate;
38
39/// A simple structure that captures a vtable use for the purposes of
40/// the \c ExternalSemaSource.
41struct ExternalVTableUse {
42 CXXRecordDecl *Record;
43 SourceLocation Location;
44 bool DefinitionRequired;
45};
46
47/// An abstract interface that should be implemented by
48/// external AST sources that also provide information for semantic
49/// analysis.
50class ExternalSemaSource : public ExternalASTSource {
51 /// LLVM-style RTTI.
52 static char ID;
53
54public:
55 ExternalSemaSource() = default;
56
57 ~ExternalSemaSource() override;
58
59 /// Initialize the semantic source with the Sema instance
60 /// being used to perform semantic analysis on the abstract syntax
61 /// tree.
62 virtual void InitializeSema(Sema &S) {}
63
64 /// Inform the semantic consumer that Sema is no longer available.
65 virtual void ForgetSema() {}
66
67 /// Load the contents of the global method pool for a given
68 /// selector.
69 virtual void ReadMethodPool(Selector Sel);
70
71 /// Load the contents of the global method pool for a given
72 /// selector if necessary.
73 virtual void updateOutOfDateSelector(Selector Sel);
74
75 /// Load the set of namespaces that are known to the external source,
76 /// which will be used during typo correction.
77 virtual void ReadKnownNamespaces(
78 SmallVectorImpl<NamespaceDecl *> &Namespaces);
79
80 /// Load the set of used but not defined functions or variables with
81 /// internal linkage, or used but not defined internal functions.
82 virtual void
83 ReadUndefinedButUsed(llvm::MapVector<NamedDecl *, SourceLocation> &Undefined);
84
85 virtual void ReadMismatchingDeleteExpressions(llvm::MapVector<
86 FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &);
87
88 /// Do last resort, unqualified lookup on a LookupResult that
89 /// Sema cannot find.
90 ///
91 /// \param R a LookupResult that is being recovered.
92 ///
93 /// \param S the Scope of the identifier occurrence.
94 ///
95 /// \return true to tell Sema to recover using the LookupResult.
96 virtual bool LookupUnqualified(LookupResult &R, Scope *S) { return false; }
97
98 /// Read the set of tentative definitions known to the external Sema
99 /// source.
100 ///
101 /// The external source should append its own tentative definitions to the
102 /// given vector of tentative definitions. Note that this routine may be
103 /// invoked multiple times; the external source should take care not to
104 /// introduce the same declarations repeatedly.
105 virtual void ReadTentativeDefinitions(
106 SmallVectorImpl<VarDecl *> &TentativeDefs) {}
107
108 /// Read the set of unused file-scope declarations known to the
109 /// external Sema source.
110 ///
111 /// The external source should append its own unused, filed-scope to the
112 /// given vector of declarations. Note that this routine may be
113 /// invoked multiple times; the external source should take care not to
114 /// introduce the same declarations repeatedly.
115 virtual void ReadUnusedFileScopedDecls(
116 SmallVectorImpl<const DeclaratorDecl *> &Decls) {}
117
118 /// Read the set of delegating constructors known to the
119 /// external Sema source.
120 ///
121 /// The external source should append its own delegating constructors to the
122 /// given vector of declarations. Note that this routine may be
123 /// invoked multiple times; the external source should take care not to
124 /// introduce the same declarations repeatedly.
125 virtual void ReadDelegatingConstructors(
126 SmallVectorImpl<CXXConstructorDecl *> &Decls) {}
127
128 /// Read the set of ext_vector type declarations known to the
129 /// external Sema source.
130 ///
131 /// The external source should append its own ext_vector type declarations to
132 /// the given vector of declarations. Note that this routine may be
133 /// invoked multiple times; the external source should take care not to
134 /// introduce the same declarations repeatedly.
135 virtual void ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl *> &Decls) {}
136
137 /// Read the set of potentially unused typedefs known to the source.
138 ///
139 /// The external source should append its own potentially unused local
140 /// typedefs to the given vector of declarations. Note that this routine may
141 /// be invoked multiple times; the external source should take care not to
142 /// introduce the same declarations repeatedly.
143 virtual void ReadUnusedLocalTypedefNameCandidates(
144 llvm::SmallPtrSetImpl<const TypedefNameDecl *> &Decls) {}
145
146 /// Read the set of referenced selectors known to the
147 /// external Sema source.
148 ///
149 /// The external source should append its own referenced selectors to the
150 /// given vector of selectors. Note that this routine
151 /// may be invoked multiple times; the external source should take care not
152 /// to introduce the same selectors repeatedly.
153 virtual void ReadReferencedSelectors(
154 SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels) {}
155
156 /// Read the set of weak, undeclared identifiers known to the
157 /// external Sema source.
158 ///
159 /// The external source should append its own weak, undeclared identifiers to
160 /// the given vector. Note that this routine may be invoked multiple times;
161 /// the external source should take care not to introduce the same identifiers
162 /// repeatedly.
163 virtual void ReadWeakUndeclaredIdentifiers(
164 SmallVectorImpl<std::pair<IdentifierInfo *, WeakInfo> > &WI) {}
165
166 /// Read the set of #pragma redefine_extname'd, undeclared identifiers known
167 /// to the external Sema source.
168 ///
169 /// The external source should append its own #pragma redefine_extname'd,
170 /// undeclared identifiers to the given vector. Note that this routine may be
171 /// invoked multiple times; the external source should take care not to
172 /// introduce the same identifiers repeatedly.
173 virtual void ReadExtnameUndeclaredIdentifiers(
174 SmallVectorImpl<std::pair<IdentifierInfo *, AsmLabelAttr *>> &EI) {}
175
176 /// Read the set of used vtables known to the external Sema source.
177 ///
178 /// The external source should append its own used vtables to the given
179 /// vector. Note that this routine may be invoked multiple times; the external
180 /// source should take care not to introduce the same vtables repeatedly.
181 virtual void ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) {}
182
183 /// Read the set of pending instantiations known to the external
184 /// Sema source.
185 ///
186 /// The external source should append its own pending instantiations to the
187 /// given vector. Note that this routine may be invoked multiple times; the
188 /// external source should take care not to introduce the same instantiations
189 /// repeatedly.
190 virtual void ReadPendingInstantiations(
191 SmallVectorImpl<std::pair<ValueDecl *,
192 SourceLocation> > &Pending) {}
193
194 /// Read the set of late parsed template functions for this source.
195 ///
196 /// The external source should insert its own late parsed template functions
197 /// into the map. Note that this routine may be invoked multiple times; the
198 /// external source should take care not to introduce the same map entries
199 /// repeatedly.
200 virtual void ReadLateParsedTemplates(
201 llvm::MapVector<const FunctionDecl *, std::unique_ptr<LateParsedTemplate>>
202 &LPTMap) {}
203
204 /// Read the set of decls to be checked for deferred diags.
205 ///
206 /// The external source should append its own potentially emitted function
207 /// and variable decls which may cause deferred diags. Note that this routine
208 /// may be invoked multiple times; the external source should take care not to
209 /// introduce the same declarations repeatedly.
210 virtual void
211 ReadDeclsToCheckForDeferredDiags(llvm::SmallSetVector<Decl *, 4> &Decls) {}
212
213 /// \copydoc Sema::CorrectTypo
214 /// \note LookupKind must correspond to a valid Sema::LookupNameKind
215 ///
216 /// ExternalSemaSource::CorrectTypo is always given the first chance to
217 /// correct a typo (really, to offer suggestions to repair a failed lookup).
218 /// It will even be called when SpellChecking is turned off or after a
219 /// fatal error has already been detected.
220 virtual TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo,
221 int LookupKind, Scope *S, CXXScopeSpec *SS,
222 CorrectionCandidateCallback &CCC,
223 DeclContext *MemberContext,
224 bool EnteringContext,
225 const ObjCObjectPointerType *OPT) {
226 return TypoCorrection();
227 }
228
229 /// Produces a diagnostic note if the external source contains a
230 /// complete definition for \p T.
231 ///
232 /// \param Loc the location at which a complete type was required but not
233 /// provided
234 ///
235 /// \param T the \c QualType that should have been complete at \p Loc
236 ///
237 /// \return true if a diagnostic was produced, false otherwise.
238 virtual bool MaybeDiagnoseMissingCompleteType(SourceLocation Loc,
239 QualType T) {
240 return false;
241 }
242
243 /// LLVM-style RTTI.
244 /// \{
245 bool isA(const void *ClassID) const override {
246 return ClassID == &ID || ExternalASTSource::isA(ClassID);
247 }
248 static bool classof(const ExternalASTSource *S) { return S->isA(ClassID: &ID); }
249 /// \}
250};
251
252/// Represents a lazily-loaded vector of data.
253///
254/// The lazily-loaded vector of data contains data that is partially loaded
255/// from an external source and partially added by local translation. The
256/// items loaded from the external source are loaded lazily, when needed for
257/// iteration over the complete vector.
258template <typename T, void (ExternalSemaSource::*Loader)(SmallVectorImpl<T> &),
259 unsigned LoadedStorage = 2, unsigned LocalStorage = 4>
260class LazyVector {
261 SmallVector<T, LoadedStorage> Loaded;
262 SmallVector<T, LocalStorage> Local;
263
264public:
265 /// Iteration over the elements in the vector.
266 ///
267 /// In a complete iteration, the iterator walks the range [-M, N),
268 /// where negative values are used to indicate elements
269 /// loaded from the external source while non-negative values are used to
270 /// indicate elements added via \c push_back().
271 /// However, to provide iteration in source order (for, e.g., chained
272 /// precompiled headers), dereferencing the iterator flips the negative
273 /// values (corresponding to loaded entities), so that position -M
274 /// corresponds to element 0 in the loaded entities vector, position -M+1
275 /// corresponds to element 1 in the loaded entities vector, etc. This
276 /// gives us a reasonably efficient, source-order walk.
277 ///
278 /// We define this as a wrapping iterator around an int. The
279 /// iterator_adaptor_base class forwards the iterator methods to basic integer
280 /// arithmetic.
281 class iterator
282 : public llvm::iterator_adaptor_base<
283 iterator, int, std::random_access_iterator_tag, T, int, T *, T &> {
284 friend class LazyVector;
285
286 LazyVector *Self;
287
288 iterator(LazyVector *Self, int Position)
289 : iterator::iterator_adaptor_base(Position), Self(Self) {}
290
291 bool isLoaded() const { return this->I < 0; }
292
293 public:
294 iterator() : iterator(nullptr, 0) {}
295
296 typename iterator::reference operator*() const {
297 if (isLoaded())
298 return Self->Loaded.end()[this->I];
299 return Self->Local.begin()[this->I];
300 }
301 };
302
303 iterator begin(ExternalSemaSource *source, bool LocalOnly = false) {
304 if (LocalOnly)
305 return iterator(this, 0);
306
307 if (source)
308 (source->*Loader)(Loaded);
309 return iterator(this, -(int)Loaded.size());
310 }
311
312 iterator end() { return iterator(this, Local.size()); }
313
314 void push_back(const T &LocalValue) { Local.push_back(LocalValue); }
315
316 void erase(iterator From, iterator To) {
317 if (From.isLoaded() && To.isLoaded()) {
318 Loaded.erase(&*From, &*To);
319 return;
320 }
321
322 if (From.isLoaded()) {
323 Loaded.erase(&*From, Loaded.end());
324 From = begin(source: nullptr, LocalOnly: true);
325 }
326
327 Local.erase(&*From, &*To);
328 }
329};
330
331} // end namespace clang
332
333#endif
334