Coverage Report

Created: 2023-09-30 09:22

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
Line
Count
Source (jump to first uncovered line)
1
//===-- ClangASTSource.h ----------------------------------------*- 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
#ifndef LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGASTSOURCE_H
10
#define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGASTSOURCE_H
11
12
#include <set>
13
14
#include "Plugins/ExpressionParser/Clang/ClangASTImporter.h"
15
#include "Plugins/ExpressionParser/Clang/NameSearchContext.h"
16
#include "lldb/Symbol/CompilerType.h"
17
#include "lldb/Target/Target.h"
18
#include "clang/AST/ExternalASTSource.h"
19
#include "clang/Basic/IdentifierTable.h"
20
21
#include "llvm/ADT/SmallSet.h"
22
23
namespace lldb_private {
24
25
/// \class ClangASTSource ClangASTSource.h "lldb/Expression/ClangASTSource.h"
26
/// Provider for named objects defined in the debug info for Clang
27
///
28
/// As Clang parses an expression, it may encounter names that are not defined
29
/// inside the expression, including variables, functions, and types.  Clang
30
/// knows the name it is looking for, but nothing else. The ExternalSemaSource
31
/// class provides Decls (VarDecl, FunDecl, TypeDecl) to Clang for these
32
/// names, consulting the ClangExpressionDeclMap to do the actual lookups.
33
class ClangASTSource : public clang::ExternalASTSource,
34
                       public ClangASTImporter::MapCompleter {
35
public:
36
  /// Constructor
37
  ///
38
  /// Initializes class variables.
39
  ///
40
  /// \param[in] target
41
  ///     A reference to the target containing debug information to use.
42
  ///
43
  /// \param[in] importer
44
  ///     The ClangASTImporter to use.
45
  ClangASTSource(const lldb::TargetSP &target,
46
                 const std::shared_ptr<ClangASTImporter> &importer);
47
48
  /// Destructor
49
  ~ClangASTSource() override;
50
51
  /// Interface stubs.
52
0
  clang::Decl *GetExternalDecl(uint32_t) override { return nullptr; }
53
0
  clang::Stmt *GetExternalDeclStmt(uint64_t) override { return nullptr; }
54
0
  clang::Selector GetExternalSelector(uint32_t) override {
55
0
    return clang::Selector();
56
0
  }
57
0
  uint32_t GetNumExternalSelectors() override { return 0; }
58
  clang::CXXBaseSpecifier *
59
0
  GetExternalCXXBaseSpecifiers(uint64_t Offset) override {
60
0
    return nullptr;
61
0
  }
62
0
  void MaterializeVisibleDecls(const clang::DeclContext *DC) {}
63
64
  void InstallASTContext(TypeSystemClang &ast_context);
65
66
  //
67
  // APIs for ExternalASTSource
68
  //
69
70
  /// Look up all Decls that match a particular name.  Only handles
71
  /// Identifiers and DeclContexts that are either NamespaceDecls or
72
  /// TranslationUnitDecls.  Calls SetExternalVisibleDeclsForName with the
73
  /// result.
74
  ///
75
  /// The work for this function is done by
76
  /// void FindExternalVisibleDecls (NameSearchContext &);
77
  ///
78
  /// \param[in] DC
79
  ///     The DeclContext to register the found Decls in.
80
  ///
81
  /// \param[in] Name
82
  ///     The name to find entries for.
83
  ///
84
  /// \return
85
  ///     Whatever SetExternalVisibleDeclsForName returns.
86
  bool FindExternalVisibleDeclsByName(const clang::DeclContext *DC,
87
                                      clang::DeclarationName Name) override;
88
89
  /// Enumerate all Decls in a given lexical context.
90
  ///
91
  /// \param[in] DC
92
  ///     The DeclContext being searched.
93
  ///
94
  /// \param[in] IsKindWeWant
95
  ///     A callback function that returns true given the
96
  ///     DeclKinds of desired Decls, and false otherwise.
97
  ///
98
  /// \param[in] Decls
99
  ///     A vector that is filled in with matching Decls.
100
  void FindExternalLexicalDecls(
101
      const clang::DeclContext *DC,
102
      llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,
103
      llvm::SmallVectorImpl<clang::Decl *> &Decls) override;
104
105
  /// Specify the layout of the contents of a RecordDecl.
106
  ///
107
  /// \param[in] Record
108
  ///     The record (in the parser's AST context) that needs to be
109
  ///     laid out.
110
  ///
111
  /// \param[out] Size
112
  ///     The total size of the record in bits.
113
  ///
114
  /// \param[out] Alignment
115
  ///     The alignment of the record in bits.
116
  ///
117
  /// \param[in] FieldOffsets
118
  ///     A map that must be populated with pairs of the record's
119
  ///     fields (in the parser's AST context) and their offsets
120
  ///     (measured in bits).
121
  ///
122
  /// \param[in] BaseOffsets
123
  ///     A map that must be populated with pairs of the record's
124
  ///     C++ concrete base classes (in the parser's AST context,
125
  ///     and only if the record is a CXXRecordDecl and has base
126
  ///     classes) and their offsets (measured in bytes).
127
  ///
128
  /// \param[in] VirtualBaseOffsets
129
  ///     A map that must be populated with pairs of the record's
130
  ///     C++ virtual base classes (in the parser's AST context,
131
  ///     and only if the record is a CXXRecordDecl and has base
132
  ///     classes) and their offsets (measured in bytes).
133
  ///
134
  /// \return
135
  ///     True <=> the layout is valid.
136
  bool layoutRecordType(
137
      const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,
138
      llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets,
139
      llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
140
          &BaseOffsets,
141
      llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
142
          &VirtualBaseOffsets) override;
143
144
  /// Complete a TagDecl.
145
  ///
146
  /// \param[in] Tag
147
  ///     The Decl to be completed in place.
148
  void CompleteType(clang::TagDecl *Tag) override;
149
150
  /// Complete an ObjCInterfaceDecl.
151
  ///
152
  /// \param[in] Class
153
  ///     The Decl to be completed in place.
154
  void CompleteType(clang::ObjCInterfaceDecl *Class) override;
155
156
  /// Called on entering a translation unit.  Tells Clang by calling
157
  /// setHasExternalVisibleStorage() and setHasExternalLexicalStorage() that
158
  /// this object has something to say about undefined names.
159
  ///
160
  /// \param[in] Consumer
161
  ///     Unused.
162
  void StartTranslationUnit(clang::ASTConsumer *Consumer) override;
163
164
  //
165
  // APIs for NamespaceMapCompleter
166
  //
167
168
  /// Look up the modules containing a given namespace and put the appropriate
169
  /// entries in the namespace map.
170
  ///
171
  /// \param[in] namespace_map
172
  ///     The map to be completed.
173
  ///
174
  /// \param[in] name
175
  ///     The name of the namespace to be found.
176
  ///
177
  /// \param[in] parent_map
178
  ///     The map for the namespace's parent namespace, if there is
179
  ///     one.
180
  void CompleteNamespaceMap(
181
      ClangASTImporter::NamespaceMapSP &namespace_map, ConstString name,
182
      ClangASTImporter::NamespaceMapSP &parent_map) const override;
183
184
  //
185
  // Helper APIs
186
  //
187
188
  clang::NamespaceDecl *
189
  AddNamespace(NameSearchContext &context,
190
               ClangASTImporter::NamespaceMapSP &namespace_decls);
191
192
  /// The worker function for FindExternalVisibleDeclsByName.
193
  ///
194
  /// \param[in] context
195
  ///     The NameSearchContext to use when filing results.
196
  virtual void FindExternalVisibleDecls(NameSearchContext &context);
197
198
  clang::Sema *getSema();
199
200
8.01k
  void SetLookupsEnabled(bool lookups_enabled) {
201
8.01k
    m_lookups_enabled = lookups_enabled;
202
8.01k
  }
203
345k
  bool GetLookupsEnabled() { return m_lookups_enabled; }
204
205
  /// \class ClangASTSourceProxy ClangASTSource.h
206
  /// "lldb/Expression/ClangASTSource.h" Proxy for ClangASTSource
207
  ///
208
  /// Clang AST contexts like to own their AST sources, so this is a state-
209
  /// free proxy object.
210
  class ClangASTSourceProxy : public clang::ExternalASTSource {
211
  public:
212
12.0k
    ClangASTSourceProxy(ClangASTSource &original) : m_original(original) {}
213
214
    bool FindExternalVisibleDeclsByName(const clang::DeclContext *DC,
215
356k
                                        clang::DeclarationName Name) override {
216
356k
      return m_original.FindExternalVisibleDeclsByName(DC, Name);
217
356k
    }
218
219
    void FindExternalLexicalDecls(
220
        const clang::DeclContext *DC,
221
        llvm::function_ref<bool(clang::Decl::Kind)> IsKindWeWant,
222
41.5k
        llvm::SmallVectorImpl<clang::Decl *> &Decls) override {
223
41.5k
      return m_original.FindExternalLexicalDecls(DC, IsKindWeWant, Decls);
224
41.5k
    }
225
226
876
    void CompleteType(clang::TagDecl *Tag) override {
227
876
      return m_original.CompleteType(Tag);
228
876
    }
229
230
38
    void CompleteType(clang::ObjCInterfaceDecl *Class) override {
231
38
      return m_original.CompleteType(Class);
232
38
    }
233
234
    bool layoutRecordType(
235
        const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,
236
        llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets,
237
        llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
238
            &BaseOffsets,
239
        llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
240
30.1k
            &VirtualBaseOffsets) override {
241
30.1k
      return m_original.layoutRecordType(Record, Size, Alignment, FieldOffsets,
242
30.1k
                                         BaseOffsets, VirtualBaseOffsets);
243
30.1k
    }
244
245
9.94k
    void StartTranslationUnit(clang::ASTConsumer *Consumer) override {
246
9.94k
      return m_original.StartTranslationUnit(Consumer);
247
9.94k
    }
248
249
  private:
250
    ClangASTSource &m_original;
251
  };
252
253
12.0k
  clang::ExternalASTSource *CreateProxy() {
254
12.0k
    return new ClangASTSourceProxy(*this);
255
12.0k
  }
256
257
protected:
258
  /// Look for the complete version of an Objective-C interface, and return it
259
  /// if found.
260
  ///
261
  /// \param[in] interface_decl
262
  ///     An ObjCInterfaceDecl that may not be the complete one.
263
  ///
264
  /// \return
265
  ///     NULL if the complete interface couldn't be found;
266
  ///     the complete interface otherwise.
267
  clang::ObjCInterfaceDecl *
268
  GetCompleteObjCInterface(const clang::ObjCInterfaceDecl *interface_decl);
269
270
  /// Find all entities matching a given name in a given module, using a
271
  /// NameSearchContext to make Decls for them.
272
  ///
273
  /// \param[in] context
274
  ///     The NameSearchContext that can construct Decls for this name.
275
  ///
276
  /// \param[in] module
277
  ///     If non-NULL, the module to query.
278
  ///
279
  /// \param[in] namespace_decl
280
  ///     If valid and module is non-NULL, the parent namespace.
281
  void FindExternalVisibleDecls(NameSearchContext &context,
282
                                lldb::ModuleSP module,
283
                                CompilerDeclContext &namespace_decl);
284
285
  /// Find all Objective-C methods matching a given selector.
286
  ///
287
  /// \param[in] context
288
  ///     The NameSearchContext that can construct Decls for this name.
289
  ///     Its m_decl_name contains the selector and its m_decl_context
290
  ///     is the containing object.
291
  void FindObjCMethodDecls(NameSearchContext &context);
292
293
  /// Find all Objective-C properties and ivars with a given name.
294
  ///
295
  /// \param[in] context
296
  ///     The NameSearchContext that can construct Decls for this name.
297
  ///     Its m_decl_name contains the name and its m_decl_context
298
  ///     is the containing object.
299
  void FindObjCPropertyAndIvarDecls(NameSearchContext &context);
300
301
  /// Performs lookup into a namespace.
302
  ///
303
  /// \param context
304
  ///     The NameSearchContext for a lookup inside a namespace.
305
  void LookupInNamespace(NameSearchContext &context);
306
307
  /// A wrapper for TypeSystemClang::CopyType that sets a flag that
308
  /// indicates that we should not respond to queries during import.
309
  ///
310
  /// \param[in] src_type
311
  ///     The source type.
312
  ///
313
  /// \return
314
  ///     The imported type.
315
  CompilerType GuardedCopyType(const CompilerType &src_type);
316
317
  std::shared_ptr<ClangModulesDeclVendor> GetClangModulesDeclVendor();
318
319
public:
320
  /// Returns true if a name should be ignored by name lookup.
321
  ///
322
  /// \param[in] name
323
  ///     The name to be considered.
324
  ///
325
  /// \param[in] ignore_all_dollar_names
326
  ///     True if $-names of all sorts should be ignored.
327
  ///
328
  /// \return
329
  ///     True if the name is one of a class of names that are ignored by
330
  ///     global lookup for performance reasons.
331
  bool IgnoreName(const ConstString name, bool ignore_all_dollar_names);
332
333
  /// Copies a single Decl into the parser's AST context.
334
  ///
335
  /// \param[in] src_decl
336
  ///     The Decl to copy.
337
  ///
338
  /// \return
339
  ///     A copy of the Decl in m_ast_context, or NULL if the copy failed.
340
  clang::Decl *CopyDecl(clang::Decl *src_decl);
341
342
  /// Determined the origin of a single Decl, if it can be found.
343
  ///
344
  /// \param[in] decl
345
  ///     The Decl whose origin is to be found.
346
  ///
347
  /// \return
348
  ///     True if lookup succeeded; false otherwise.
349
  ClangASTImporter::DeclOrigin GetDeclOrigin(const clang::Decl *decl);
350
351
  /// Returns the TypeSystem that uses this ClangASTSource instance as it's
352
  /// ExternalASTSource.
353
20.7k
  TypeSystemClang *GetTypeSystem() const { return m_clang_ast_context; }
354
355
protected:
356
  bool FindObjCMethodDeclsWithOrigin(
357
      NameSearchContext &context,
358
      clang::ObjCInterfaceDecl *original_interface_decl, const char *log_info);
359
360
  void FindDeclInModules(NameSearchContext &context, ConstString name);
361
  void FindDeclInObjCRuntime(NameSearchContext &context, ConstString name);
362
363
  /// Fills the namespace map of the given NameSearchContext.
364
  ///
365
  /// \param context The NameSearchContext with the namespace map to fill.
366
  /// \param module_sp The module to search for namespaces or a nullptr if
367
  ///                  the current target should be searched.
368
  /// \param namespace_decl The DeclContext in which to search for namespaces.
369
  void FillNamespaceMap(NameSearchContext &context, lldb::ModuleSP module_sp,
370
                        const CompilerDeclContext &namespace_decl);
371
372
  clang::TagDecl *FindCompleteType(const clang::TagDecl *decl);
373
374
  friend struct NameSearchContext;
375
376
  bool m_lookups_enabled;
377
378
  /// The target to use in finding variables and types.
379
  const lldb::TargetSP m_target;
380
  /// The AST context requests are coming in for.
381
  clang::ASTContext *m_ast_context;
382
  /// The TypeSystemClang for m_ast_context.
383
  TypeSystemClang *m_clang_ast_context;
384
  /// The file manager paired with the AST context.
385
  clang::FileManager *m_file_manager;
386
  /// The target's AST importer.
387
  std::shared_ptr<ClangASTImporter> m_ast_importer_sp;
388
  std::set<const clang::Decl *> m_active_lexical_decls;
389
  std::set<const char *> m_active_lookups;
390
};
391
392
} // namespace lldb_private
393
394
#endif // LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGASTSOURCE_H