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