1 | //===-- ClangASTImporter.cpp ----------------------------------------------===// |
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 | #include "lldb/Core/Module.h" |
10 | #include "lldb/Utility/LLDBAssert.h" |
11 | #include "lldb/Utility/LLDBLog.h" |
12 | #include "lldb/Utility/Log.h" |
13 | #include "clang/AST/ASTContext.h" |
14 | #include "clang/AST/Decl.h" |
15 | #include "clang/AST/DeclCXX.h" |
16 | #include "clang/AST/DeclObjC.h" |
17 | #include "clang/AST/RecordLayout.h" |
18 | #include "clang/Sema/Lookup.h" |
19 | #include "clang/Sema/Sema.h" |
20 | #include "llvm/Support/raw_ostream.h" |
21 | |
22 | #include "Plugins/ExpressionParser/Clang/ClangASTImporter.h" |
23 | #include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h" |
24 | #include "Plugins/ExpressionParser/Clang/ClangASTSource.h" |
25 | #include "Plugins/ExpressionParser/Clang/ClangExternalASTSourceCallbacks.h" |
26 | #include "Plugins/ExpressionParser/Clang/ClangUtil.h" |
27 | #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" |
28 | |
29 | #include <memory> |
30 | #include <optional> |
31 | #include <type_traits> |
32 | |
33 | using namespace lldb_private; |
34 | using namespace clang; |
35 | |
36 | CompilerType ClangASTImporter::CopyType(TypeSystemClang &dst_ast, |
37 | const CompilerType &src_type) { |
38 | clang::ASTContext &dst_clang_ast = dst_ast.getASTContext(); |
39 | |
40 | auto src_ast = src_type.GetTypeSystem<TypeSystemClang>(); |
41 | if (!src_ast) |
42 | return CompilerType(); |
43 | |
44 | clang::ASTContext &src_clang_ast = src_ast->getASTContext(); |
45 | |
46 | clang::QualType src_qual_type = ClangUtil::GetQualType(ct: src_type); |
47 | |
48 | ImporterDelegateSP delegate_sp(GetDelegate(dst_ctx: &dst_clang_ast, src_ctx: &src_clang_ast)); |
49 | if (!delegate_sp) |
50 | return CompilerType(); |
51 | |
52 | ASTImporterDelegate::CxxModuleScope std_scope(*delegate_sp, &dst_clang_ast); |
53 | |
54 | llvm::Expected<QualType> ret_or_error = delegate_sp->Import(src_qual_type); |
55 | if (!ret_or_error) { |
56 | Log *log = GetLog(mask: LLDBLog::Expressions); |
57 | LLDB_LOG_ERROR(log, ret_or_error.takeError(), |
58 | "Couldn't import type: {0}" ); |
59 | return CompilerType(); |
60 | } |
61 | |
62 | lldb::opaque_compiler_type_t dst_clang_type = ret_or_error->getAsOpaquePtr(); |
63 | |
64 | if (dst_clang_type) |
65 | return CompilerType(dst_ast.weak_from_this(), dst_clang_type); |
66 | return CompilerType(); |
67 | } |
68 | |
69 | clang::Decl *ClangASTImporter::CopyDecl(clang::ASTContext *dst_ast, |
70 | clang::Decl *decl) { |
71 | ImporterDelegateSP delegate_sp; |
72 | |
73 | clang::ASTContext *src_ast = &decl->getASTContext(); |
74 | delegate_sp = GetDelegate(dst_ctx: dst_ast, src_ctx: src_ast); |
75 | |
76 | ASTImporterDelegate::CxxModuleScope std_scope(*delegate_sp, dst_ast); |
77 | |
78 | if (!delegate_sp) |
79 | return nullptr; |
80 | |
81 | llvm::Expected<clang::Decl *> result = delegate_sp->Import(FromD: decl); |
82 | if (!result) { |
83 | Log *log = GetLog(mask: LLDBLog::Expressions); |
84 | LLDB_LOG_ERROR(log, result.takeError(), "Couldn't import decl: {0}" ); |
85 | if (log) { |
86 | lldb::user_id_t user_id = LLDB_INVALID_UID; |
87 | if (std::optional<ClangASTMetadata> metadata = GetDeclMetadata(decl)) |
88 | user_id = metadata->GetUserID(); |
89 | |
90 | if (NamedDecl *named_decl = dyn_cast<NamedDecl>(Val: decl)) |
91 | LLDB_LOG(log, |
92 | " [ClangASTImporter] WARNING: Failed to import a {0} " |
93 | "'{1}', metadata {2}" , |
94 | decl->getDeclKindName(), named_decl->getNameAsString(), |
95 | user_id); |
96 | else |
97 | LLDB_LOG(log, |
98 | " [ClangASTImporter] WARNING: Failed to import a {0}, " |
99 | "metadata {1}" , |
100 | decl->getDeclKindName(), user_id); |
101 | } |
102 | return nullptr; |
103 | } |
104 | |
105 | return *result; |
106 | } |
107 | |
108 | class DeclContextOverride { |
109 | private: |
110 | struct Backup { |
111 | clang::DeclContext *decl_context; |
112 | clang::DeclContext *lexical_decl_context; |
113 | }; |
114 | |
115 | llvm::DenseMap<clang::Decl *, Backup> m_backups; |
116 | |
117 | void OverrideOne(clang::Decl *decl) { |
118 | if (m_backups.contains(Val: decl)) { |
119 | return; |
120 | } |
121 | |
122 | m_backups[decl] = {.decl_context: decl->getDeclContext(), .lexical_decl_context: decl->getLexicalDeclContext()}; |
123 | |
124 | decl->setDeclContext(decl->getASTContext().getTranslationUnitDecl()); |
125 | decl->setLexicalDeclContext(decl->getASTContext().getTranslationUnitDecl()); |
126 | } |
127 | |
128 | bool ChainPassesThrough( |
129 | clang::Decl *decl, clang::DeclContext *base, |
130 | clang::DeclContext *(clang::Decl::*contextFromDecl)(), |
131 | clang::DeclContext *(clang::DeclContext::*contextFromContext)()) { |
132 | for (DeclContext *decl_ctx = (decl->*contextFromDecl)(); decl_ctx; |
133 | decl_ctx = (decl_ctx->*contextFromContext)()) { |
134 | if (decl_ctx == base) { |
135 | return true; |
136 | } |
137 | } |
138 | |
139 | return false; |
140 | } |
141 | |
142 | clang::Decl *GetEscapedChild(clang::Decl *decl, |
143 | clang::DeclContext *base = nullptr) { |
144 | if (base) { |
145 | // decl's DeclContext chains must pass through base. |
146 | |
147 | if (!ChainPassesThrough(decl, base, contextFromDecl: &clang::Decl::getDeclContext, |
148 | contextFromContext: &clang::DeclContext::getParent) || |
149 | !ChainPassesThrough(decl, base, contextFromDecl: &clang::Decl::getLexicalDeclContext, |
150 | contextFromContext: &clang::DeclContext::getLexicalParent)) { |
151 | return decl; |
152 | } |
153 | } else { |
154 | base = clang::dyn_cast<clang::DeclContext>(Val: decl); |
155 | |
156 | if (!base) { |
157 | return nullptr; |
158 | } |
159 | } |
160 | |
161 | if (clang::DeclContext *context = |
162 | clang::dyn_cast<clang::DeclContext>(Val: decl)) { |
163 | for (clang::Decl *decl : context->decls()) { |
164 | if (clang::Decl *escaped_child = GetEscapedChild(decl)) { |
165 | return escaped_child; |
166 | } |
167 | } |
168 | } |
169 | |
170 | return nullptr; |
171 | } |
172 | |
173 | void Override(clang::Decl *decl) { |
174 | if (clang::Decl *escaped_child = GetEscapedChild(decl)) { |
175 | Log *log = GetLog(mask: LLDBLog::Expressions); |
176 | |
177 | LLDB_LOG(log, |
178 | " [ClangASTImporter] DeclContextOverride couldn't " |
179 | "override ({0}Decl*){1} - its child ({2}Decl*){3} escapes" , |
180 | decl->getDeclKindName(), decl, escaped_child->getDeclKindName(), |
181 | escaped_child); |
182 | lldbassert(0 && "Couldn't override!" ); |
183 | } |
184 | |
185 | OverrideOne(decl); |
186 | } |
187 | |
188 | public: |
189 | DeclContextOverride() = default; |
190 | |
191 | void OverrideAllDeclsFromContainingFunction(clang::Decl *decl) { |
192 | for (DeclContext *decl_context = decl->getLexicalDeclContext(); |
193 | decl_context; decl_context = decl_context->getLexicalParent()) { |
194 | DeclContext *redecl_context = decl_context->getRedeclContext(); |
195 | |
196 | if (llvm::isa<FunctionDecl>(Val: redecl_context) && |
197 | llvm::isa<TranslationUnitDecl>(Val: redecl_context->getLexicalParent())) { |
198 | for (clang::Decl *child_decl : decl_context->decls()) { |
199 | Override(decl: child_decl); |
200 | } |
201 | } |
202 | } |
203 | } |
204 | |
205 | ~DeclContextOverride() { |
206 | for (const std::pair<clang::Decl *, Backup> &backup : m_backups) { |
207 | backup.first->setDeclContext(backup.second.decl_context); |
208 | backup.first->setLexicalDeclContext(backup.second.lexical_decl_context); |
209 | } |
210 | } |
211 | }; |
212 | |
213 | namespace { |
214 | /// Completes all imported TagDecls at the end of the scope. |
215 | /// |
216 | /// While in a CompleteTagDeclsScope, every decl that could be completed will |
217 | /// be completed at the end of the scope (including all Decls that are |
218 | /// imported while completing the original Decls). |
219 | class CompleteTagDeclsScope : public ClangASTImporter::NewDeclListener { |
220 | ClangASTImporter::ImporterDelegateSP m_delegate; |
221 | /// List of declarations in the target context that need to be completed. |
222 | /// Every declaration should only be completed once and therefore should only |
223 | /// be once in this list. |
224 | llvm::SetVector<NamedDecl *> m_decls_to_complete; |
225 | /// Set of declarations that already were successfully completed (not just |
226 | /// added to m_decls_to_complete). |
227 | llvm::SmallPtrSet<NamedDecl *, 32> m_decls_already_completed; |
228 | clang::ASTContext *m_dst_ctx; |
229 | clang::ASTContext *m_src_ctx; |
230 | ClangASTImporter &importer; |
231 | |
232 | public: |
233 | /// Constructs a CompleteTagDeclsScope. |
234 | /// \param importer The ClangASTImporter that we should observe. |
235 | /// \param dst_ctx The ASTContext to which Decls are imported. |
236 | /// \param src_ctx The ASTContext from which Decls are imported. |
237 | explicit CompleteTagDeclsScope(ClangASTImporter &importer, |
238 | clang::ASTContext *dst_ctx, |
239 | clang::ASTContext *src_ctx) |
240 | : m_delegate(importer.GetDelegate(dst_ctx, src_ctx)), m_dst_ctx(dst_ctx), |
241 | m_src_ctx(src_ctx), importer(importer) { |
242 | m_delegate->SetImportListener(this); |
243 | } |
244 | |
245 | ~CompleteTagDeclsScope() override { |
246 | ClangASTImporter::ASTContextMetadataSP to_context_md = |
247 | importer.GetContextMetadata(dst_ctx: m_dst_ctx); |
248 | |
249 | // Complete all decls we collected until now. |
250 | while (!m_decls_to_complete.empty()) { |
251 | NamedDecl *decl = m_decls_to_complete.pop_back_val(); |
252 | m_decls_already_completed.insert(Ptr: decl); |
253 | |
254 | // The decl that should be completed has to be imported into the target |
255 | // context from some other context. |
256 | assert(to_context_md->hasOrigin(decl)); |
257 | // We should only complete decls coming from the source context. |
258 | assert(to_context_md->getOrigin(decl).ctx == m_src_ctx); |
259 | |
260 | Decl *original_decl = to_context_md->getOrigin(decl).decl; |
261 | |
262 | // Complete the decl now. |
263 | TypeSystemClang::GetCompleteDecl(ast: m_src_ctx, decl: original_decl); |
264 | if (auto *tag_decl = dyn_cast<TagDecl>(Val: decl)) { |
265 | if (auto *original_tag_decl = dyn_cast<TagDecl>(original_decl)) { |
266 | if (original_tag_decl->isCompleteDefinition()) { |
267 | m_delegate->ImportDefinitionTo(to: tag_decl, from: original_tag_decl); |
268 | tag_decl->setCompleteDefinition(true); |
269 | } |
270 | } |
271 | |
272 | tag_decl->setHasExternalLexicalStorage(false); |
273 | tag_decl->setHasExternalVisibleStorage(false); |
274 | } else if (auto *container_decl = dyn_cast<ObjCContainerDecl>(Val: decl)) { |
275 | container_decl->setHasExternalLexicalStorage(false); |
276 | container_decl->setHasExternalVisibleStorage(false); |
277 | } |
278 | |
279 | to_context_md->removeOrigin(decl); |
280 | } |
281 | |
282 | // Stop listening to imported decls. We do this after clearing the |
283 | // Decls we needed to import to catch all Decls they might have pulled in. |
284 | m_delegate->RemoveImportListener(); |
285 | } |
286 | |
287 | void NewDeclImported(clang::Decl *from, clang::Decl *to) override { |
288 | // Filter out decls that we can't complete later. |
289 | if (!isa<TagDecl>(Val: to) && !isa<ObjCInterfaceDecl>(Val: to)) |
290 | return; |
291 | RecordDecl *from_record_decl = dyn_cast<RecordDecl>(Val: from); |
292 | // We don't need to complete injected class name decls. |
293 | if (from_record_decl && from_record_decl->isInjectedClassName()) |
294 | return; |
295 | |
296 | NamedDecl *to_named_decl = dyn_cast<NamedDecl>(Val: to); |
297 | // Check if we already completed this type. |
298 | if (m_decls_already_completed.contains(Ptr: to_named_decl)) |
299 | return; |
300 | // Queue this type to be completed. |
301 | m_decls_to_complete.insert(X: to_named_decl); |
302 | } |
303 | }; |
304 | } // namespace |
305 | |
306 | CompilerType ClangASTImporter::DeportType(TypeSystemClang &dst, |
307 | const CompilerType &src_type) { |
308 | Log *log = GetLog(mask: LLDBLog::Expressions); |
309 | |
310 | auto src_ctxt = src_type.GetTypeSystem<TypeSystemClang>(); |
311 | if (!src_ctxt) |
312 | return {}; |
313 | |
314 | LLDB_LOG(log, |
315 | " [ClangASTImporter] DeportType called on ({0}Type*){1:x} " |
316 | "from (ASTContext*){2:x} to (ASTContext*){3:x}" , |
317 | src_type.GetTypeName(), src_type.GetOpaqueQualType(), |
318 | &src_ctxt->getASTContext(), &dst.getASTContext()); |
319 | |
320 | DeclContextOverride decl_context_override; |
321 | |
322 | if (auto *t = ClangUtil::GetQualType(ct: src_type)->getAs<TagType>()) |
323 | decl_context_override.OverrideAllDeclsFromContainingFunction(t->getDecl()); |
324 | |
325 | CompleteTagDeclsScope complete_scope(*this, &dst.getASTContext(), |
326 | &src_ctxt->getASTContext()); |
327 | return CopyType(dst_ast&: dst, src_type); |
328 | } |
329 | |
330 | clang::Decl *ClangASTImporter::DeportDecl(clang::ASTContext *dst_ctx, |
331 | clang::Decl *decl) { |
332 | Log *log = GetLog(mask: LLDBLog::Expressions); |
333 | |
334 | clang::ASTContext *src_ctx = &decl->getASTContext(); |
335 | LLDB_LOG(log, |
336 | " [ClangASTImporter] DeportDecl called on ({0}Decl*){1:x} from " |
337 | "(ASTContext*){2:x} to (ASTContext*){3:x}" , |
338 | decl->getDeclKindName(), decl, src_ctx, dst_ctx); |
339 | |
340 | DeclContextOverride decl_context_override; |
341 | |
342 | decl_context_override.OverrideAllDeclsFromContainingFunction(decl); |
343 | |
344 | clang::Decl *result; |
345 | { |
346 | CompleteTagDeclsScope complete_scope(*this, dst_ctx, src_ctx); |
347 | result = CopyDecl(dst_ast: dst_ctx, decl); |
348 | } |
349 | |
350 | if (!result) |
351 | return nullptr; |
352 | |
353 | LLDB_LOG(log, |
354 | " [ClangASTImporter] DeportDecl deported ({0}Decl*){1:x} to " |
355 | "({2}Decl*){3:x}" , |
356 | decl->getDeclKindName(), decl, result->getDeclKindName(), result); |
357 | |
358 | return result; |
359 | } |
360 | |
361 | bool ClangASTImporter::CanImport(const CompilerType &type) { |
362 | if (!ClangUtil::IsClangType(ct: type)) |
363 | return false; |
364 | |
365 | clang::QualType qual_type( |
366 | ClangUtil::GetCanonicalQualType(ct: ClangUtil::RemoveFastQualifiers(ct: type))); |
367 | |
368 | const clang::Type::TypeClass type_class = qual_type->getTypeClass(); |
369 | switch (type_class) { |
370 | case clang::Type::Record: { |
371 | const clang::CXXRecordDecl *cxx_record_decl = |
372 | qual_type->getAsCXXRecordDecl(); |
373 | if (cxx_record_decl) { |
374 | if (GetDeclOrigin(cxx_record_decl).Valid()) |
375 | return true; |
376 | } |
377 | } break; |
378 | |
379 | case clang::Type::Enum: { |
380 | clang::EnumDecl *enum_decl = |
381 | llvm::cast<clang::EnumType>(Val&: qual_type)->getDecl(); |
382 | if (enum_decl) { |
383 | if (GetDeclOrigin(enum_decl).Valid()) |
384 | return true; |
385 | } |
386 | } break; |
387 | |
388 | case clang::Type::ObjCObject: |
389 | case clang::Type::ObjCInterface: { |
390 | const clang::ObjCObjectType *objc_class_type = |
391 | llvm::dyn_cast<clang::ObjCObjectType>(Val&: qual_type); |
392 | if (objc_class_type) { |
393 | clang::ObjCInterfaceDecl *class_interface_decl = |
394 | objc_class_type->getInterface(); |
395 | // We currently can't complete objective C types through the newly added |
396 | // ASTContext because it only supports TagDecl objects right now... |
397 | if (class_interface_decl) { |
398 | if (GetDeclOrigin(class_interface_decl).Valid()) |
399 | return true; |
400 | } |
401 | } |
402 | } break; |
403 | |
404 | case clang::Type::Typedef: |
405 | return CanImport(type: CompilerType(type.GetTypeSystem(), |
406 | llvm::cast<clang::TypedefType>(Val&: qual_type) |
407 | ->getDecl() |
408 | ->getUnderlyingType() |
409 | .getAsOpaquePtr())); |
410 | |
411 | case clang::Type::Auto: |
412 | return CanImport(type: CompilerType(type.GetTypeSystem(), |
413 | llvm::cast<clang::AutoType>(Val&: qual_type) |
414 | ->getDeducedType() |
415 | .getAsOpaquePtr())); |
416 | |
417 | case clang::Type::Elaborated: |
418 | return CanImport(type: CompilerType(type.GetTypeSystem(), |
419 | llvm::cast<clang::ElaboratedType>(Val&: qual_type) |
420 | ->getNamedType() |
421 | .getAsOpaquePtr())); |
422 | |
423 | case clang::Type::Paren: |
424 | return CanImport(type: CompilerType( |
425 | type.GetTypeSystem(), |
426 | llvm::cast<clang::ParenType>(Val&: qual_type)->desugar().getAsOpaquePtr())); |
427 | |
428 | default: |
429 | break; |
430 | } |
431 | |
432 | return false; |
433 | } |
434 | |
435 | bool ClangASTImporter::Import(const CompilerType &type) { |
436 | if (!ClangUtil::IsClangType(ct: type)) |
437 | return false; |
438 | |
439 | clang::QualType qual_type( |
440 | ClangUtil::GetCanonicalQualType(ct: ClangUtil::RemoveFastQualifiers(ct: type))); |
441 | |
442 | const clang::Type::TypeClass type_class = qual_type->getTypeClass(); |
443 | switch (type_class) { |
444 | case clang::Type::Record: { |
445 | const clang::CXXRecordDecl *cxx_record_decl = |
446 | qual_type->getAsCXXRecordDecl(); |
447 | if (cxx_record_decl) { |
448 | if (GetDeclOrigin(cxx_record_decl).Valid()) |
449 | return CompleteAndFetchChildren(type: qual_type); |
450 | } |
451 | } break; |
452 | |
453 | case clang::Type::Enum: { |
454 | clang::EnumDecl *enum_decl = |
455 | llvm::cast<clang::EnumType>(Val&: qual_type)->getDecl(); |
456 | if (enum_decl) { |
457 | if (GetDeclOrigin(enum_decl).Valid()) |
458 | return CompleteAndFetchChildren(type: qual_type); |
459 | } |
460 | } break; |
461 | |
462 | case clang::Type::ObjCObject: |
463 | case clang::Type::ObjCInterface: { |
464 | const clang::ObjCObjectType *objc_class_type = |
465 | llvm::dyn_cast<clang::ObjCObjectType>(Val&: qual_type); |
466 | if (objc_class_type) { |
467 | clang::ObjCInterfaceDecl *class_interface_decl = |
468 | objc_class_type->getInterface(); |
469 | // We currently can't complete objective C types through the newly added |
470 | // ASTContext because it only supports TagDecl objects right now... |
471 | if (class_interface_decl) { |
472 | if (GetDeclOrigin(class_interface_decl).Valid()) |
473 | return CompleteAndFetchChildren(type: qual_type); |
474 | } |
475 | } |
476 | } break; |
477 | |
478 | case clang::Type::Typedef: |
479 | return Import(type: CompilerType(type.GetTypeSystem(), |
480 | llvm::cast<clang::TypedefType>(Val&: qual_type) |
481 | ->getDecl() |
482 | ->getUnderlyingType() |
483 | .getAsOpaquePtr())); |
484 | |
485 | case clang::Type::Auto: |
486 | return Import(type: CompilerType(type.GetTypeSystem(), |
487 | llvm::cast<clang::AutoType>(Val&: qual_type) |
488 | ->getDeducedType() |
489 | .getAsOpaquePtr())); |
490 | |
491 | case clang::Type::Elaborated: |
492 | return Import(type: CompilerType(type.GetTypeSystem(), |
493 | llvm::cast<clang::ElaboratedType>(Val&: qual_type) |
494 | ->getNamedType() |
495 | .getAsOpaquePtr())); |
496 | |
497 | case clang::Type::Paren: |
498 | return Import(type: CompilerType( |
499 | type.GetTypeSystem(), |
500 | llvm::cast<clang::ParenType>(Val&: qual_type)->desugar().getAsOpaquePtr())); |
501 | |
502 | default: |
503 | break; |
504 | } |
505 | return false; |
506 | } |
507 | |
508 | bool ClangASTImporter::CompleteType(const CompilerType &compiler_type) { |
509 | if (!CanImport(type: compiler_type)) |
510 | return false; |
511 | |
512 | if (Import(type: compiler_type)) { |
513 | TypeSystemClang::CompleteTagDeclarationDefinition(type: compiler_type); |
514 | return true; |
515 | } |
516 | |
517 | TypeSystemClang::SetHasExternalStorage(type: compiler_type.GetOpaqueQualType(), |
518 | has_extern: false); |
519 | return false; |
520 | } |
521 | |
522 | /// Copy layout information from \ref source_map to the \ref destination_map. |
523 | /// |
524 | /// In the process of copying over layout info, we may need to import |
525 | /// decls from the \ref source_map. This function will use the supplied |
526 | /// \ref importer to import the necessary decls into \ref dest_ctx. |
527 | /// |
528 | /// \param[in,out] dest_ctx Destination ASTContext into which we import |
529 | /// decls from the \ref source_map. |
530 | /// \param[out] destination_map A map from decls in \ref dest_ctx to an |
531 | /// integral offest, which will be copies |
532 | /// of the decl/offest pairs in \ref source_map |
533 | /// if successful. |
534 | /// \param[in] source_map A map from decls to integral offests. These will |
535 | /// be copied into \ref destination_map. |
536 | /// \param[in,out] importer Used to import decls into \ref dest_ctx. |
537 | /// |
538 | /// \returns On success, will return 'true' and the offsets in \ref |
539 | /// destination_map |
540 | /// are usable copies of \ref source_map. |
541 | template <class D, class O> |
542 | static bool ImportOffsetMap(clang::ASTContext *dest_ctx, |
543 | llvm::DenseMap<const D *, O> &destination_map, |
544 | llvm::DenseMap<const D *, O> &source_map, |
545 | ClangASTImporter &importer) { |
546 | // When importing fields into a new record, clang has a hard requirement that |
547 | // fields be imported in field offset order. Since they are stored in a |
548 | // DenseMap with a pointer as the key type, this means we cannot simply |
549 | // iterate over the map, as the order will be non-deterministic. Instead we |
550 | // have to sort by the offset and then insert in sorted order. |
551 | typedef llvm::DenseMap<const D *, O> MapType; |
552 | typedef typename MapType::value_type PairType; |
553 | std::vector<PairType> sorted_items; |
554 | sorted_items.reserve(source_map.size()); |
555 | sorted_items.assign(source_map.begin(), source_map.end()); |
556 | llvm::sort(sorted_items, llvm::less_second()); |
557 | |
558 | for (const auto &item : sorted_items) { |
559 | DeclFromUser<D> user_decl(const_cast<D *>(item.first)); |
560 | DeclFromParser<D> parser_decl(user_decl.Import(dest_ctx, importer)); |
561 | if (parser_decl.IsInvalid()) |
562 | return false; |
563 | destination_map.insert( |
564 | std::pair<const D *, O>(parser_decl.decl, item.second)); |
565 | } |
566 | |
567 | return true; |
568 | } |
569 | |
570 | /// Given a CXXRecordDecl, will calculate and populate \ref base_offsets |
571 | /// with the integral offsets of any of its (possibly virtual) base classes. |
572 | /// |
573 | /// \param[in] record_layout ASTRecordLayout of \ref record. |
574 | /// \param[in] record The record that we're calculating the base layouts of. |
575 | /// \param[out] base_offsets Map of base-class decl to integral offset which |
576 | /// this function will fill in. |
577 | /// |
578 | /// \returns On success, will return 'true' and the offsets in \ref base_offsets |
579 | /// are usable. |
580 | template <bool IsVirtual> |
581 | bool (const ASTRecordLayout &record_layout, |
582 | DeclFromUser<const CXXRecordDecl> &record, |
583 | llvm::DenseMap<const clang::CXXRecordDecl *, |
584 | clang::CharUnits> &base_offsets) { |
585 | for (CXXRecordDecl::base_class_const_iterator |
586 | bi = (IsVirtual ? record->vbases_begin() : record->bases_begin()), |
587 | be = (IsVirtual ? record->vbases_end() : record->bases_end()); |
588 | bi != be; ++bi) { |
589 | if (!IsVirtual && bi->isVirtual()) |
590 | continue; |
591 | |
592 | const clang::Type *origin_base_type = bi->getType().getTypePtr(); |
593 | const clang::RecordType *origin_base_record_type = |
594 | origin_base_type->getAs<RecordType>(); |
595 | |
596 | if (!origin_base_record_type) |
597 | return false; |
598 | |
599 | DeclFromUser<RecordDecl> origin_base_record( |
600 | origin_base_record_type->getDecl()); |
601 | |
602 | if (origin_base_record.IsInvalid()) |
603 | return false; |
604 | |
605 | DeclFromUser<CXXRecordDecl> origin_base_cxx_record( |
606 | DynCast<CXXRecordDecl>(source: origin_base_record)); |
607 | |
608 | if (origin_base_cxx_record.IsInvalid()) |
609 | return false; |
610 | |
611 | CharUnits base_offset; |
612 | |
613 | if (IsVirtual) |
614 | base_offset = |
615 | record_layout.getVBaseClassOffset(VBase: origin_base_cxx_record.decl); |
616 | else |
617 | base_offset = |
618 | record_layout.getBaseClassOffset(Base: origin_base_cxx_record.decl); |
619 | |
620 | base_offsets.insert(KV: std::pair<const CXXRecordDecl *, CharUnits>( |
621 | origin_base_cxx_record.decl, base_offset)); |
622 | } |
623 | |
624 | return true; |
625 | } |
626 | |
627 | bool ClangASTImporter::importRecordLayoutFromOrigin( |
628 | const RecordDecl *record, uint64_t &size, uint64_t &alignment, |
629 | llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets, |
630 | llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> |
631 | &base_offsets, |
632 | llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> |
633 | &vbase_offsets) { |
634 | |
635 | Log *log = GetLog(mask: LLDBLog::Expressions); |
636 | |
637 | clang::ASTContext &dest_ctx = record->getASTContext(); |
638 | LLDB_LOG(log, |
639 | "LayoutRecordType on (ASTContext*){0:x} '{1}' for (RecordDecl*)" |
640 | "{2:x} [name = '{3}']" , |
641 | &dest_ctx, |
642 | TypeSystemClang::GetASTContext(&dest_ctx)->getDisplayName(), record, |
643 | record->getName()); |
644 | |
645 | DeclFromParser<const RecordDecl> parser_record(record); |
646 | DeclFromUser<const RecordDecl> origin_record(parser_record.GetOrigin(importer&: *this)); |
647 | |
648 | if (origin_record.IsInvalid()) |
649 | return false; |
650 | |
651 | std::remove_reference_t<decltype(field_offsets)> origin_field_offsets; |
652 | std::remove_reference_t<decltype(base_offsets)> origin_base_offsets; |
653 | std::remove_reference_t<decltype(vbase_offsets)> origin_virtual_base_offsets; |
654 | |
655 | TypeSystemClang::GetCompleteDecl( |
656 | &origin_record->getASTContext(), |
657 | const_cast<RecordDecl *>(origin_record.decl)); |
658 | |
659 | clang::RecordDecl *definition = origin_record.decl->getDefinition(); |
660 | if (!definition || !definition->isCompleteDefinition()) |
661 | return false; |
662 | |
663 | const ASTRecordLayout &record_layout( |
664 | origin_record->getASTContext().getASTRecordLayout(origin_record.decl)); |
665 | |
666 | int field_idx = 0, field_count = record_layout.getFieldCount(); |
667 | |
668 | for (RecordDecl::field_iterator fi = origin_record->field_begin(), |
669 | fe = origin_record->field_end(); |
670 | fi != fe; ++fi) { |
671 | if (field_idx >= field_count) |
672 | return false; // Layout didn't go well. Bail out. |
673 | |
674 | uint64_t field_offset = record_layout.getFieldOffset(FieldNo: field_idx); |
675 | |
676 | origin_field_offsets.insert( |
677 | KV: std::pair<const FieldDecl *, uint64_t>(*fi, field_offset)); |
678 | |
679 | field_idx++; |
680 | } |
681 | |
682 | DeclFromUser<const CXXRecordDecl> origin_cxx_record( |
683 | DynCast<const CXXRecordDecl>(source: origin_record)); |
684 | |
685 | if (origin_cxx_record.IsValid()) { |
686 | if (!ExtractBaseOffsets<false>(record_layout, record&: origin_cxx_record, |
687 | base_offsets&: origin_base_offsets) || |
688 | !ExtractBaseOffsets<true>(record_layout, record&: origin_cxx_record, |
689 | base_offsets&: origin_virtual_base_offsets)) |
690 | return false; |
691 | } |
692 | |
693 | if (!ImportOffsetMap(dest_ctx: &dest_ctx, destination_map&: field_offsets, source_map&: origin_field_offsets, importer&: *this) || |
694 | !ImportOffsetMap(dest_ctx: &dest_ctx, destination_map&: base_offsets, source_map&: origin_base_offsets, importer&: *this) || |
695 | !ImportOffsetMap(dest_ctx: &dest_ctx, destination_map&: vbase_offsets, source_map&: origin_virtual_base_offsets, |
696 | importer&: *this)) |
697 | return false; |
698 | |
699 | size = record_layout.getSize().getQuantity() * dest_ctx.getCharWidth(); |
700 | alignment = |
701 | record_layout.getAlignment().getQuantity() * dest_ctx.getCharWidth(); |
702 | |
703 | if (log) { |
704 | LLDB_LOG(log, "LRT returned:" ); |
705 | LLDB_LOG(log, "LRT Original = (RecordDecl*){0:x}" , |
706 | static_cast<const void *>(origin_record.decl)); |
707 | LLDB_LOG(log, "LRT Size = {0}" , size); |
708 | LLDB_LOG(log, "LRT Alignment = {0}" , alignment); |
709 | LLDB_LOG(log, "LRT Fields:" ); |
710 | for (RecordDecl::field_iterator fi = record->field_begin(), |
711 | fe = record->field_end(); |
712 | fi != fe; ++fi) { |
713 | LLDB_LOG( |
714 | log, |
715 | "LRT (FieldDecl*){0:x}, Name = '{1}', Type = '{2}', Offset = " |
716 | "{3} bits" , |
717 | *fi, fi->getName(), fi->getType().getAsString(), field_offsets[*fi]); |
718 | } |
719 | DeclFromParser<const CXXRecordDecl> parser_cxx_record = |
720 | DynCast<const CXXRecordDecl>(source: parser_record); |
721 | if (parser_cxx_record.IsValid()) { |
722 | LLDB_LOG(log, "LRT Bases:" ); |
723 | for (CXXRecordDecl::base_class_const_iterator |
724 | bi = parser_cxx_record->bases_begin(), |
725 | be = parser_cxx_record->bases_end(); |
726 | bi != be; ++bi) { |
727 | bool is_virtual = bi->isVirtual(); |
728 | |
729 | QualType base_type = bi->getType(); |
730 | const RecordType *base_record_type = base_type->getAs<RecordType>(); |
731 | DeclFromParser<RecordDecl> base_record(base_record_type->getDecl()); |
732 | DeclFromParser<CXXRecordDecl> base_cxx_record = |
733 | DynCast<CXXRecordDecl>(source: base_record); |
734 | |
735 | LLDB_LOG(log, |
736 | "LRT {0}(CXXRecordDecl*){1:x}, Name = '{2}', Offset = " |
737 | "{3} chars" , |
738 | (is_virtual ? "Virtual " : "" ), base_cxx_record.decl, |
739 | base_cxx_record.decl->getName(), |
740 | (is_virtual |
741 | ? vbase_offsets[base_cxx_record.decl].getQuantity() |
742 | : base_offsets[base_cxx_record.decl].getQuantity())); |
743 | } |
744 | } else { |
745 | LLDB_LOG(log, "LRD Not a CXXRecord, so no bases" ); |
746 | } |
747 | } |
748 | |
749 | return true; |
750 | } |
751 | |
752 | bool ClangASTImporter::LayoutRecordType( |
753 | const clang::RecordDecl *record_decl, uint64_t &bit_size, |
754 | uint64_t &alignment, |
755 | llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets, |
756 | llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> |
757 | &base_offsets, |
758 | llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> |
759 | &vbase_offsets) { |
760 | RecordDeclToLayoutMap::iterator pos = |
761 | m_record_decl_to_layout_map.find(Val: record_decl); |
762 | base_offsets.clear(); |
763 | vbase_offsets.clear(); |
764 | if (pos != m_record_decl_to_layout_map.end()) { |
765 | bit_size = pos->second.bit_size; |
766 | alignment = pos->second.alignment; |
767 | field_offsets.swap(RHS&: pos->second.field_offsets); |
768 | base_offsets.swap(RHS&: pos->second.base_offsets); |
769 | vbase_offsets.swap(RHS&: pos->second.vbase_offsets); |
770 | m_record_decl_to_layout_map.erase(I: pos); |
771 | return true; |
772 | } |
773 | |
774 | // It's possible that we calculated the layout in a different |
775 | // ClangASTImporter instance. Try to import such layout if |
776 | // our decl has an origin. |
777 | if (auto origin = GetDeclOrigin(record_decl); origin.Valid()) |
778 | if (importRecordLayoutFromOrigin(record: record_decl, size&: bit_size, alignment, |
779 | field_offsets, base_offsets, |
780 | vbase_offsets)) |
781 | return true; |
782 | |
783 | bit_size = 0; |
784 | alignment = 0; |
785 | field_offsets.clear(); |
786 | |
787 | return false; |
788 | } |
789 | |
790 | void ClangASTImporter::SetRecordLayout(clang::RecordDecl *decl, |
791 | const LayoutInfo &layout) { |
792 | m_record_decl_to_layout_map.insert(KV: std::make_pair(x&: decl, y: layout)); |
793 | } |
794 | |
795 | bool ClangASTImporter::CompleteTagDecl(clang::TagDecl *decl) { |
796 | DeclOrigin decl_origin = GetDeclOrigin(decl); |
797 | |
798 | if (!decl_origin.Valid()) |
799 | return false; |
800 | |
801 | if (!TypeSystemClang::GetCompleteDecl(ast: decl_origin.ctx, decl: decl_origin.decl)) |
802 | return false; |
803 | |
804 | ImporterDelegateSP delegate_sp( |
805 | GetDelegate(dst_ctx: &decl->getASTContext(), src_ctx: decl_origin.ctx)); |
806 | |
807 | ASTImporterDelegate::CxxModuleScope std_scope(*delegate_sp, |
808 | &decl->getASTContext()); |
809 | if (delegate_sp) |
810 | delegate_sp->ImportDefinitionTo(decl, decl_origin.decl); |
811 | |
812 | return true; |
813 | } |
814 | |
815 | bool ClangASTImporter::CompleteTagDeclWithOrigin(clang::TagDecl *decl, |
816 | clang::TagDecl *origin_decl) { |
817 | clang::ASTContext *origin_ast_ctx = &origin_decl->getASTContext(); |
818 | |
819 | if (!TypeSystemClang::GetCompleteDecl(origin_ast_ctx, origin_decl)) |
820 | return false; |
821 | |
822 | ImporterDelegateSP delegate_sp( |
823 | GetDelegate(dst_ctx: &decl->getASTContext(), src_ctx: origin_ast_ctx)); |
824 | |
825 | if (delegate_sp) |
826 | delegate_sp->ImportDefinitionTo(decl, origin_decl); |
827 | |
828 | ASTContextMetadataSP context_md = GetContextMetadata(dst_ctx: &decl->getASTContext()); |
829 | |
830 | context_md->setOrigin(decl, DeclOrigin(origin_ast_ctx, origin_decl)); |
831 | return true; |
832 | } |
833 | |
834 | bool ClangASTImporter::CompleteObjCInterfaceDecl( |
835 | clang::ObjCInterfaceDecl *interface_decl) { |
836 | DeclOrigin decl_origin = GetDeclOrigin(interface_decl); |
837 | |
838 | if (!decl_origin.Valid()) |
839 | return false; |
840 | |
841 | if (!TypeSystemClang::GetCompleteDecl(ast: decl_origin.ctx, decl: decl_origin.decl)) |
842 | return false; |
843 | |
844 | ImporterDelegateSP delegate_sp( |
845 | GetDelegate(dst_ctx: &interface_decl->getASTContext(), src_ctx: decl_origin.ctx)); |
846 | |
847 | if (delegate_sp) |
848 | delegate_sp->ImportDefinitionTo(interface_decl, decl_origin.decl); |
849 | |
850 | if (ObjCInterfaceDecl *super_class = interface_decl->getSuperClass()) |
851 | RequireCompleteType(type: clang::QualType(super_class->getTypeForDecl(), 0)); |
852 | |
853 | return true; |
854 | } |
855 | |
856 | bool ClangASTImporter::CompleteAndFetchChildren(clang::QualType type) { |
857 | if (!RequireCompleteType(type)) |
858 | return false; |
859 | |
860 | Log *log = GetLog(mask: LLDBLog::Expressions); |
861 | |
862 | if (const TagType *tag_type = type->getAs<TagType>()) { |
863 | TagDecl *tag_decl = tag_type->getDecl(); |
864 | |
865 | DeclOrigin decl_origin = GetDeclOrigin(tag_decl); |
866 | |
867 | if (!decl_origin.Valid()) |
868 | return false; |
869 | |
870 | ImporterDelegateSP delegate_sp( |
871 | GetDelegate(dst_ctx: &tag_decl->getASTContext(), src_ctx: decl_origin.ctx)); |
872 | |
873 | ASTImporterDelegate::CxxModuleScope std_scope(*delegate_sp, |
874 | &tag_decl->getASTContext()); |
875 | |
876 | TagDecl *origin_tag_decl = llvm::dyn_cast<TagDecl>(Val: decl_origin.decl); |
877 | |
878 | for (Decl *origin_child_decl : origin_tag_decl->decls()) { |
879 | llvm::Expected<Decl *> imported_or_err = |
880 | delegate_sp->Import(origin_child_decl); |
881 | if (!imported_or_err) { |
882 | LLDB_LOG_ERROR(log, imported_or_err.takeError(), |
883 | "Couldn't import decl: {0}" ); |
884 | return false; |
885 | } |
886 | } |
887 | |
888 | if (RecordDecl *record_decl = dyn_cast<RecordDecl>(Val: origin_tag_decl)) |
889 | record_decl->setHasLoadedFieldsFromExternalStorage(true); |
890 | |
891 | return true; |
892 | } |
893 | |
894 | if (const ObjCObjectType *objc_object_type = type->getAs<ObjCObjectType>()) { |
895 | if (ObjCInterfaceDecl *objc_interface_decl = |
896 | objc_object_type->getInterface()) { |
897 | DeclOrigin decl_origin = GetDeclOrigin(objc_interface_decl); |
898 | |
899 | if (!decl_origin.Valid()) |
900 | return false; |
901 | |
902 | ImporterDelegateSP delegate_sp( |
903 | GetDelegate(dst_ctx: &objc_interface_decl->getASTContext(), src_ctx: decl_origin.ctx)); |
904 | |
905 | ObjCInterfaceDecl *origin_interface_decl = |
906 | llvm::dyn_cast<ObjCInterfaceDecl>(Val: decl_origin.decl); |
907 | |
908 | for (Decl *origin_child_decl : origin_interface_decl->decls()) { |
909 | llvm::Expected<Decl *> imported_or_err = |
910 | delegate_sp->Import(origin_child_decl); |
911 | if (!imported_or_err) { |
912 | LLDB_LOG_ERROR(log, imported_or_err.takeError(), |
913 | "Couldn't import decl: {0}" ); |
914 | return false; |
915 | } |
916 | } |
917 | |
918 | return true; |
919 | } |
920 | return false; |
921 | } |
922 | |
923 | return true; |
924 | } |
925 | |
926 | bool ClangASTImporter::RequireCompleteType(clang::QualType type) { |
927 | if (type.isNull()) |
928 | return false; |
929 | |
930 | if (const TagType *tag_type = type->getAs<TagType>()) { |
931 | TagDecl *tag_decl = tag_type->getDecl(); |
932 | |
933 | if (tag_decl->getDefinition() || tag_decl->isBeingDefined()) |
934 | return true; |
935 | |
936 | return CompleteTagDecl(decl: tag_decl); |
937 | } |
938 | if (const ObjCObjectType *objc_object_type = type->getAs<ObjCObjectType>()) { |
939 | if (ObjCInterfaceDecl *objc_interface_decl = |
940 | objc_object_type->getInterface()) |
941 | return CompleteObjCInterfaceDecl(interface_decl: objc_interface_decl); |
942 | return false; |
943 | } |
944 | if (const ArrayType *array_type = type->getAsArrayTypeUnsafe()) |
945 | return RequireCompleteType(type: array_type->getElementType()); |
946 | if (const AtomicType *atomic_type = type->getAs<AtomicType>()) |
947 | return RequireCompleteType(type: atomic_type->getPointeeType()); |
948 | |
949 | return true; |
950 | } |
951 | |
952 | std::optional<ClangASTMetadata> |
953 | ClangASTImporter::GetDeclMetadata(const clang::Decl *decl) { |
954 | DeclOrigin decl_origin = GetDeclOrigin(decl); |
955 | |
956 | if (decl_origin.Valid()) { |
957 | TypeSystemClang *ast = TypeSystemClang::GetASTContext(ast_ctx: decl_origin.ctx); |
958 | return ast->GetMetadata(object: decl_origin.decl); |
959 | } |
960 | TypeSystemClang *ast = TypeSystemClang::GetASTContext(ast_ctx: &decl->getASTContext()); |
961 | return ast->GetMetadata(object: decl); |
962 | } |
963 | |
964 | ClangASTImporter::DeclOrigin |
965 | ClangASTImporter::GetDeclOrigin(const clang::Decl *decl) { |
966 | ASTContextMetadataSP context_md = GetContextMetadata(dst_ctx: &decl->getASTContext()); |
967 | |
968 | return context_md->getOrigin(decl); |
969 | } |
970 | |
971 | void ClangASTImporter::SetDeclOrigin(const clang::Decl *decl, |
972 | clang::Decl *original_decl) { |
973 | ASTContextMetadataSP context_md = GetContextMetadata(dst_ctx: &decl->getASTContext()); |
974 | context_md->setOrigin( |
975 | decl, origin: DeclOrigin(&original_decl->getASTContext(), original_decl)); |
976 | } |
977 | |
978 | void ClangASTImporter::RegisterNamespaceMap(const clang::NamespaceDecl *decl, |
979 | NamespaceMapSP &namespace_map) { |
980 | ASTContextMetadataSP context_md = GetContextMetadata(dst_ctx: &decl->getASTContext()); |
981 | |
982 | context_md->m_namespace_maps[decl] = namespace_map; |
983 | } |
984 | |
985 | ClangASTImporter::NamespaceMapSP |
986 | ClangASTImporter::GetNamespaceMap(const clang::NamespaceDecl *decl) { |
987 | ASTContextMetadataSP context_md = GetContextMetadata(dst_ctx: &decl->getASTContext()); |
988 | |
989 | NamespaceMetaMap &namespace_maps = context_md->m_namespace_maps; |
990 | |
991 | NamespaceMetaMap::iterator iter = namespace_maps.find(Val: decl); |
992 | |
993 | if (iter != namespace_maps.end()) |
994 | return iter->second; |
995 | return NamespaceMapSP(); |
996 | } |
997 | |
998 | void ClangASTImporter::BuildNamespaceMap(const clang::NamespaceDecl *decl) { |
999 | assert(decl); |
1000 | ASTContextMetadataSP context_md = GetContextMetadata(dst_ctx: &decl->getASTContext()); |
1001 | |
1002 | const DeclContext *parent_context = decl->getDeclContext(); |
1003 | const NamespaceDecl *parent_namespace = |
1004 | dyn_cast<NamespaceDecl>(Val: parent_context); |
1005 | NamespaceMapSP parent_map; |
1006 | |
1007 | if (parent_namespace) |
1008 | parent_map = GetNamespaceMap(decl: parent_namespace); |
1009 | |
1010 | NamespaceMapSP new_map; |
1011 | |
1012 | new_map = std::make_shared<NamespaceMap>(); |
1013 | |
1014 | if (context_md->m_map_completer) { |
1015 | std::string namespace_string = decl->getDeclName().getAsString(); |
1016 | |
1017 | context_md->m_map_completer->CompleteNamespaceMap( |
1018 | namespace_map&: new_map, name: ConstString(namespace_string.c_str()), parent_map); |
1019 | } |
1020 | |
1021 | context_md->m_namespace_maps[decl] = new_map; |
1022 | } |
1023 | |
1024 | void ClangASTImporter::ForgetDestination(clang::ASTContext *dst_ast) { |
1025 | Log *log = GetLog(mask: LLDBLog::Expressions); |
1026 | |
1027 | LLDB_LOG(log, |
1028 | " [ClangASTImporter] Forgetting destination (ASTContext*){0:x}" , |
1029 | dst_ast); |
1030 | |
1031 | m_metadata_map.erase(Val: dst_ast); |
1032 | } |
1033 | |
1034 | void ClangASTImporter::ForgetSource(clang::ASTContext *dst_ast, |
1035 | clang::ASTContext *src_ast) { |
1036 | ASTContextMetadataSP md = MaybeGetContextMetadata(dst_ctx: dst_ast); |
1037 | |
1038 | Log *log = GetLog(mask: LLDBLog::Expressions); |
1039 | |
1040 | LLDB_LOG(log, |
1041 | " [ClangASTImporter] Forgetting source->dest " |
1042 | "(ASTContext*){0:x}->(ASTContext*){1:x}" , |
1043 | src_ast, dst_ast); |
1044 | |
1045 | if (!md) |
1046 | return; |
1047 | |
1048 | md->m_delegates.erase(Val: src_ast); |
1049 | md->removeOriginsWithContext(ctx: src_ast); |
1050 | } |
1051 | |
1052 | ClangASTImporter::MapCompleter::~MapCompleter() = default; |
1053 | |
1054 | llvm::Expected<Decl *> |
1055 | ClangASTImporter::ASTImporterDelegate::ImportImpl(Decl *From) { |
1056 | if (m_std_handler) { |
1057 | std::optional<Decl *> D = m_std_handler->Import(d: From); |
1058 | if (D) { |
1059 | // Make sure we don't use this decl later to map it back to it's original |
1060 | // decl. The decl the CxxModuleHandler created has nothing to do with |
1061 | // the one from debug info, and linking those two would just cause the |
1062 | // ASTImporter to try 'updating' the module decl with the minimal one from |
1063 | // the debug info. |
1064 | m_decls_to_ignore.insert(Ptr: *D); |
1065 | return *D; |
1066 | } |
1067 | } |
1068 | |
1069 | // Check which ASTContext this declaration originally came from. |
1070 | DeclOrigin origin = m_main.GetDeclOrigin(decl: From); |
1071 | |
1072 | // Prevent infinite recursion when the origin tracking contains a cycle. |
1073 | assert(origin.decl != From && "Origin points to itself?" ); |
1074 | |
1075 | // If it originally came from the target ASTContext then we can just |
1076 | // pretend that the original is the one we imported. This can happen for |
1077 | // example when inspecting a persistent declaration from the scratch |
1078 | // ASTContext (which will provide the declaration when parsing the |
1079 | // expression and then we later try to copy the declaration back to the |
1080 | // scratch ASTContext to store the result). |
1081 | // Without this check we would ask the ASTImporter to import a declaration |
1082 | // into the same ASTContext where it came from (which doesn't make a lot of |
1083 | // sense). |
1084 | if (origin.Valid() && origin.ctx == &getToContext()) { |
1085 | RegisterImportedDecl(FromD: From, ToD: origin.decl); |
1086 | return origin.decl; |
1087 | } |
1088 | |
1089 | // This declaration came originally from another ASTContext. Instead of |
1090 | // copying our potentially incomplete 'From' Decl we instead go to the |
1091 | // original ASTContext and copy the original to the target. This is not |
1092 | // only faster than first completing our current decl and then copying it |
1093 | // to the target, but it also prevents that indirectly copying the same |
1094 | // declaration to the same target requires the ASTImporter to merge all |
1095 | // the different decls that appear to come from different ASTContexts (even |
1096 | // though all these different source ASTContexts just got a copy from |
1097 | // one source AST). |
1098 | if (origin.Valid()) { |
1099 | auto R = m_main.CopyDecl(dst_ast: &getToContext(), decl: origin.decl); |
1100 | if (R) { |
1101 | RegisterImportedDecl(FromD: From, ToD: R); |
1102 | return R; |
1103 | } |
1104 | } |
1105 | |
1106 | // If we have a forcefully completed type, try to find an actual definition |
1107 | // for it in other modules. |
1108 | std::optional<ClangASTMetadata> md = m_main.GetDeclMetadata(decl: From); |
1109 | auto *td = dyn_cast<TagDecl>(Val: From); |
1110 | if (td && md && md->IsForcefullyCompleted()) { |
1111 | Log *log = GetLog(mask: LLDBLog::Expressions); |
1112 | LLDB_LOG(log, |
1113 | "[ClangASTImporter] Searching for a complete definition of {0} in " |
1114 | "other modules" , |
1115 | td->getName()); |
1116 | Expected<DeclContext *> dc_or_err = ImportContext(FromDC: td->getDeclContext()); |
1117 | if (!dc_or_err) |
1118 | return dc_or_err.takeError(); |
1119 | Expected<DeclarationName> dn_or_err = Import(td->getDeclName()); |
1120 | if (!dn_or_err) |
1121 | return dn_or_err.takeError(); |
1122 | DeclContext *dc = *dc_or_err; |
1123 | DeclContext::lookup_result lr = dc->lookup(Name: *dn_or_err); |
1124 | for (clang::Decl *candidate : lr) { |
1125 | if (candidate->getKind() == From->getKind()) { |
1126 | RegisterImportedDecl(From, candidate); |
1127 | m_decls_to_ignore.insert(candidate); |
1128 | return candidate; |
1129 | } |
1130 | } |
1131 | LLDB_LOG(log, "[ClangASTImporter] Complete definition not found" ); |
1132 | } |
1133 | |
1134 | return ASTImporter::ImportImpl(From); |
1135 | } |
1136 | |
1137 | void ClangASTImporter::ASTImporterDelegate::ImportDefinitionTo( |
1138 | clang::Decl *to, clang::Decl *from) { |
1139 | Log *log = GetLog(mask: LLDBLog::Expressions); |
1140 | |
1141 | auto getDeclName = [](Decl const *decl) { |
1142 | std::string name_string; |
1143 | if (auto const *from_named_decl = dyn_cast<clang::NamedDecl>(Val: decl)) { |
1144 | llvm::raw_string_ostream name_stream(name_string); |
1145 | from_named_decl->printName(OS&: name_stream); |
1146 | } |
1147 | |
1148 | return name_string; |
1149 | }; |
1150 | |
1151 | if (log) { |
1152 | if (auto *D = GetAlreadyImportedOrNull(FromD: from); D && D != to) { |
1153 | LLDB_LOG( |
1154 | log, |
1155 | "[ClangASTImporter] ERROR: overwriting an already imported decl " |
1156 | "'{0:x}' ('{1}') from '{2:x}' with '{3:x}'. Likely due to a name " |
1157 | "conflict when importing '{1}'." , |
1158 | D, getDeclName(from), from, to); |
1159 | } |
1160 | } |
1161 | |
1162 | // We might have a forward declaration from a shared library that we |
1163 | // gave external lexical storage so that Clang asks us about the full |
1164 | // definition when it needs it. In this case the ASTImporter isn't aware |
1165 | // that the forward decl from the shared library is the actual import |
1166 | // target but would create a second declaration that would then be defined. |
1167 | // We want that 'to' is actually complete after this function so let's |
1168 | // tell the ASTImporter that 'to' was imported from 'from'. |
1169 | MapImported(From: from, To: to); |
1170 | |
1171 | if (llvm::Error err = ImportDefinition(From: from)) { |
1172 | LLDB_LOG_ERROR(log, std::move(err), |
1173 | "[ClangASTImporter] Error during importing definition: {0}" ); |
1174 | return; |
1175 | } |
1176 | |
1177 | if (clang::TagDecl *to_tag = dyn_cast<clang::TagDecl>(Val: to)) { |
1178 | if (clang::TagDecl *from_tag = dyn_cast<clang::TagDecl>(Val: from)) { |
1179 | to_tag->setCompleteDefinition(from_tag->isCompleteDefinition()); |
1180 | |
1181 | if (Log *log_ast = GetLog(mask: LLDBLog::AST)) { |
1182 | LLDB_LOG(log_ast, |
1183 | "==== [ClangASTImporter][TUDecl: {0:x}] Imported " |
1184 | "({1}Decl*){2:x}, named {3} (from " |
1185 | "(Decl*){4:x})" , |
1186 | static_cast<void *>(to->getTranslationUnitDecl()), |
1187 | from->getDeclKindName(), static_cast<void *>(to), |
1188 | getDeclName(from), static_cast<void *>(from)); |
1189 | |
1190 | // Log the AST of the TU. |
1191 | std::string ast_string; |
1192 | llvm::raw_string_ostream ast_stream(ast_string); |
1193 | to->getTranslationUnitDecl()->dump(ast_stream); |
1194 | LLDB_LOG(log_ast, "{0}" , ast_string); |
1195 | } |
1196 | } |
1197 | } |
1198 | |
1199 | // If we're dealing with an Objective-C class, ensure that the inheritance |
1200 | // has been set up correctly. The ASTImporter may not do this correctly if |
1201 | // the class was originally sourced from symbols. |
1202 | |
1203 | if (ObjCInterfaceDecl *to_objc_interface = dyn_cast<ObjCInterfaceDecl>(Val: to)) { |
1204 | ObjCInterfaceDecl *to_superclass = to_objc_interface->getSuperClass(); |
1205 | |
1206 | if (to_superclass) |
1207 | return; // we're not going to override it if it's set |
1208 | |
1209 | ObjCInterfaceDecl *from_objc_interface = dyn_cast<ObjCInterfaceDecl>(Val: from); |
1210 | |
1211 | if (!from_objc_interface) |
1212 | return; |
1213 | |
1214 | ObjCInterfaceDecl *from_superclass = from_objc_interface->getSuperClass(); |
1215 | |
1216 | if (!from_superclass) |
1217 | return; |
1218 | |
1219 | llvm::Expected<Decl *> imported_from_superclass_decl = |
1220 | Import(from_superclass); |
1221 | |
1222 | if (!imported_from_superclass_decl) { |
1223 | LLDB_LOG_ERROR(log, imported_from_superclass_decl.takeError(), |
1224 | "Couldn't import decl: {0}" ); |
1225 | return; |
1226 | } |
1227 | |
1228 | ObjCInterfaceDecl *imported_from_superclass = |
1229 | dyn_cast<ObjCInterfaceDecl>(Val: *imported_from_superclass_decl); |
1230 | |
1231 | if (!imported_from_superclass) |
1232 | return; |
1233 | |
1234 | if (!to_objc_interface->hasDefinition()) |
1235 | to_objc_interface->startDefinition(); |
1236 | |
1237 | to_objc_interface->setSuperClass(m_source_ctx->getTrivialTypeSourceInfo( |
1238 | T: m_source_ctx->getObjCInterfaceType(Decl: imported_from_superclass))); |
1239 | } |
1240 | } |
1241 | |
1242 | /// Takes a CXXMethodDecl and completes the return type if necessary. This |
1243 | /// is currently only necessary for virtual functions with covariant return |
1244 | /// types where Clang's CodeGen expects that the underlying records are already |
1245 | /// completed. |
1246 | static void MaybeCompleteReturnType(ClangASTImporter &importer, |
1247 | CXXMethodDecl *to_method) { |
1248 | if (!to_method->isVirtual()) |
1249 | return; |
1250 | QualType return_type = to_method->getReturnType(); |
1251 | if (!return_type->isPointerType() && !return_type->isReferenceType()) |
1252 | return; |
1253 | |
1254 | clang::RecordDecl *rd = return_type->getPointeeType()->getAsRecordDecl(); |
1255 | if (!rd) |
1256 | return; |
1257 | if (rd->getDefinition()) |
1258 | return; |
1259 | |
1260 | importer.CompleteTagDecl(rd); |
1261 | } |
1262 | |
1263 | /// Recreate a module with its parents in \p to_source and return its id. |
1264 | static OptionalClangModuleID |
1265 | RemapModule(OptionalClangModuleID from_id, |
1266 | ClangExternalASTSourceCallbacks &from_source, |
1267 | ClangExternalASTSourceCallbacks &to_source) { |
1268 | if (!from_id.HasValue()) |
1269 | return {}; |
1270 | clang::Module *module = from_source.getModule(ID: from_id.GetValue()); |
1271 | OptionalClangModuleID parent = RemapModule( |
1272 | from_id: from_source.GetIDForModule(module: module->Parent), from_source, to_source); |
1273 | TypeSystemClang &to_ts = to_source.GetTypeSystem(); |
1274 | return to_ts.GetOrCreateClangModule(name: module->Name, parent, is_framework: module->IsFramework, |
1275 | is_explicit: module->IsExplicit); |
1276 | } |
1277 | |
1278 | void ClangASTImporter::ASTImporterDelegate::Imported(clang::Decl *from, |
1279 | clang::Decl *to) { |
1280 | Log *log = GetLog(mask: LLDBLog::Expressions); |
1281 | |
1282 | // Some decls shouldn't be tracked here because they were not created by |
1283 | // copying 'from' to 'to'. Just exit early for those. |
1284 | if (m_decls_to_ignore.count(Ptr: to)) |
1285 | return; |
1286 | |
1287 | // Transfer module ownership information. |
1288 | auto *from_source = llvm::dyn_cast_or_null<ClangExternalASTSourceCallbacks>( |
1289 | Val: getFromContext().getExternalSource()); |
1290 | // Can also be a ClangASTSourceProxy. |
1291 | auto *to_source = llvm::dyn_cast_or_null<ClangExternalASTSourceCallbacks>( |
1292 | Val: getToContext().getExternalSource()); |
1293 | if (from_source && to_source) { |
1294 | OptionalClangModuleID from_id(from->getOwningModuleID()); |
1295 | OptionalClangModuleID to_id = |
1296 | RemapModule(from_id, from_source&: *from_source, to_source&: *to_source); |
1297 | TypeSystemClang &to_ts = to_source->GetTypeSystem(); |
1298 | to_ts.SetOwningModule(decl: to, owning_module: to_id); |
1299 | } |
1300 | |
1301 | lldb::user_id_t user_id = LLDB_INVALID_UID; |
1302 | if (std::optional<ClangASTMetadata> metadata = m_main.GetDeclMetadata(decl: from)) |
1303 | user_id = metadata->GetUserID(); |
1304 | |
1305 | if (log) { |
1306 | if (NamedDecl *from_named_decl = dyn_cast<clang::NamedDecl>(Val: from)) { |
1307 | std::string name_string; |
1308 | llvm::raw_string_ostream name_stream(name_string); |
1309 | from_named_decl->printName(OS&: name_stream); |
1310 | |
1311 | LLDB_LOG( |
1312 | log, |
1313 | " [ClangASTImporter] Imported ({0}Decl*){1:x}, named {2} (from " |
1314 | "(Decl*){3:x}), metadata {4}" , |
1315 | from->getDeclKindName(), to, name_string, from, user_id); |
1316 | } else { |
1317 | LLDB_LOG(log, |
1318 | " [ClangASTImporter] Imported ({0}Decl*){1:x} (from " |
1319 | "(Decl*){2:x}), metadata {3}" , |
1320 | from->getDeclKindName(), to, from, user_id); |
1321 | } |
1322 | } |
1323 | |
1324 | ASTContextMetadataSP to_context_md = |
1325 | m_main.GetContextMetadata(dst_ctx: &to->getASTContext()); |
1326 | ASTContextMetadataSP from_context_md = |
1327 | m_main.MaybeGetContextMetadata(dst_ctx: m_source_ctx); |
1328 | |
1329 | if (from_context_md) { |
1330 | DeclOrigin origin = from_context_md->getOrigin(decl: from); |
1331 | |
1332 | if (origin.Valid()) { |
1333 | if (origin.ctx != &to->getASTContext()) { |
1334 | if (!to_context_md->hasOrigin(decl: to) || user_id != LLDB_INVALID_UID) |
1335 | to_context_md->setOrigin(decl: to, origin); |
1336 | |
1337 | LLDB_LOG(log, |
1338 | " [ClangASTImporter] Propagated origin " |
1339 | "(Decl*){0:x}/(ASTContext*){1:x} from (ASTContext*){2:x} to " |
1340 | "(ASTContext*){3:x}" , |
1341 | origin.decl, origin.ctx, &from->getASTContext(), |
1342 | &to->getASTContext()); |
1343 | } |
1344 | } else { |
1345 | if (m_new_decl_listener) |
1346 | m_new_decl_listener->NewDeclImported(from, to); |
1347 | |
1348 | if (!to_context_md->hasOrigin(decl: to) || user_id != LLDB_INVALID_UID) |
1349 | to_context_md->setOrigin(decl: to, origin: DeclOrigin(m_source_ctx, from)); |
1350 | |
1351 | LLDB_LOG(log, |
1352 | " [ClangASTImporter] Decl has no origin information in " |
1353 | "(ASTContext*){0:x}" , |
1354 | &from->getASTContext()); |
1355 | } |
1356 | |
1357 | if (auto *to_namespace = dyn_cast<clang::NamespaceDecl>(Val: to)) { |
1358 | auto *from_namespace = cast<clang::NamespaceDecl>(Val: from); |
1359 | |
1360 | NamespaceMetaMap &namespace_maps = from_context_md->m_namespace_maps; |
1361 | |
1362 | NamespaceMetaMap::iterator namespace_map_iter = |
1363 | namespace_maps.find(Val: from_namespace); |
1364 | |
1365 | if (namespace_map_iter != namespace_maps.end()) |
1366 | to_context_md->m_namespace_maps[to_namespace] = |
1367 | namespace_map_iter->second; |
1368 | } |
1369 | } else { |
1370 | to_context_md->setOrigin(decl: to, origin: DeclOrigin(m_source_ctx, from)); |
1371 | |
1372 | LLDB_LOG(log, |
1373 | " [ClangASTImporter] Sourced origin " |
1374 | "(Decl*){0:x}/(ASTContext*){1:x} into (ASTContext*){2:x}" , |
1375 | from, m_source_ctx, &to->getASTContext()); |
1376 | } |
1377 | |
1378 | if (auto *to_tag_decl = dyn_cast<TagDecl>(Val: to)) { |
1379 | to_tag_decl->setHasExternalLexicalStorage(); |
1380 | to_tag_decl->getPrimaryContext()->setMustBuildLookupTable(); |
1381 | auto from_tag_decl = cast<TagDecl>(Val: from); |
1382 | |
1383 | LLDB_LOG( |
1384 | log, |
1385 | " [ClangASTImporter] To is a TagDecl - attributes {0}{1} [{2}->{3}]" , |
1386 | (to_tag_decl->hasExternalLexicalStorage() ? " Lexical" : "" ), |
1387 | (to_tag_decl->hasExternalVisibleStorage() ? " Visible" : "" ), |
1388 | (from_tag_decl->isCompleteDefinition() ? "complete" : "incomplete" ), |
1389 | (to_tag_decl->isCompleteDefinition() ? "complete" : "incomplete" )); |
1390 | } |
1391 | |
1392 | if (auto *to_namespace_decl = dyn_cast<NamespaceDecl>(Val: to)) { |
1393 | m_main.BuildNamespaceMap(decl: to_namespace_decl); |
1394 | to_namespace_decl->setHasExternalVisibleStorage(); |
1395 | } |
1396 | |
1397 | if (auto *to_container_decl = dyn_cast<ObjCContainerDecl>(Val: to)) { |
1398 | to_container_decl->setHasExternalLexicalStorage(); |
1399 | to_container_decl->setHasExternalVisibleStorage(); |
1400 | |
1401 | if (log) { |
1402 | if (ObjCInterfaceDecl *to_interface_decl = |
1403 | llvm::dyn_cast<ObjCInterfaceDecl>(Val: to_container_decl)) { |
1404 | LLDB_LOG( |
1405 | log, |
1406 | " [ClangASTImporter] To is an ObjCInterfaceDecl - attributes " |
1407 | "{0}{1}{2}" , |
1408 | (to_interface_decl->hasExternalLexicalStorage() ? " Lexical" : "" ), |
1409 | (to_interface_decl->hasExternalVisibleStorage() ? " Visible" : "" ), |
1410 | (to_interface_decl->hasDefinition() ? " HasDefinition" : "" )); |
1411 | } else { |
1412 | LLDB_LOG( |
1413 | log, " [ClangASTImporter] To is an {0}Decl - attributes {1}{2}" , |
1414 | ((Decl *)to_container_decl)->getDeclKindName(), |
1415 | (to_container_decl->hasExternalLexicalStorage() ? " Lexical" : "" ), |
1416 | (to_container_decl->hasExternalVisibleStorage() ? " Visible" : "" )); |
1417 | } |
1418 | } |
1419 | } |
1420 | |
1421 | if (clang::CXXMethodDecl *to_method = dyn_cast<CXXMethodDecl>(Val: to)) |
1422 | MaybeCompleteReturnType(importer&: m_main, to_method); |
1423 | } |
1424 | |
1425 | clang::Decl * |
1426 | ClangASTImporter::ASTImporterDelegate::GetOriginalDecl(clang::Decl *To) { |
1427 | return m_main.GetDeclOrigin(decl: To).decl; |
1428 | } |
1429 | |