1 //===-- AppleObjCDeclVendor.cpp ---------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "AppleObjCDeclVendor.h"
12 #include "Plugins/ExpressionParser/Clang/ASTDumper.h"
13 #include "lldb/Core/Module.h"
14 #include "lldb/Symbol/ClangExternalASTSourceCommon.h"
15 #include "lldb/Symbol/ClangUtil.h"
16 #include "lldb/Target/ObjCLanguageRuntime.h"
17 #include "lldb/Target/Process.h"
18 #include "lldb/Target/Target.h"
19 #include "lldb/Utility/Log.h"
21 #include "clang/AST/ASTContext.h"
22 #include "clang/AST/DeclObjC.h"
24 using namespace lldb_private;
26 class lldb_private::AppleObjCExternalASTSource
27 : public ClangExternalASTSourceCommon {
29 AppleObjCExternalASTSource(AppleObjCDeclVendor &decl_vendor)
30 : m_decl_vendor(decl_vendor) {}
32 bool FindExternalVisibleDeclsByName(const clang::DeclContext *decl_ctx,
33 clang::DeclarationName name) override {
34 static unsigned int invocation_id = 0;
35 unsigned int current_id = invocation_id++;
37 Log *log(GetLogIfAllCategoriesSet(
38 LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel?
41 log->Printf("AppleObjCExternalASTSource::FindExternalVisibleDeclsByName[%"
42 "u] on (ASTContext*)%p Looking for %s in (%sDecl*)%p",
44 static_cast<void *>(&decl_ctx->getParentASTContext()),
45 name.getAsString().c_str(), decl_ctx->getDeclKindName(),
46 static_cast<const void *>(decl_ctx));
50 const clang::ObjCInterfaceDecl *interface_decl =
51 llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl_ctx);
56 clang::ObjCInterfaceDecl *non_const_interface_decl =
57 const_cast<clang::ObjCInterfaceDecl *>(interface_decl);
59 if (!m_decl_vendor.FinishDecl(non_const_interface_decl))
62 clang::DeclContext::lookup_result result =
63 non_const_interface_decl->lookup(name);
65 return (result.size() != 0);
68 SetNoExternalVisibleDeclsForName(decl_ctx, name);
72 void CompleteType(clang::TagDecl *tag_decl) override {
73 static unsigned int invocation_id = 0;
74 unsigned int current_id = invocation_id++;
76 Log *log(GetLogIfAllCategoriesSet(
77 LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel?
80 log->Printf("AppleObjCExternalASTSource::CompleteType[%u] on "
81 "(ASTContext*)%p Completing (TagDecl*)%p named %s",
82 current_id, static_cast<void *>(&tag_decl->getASTContext()),
83 static_cast<void *>(tag_decl),
84 tag_decl->getName().str().c_str());
86 log->Printf(" AOEAS::CT[%u] Before:", current_id);
87 ASTDumper dumper((clang::Decl *)tag_decl);
88 dumper.ToLog(log, " [CT] ");
92 log->Printf(" AOEAS::CT[%u] After:", current_id);
93 ASTDumper dumper((clang::Decl *)tag_decl);
94 dumper.ToLog(log, " [CT] ");
99 void CompleteType(clang::ObjCInterfaceDecl *interface_decl) override {
100 static unsigned int invocation_id = 0;
101 unsigned int current_id = invocation_id++;
103 Log *log(GetLogIfAllCategoriesSet(
104 LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel?
107 log->Printf("AppleObjCExternalASTSource::CompleteType[%u] on "
108 "(ASTContext*)%p Completing (ObjCInterfaceDecl*)%p named %s",
110 static_cast<void *>(&interface_decl->getASTContext()),
111 static_cast<void *>(interface_decl),
112 interface_decl->getName().str().c_str());
114 log->Printf(" AOEAS::CT[%u] Before:", current_id);
115 ASTDumper dumper((clang::Decl *)interface_decl);
116 dumper.ToLog(log, " [CT] ");
119 m_decl_vendor.FinishDecl(interface_decl);
122 log->Printf(" [CT] After:");
123 ASTDumper dumper((clang::Decl *)interface_decl);
124 dumper.ToLog(log, " [CT] ");
129 bool layoutRecordType(
130 const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,
131 llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets,
132 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
134 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
135 &VirtualBaseOffsets) override {
139 void StartTranslationUnit(clang::ASTConsumer *Consumer) override {
140 clang::TranslationUnitDecl *translation_unit_decl =
141 m_decl_vendor.m_ast_ctx.getASTContext()->getTranslationUnitDecl();
142 translation_unit_decl->setHasExternalVisibleStorage();
143 translation_unit_decl->setHasExternalLexicalStorage();
147 AppleObjCDeclVendor &m_decl_vendor;
150 AppleObjCDeclVendor::AppleObjCDeclVendor(ObjCLanguageRuntime &runtime)
151 : DeclVendor(), m_runtime(runtime), m_ast_ctx(runtime.GetProcess()
157 m_type_realizer_sp(m_runtime.GetEncodingToType()) {
158 m_external_source = new AppleObjCExternalASTSource(*this);
159 llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> external_source_owning_ptr(
161 m_ast_ctx.getASTContext()->setExternalSource(external_source_owning_ptr);
164 clang::ObjCInterfaceDecl *
165 AppleObjCDeclVendor::GetDeclForISA(ObjCLanguageRuntime::ObjCISA isa) {
166 ISAToInterfaceMap::const_iterator iter = m_isa_to_interface.find(isa);
168 if (iter != m_isa_to_interface.end())
171 clang::ASTContext *ast_ctx = m_ast_ctx.getASTContext();
173 ObjCLanguageRuntime::ClassDescriptorSP descriptor =
174 m_runtime.GetClassDescriptorFromISA(isa);
179 const ConstString &name(descriptor->GetClassName());
181 clang::IdentifierInfo &identifier_info =
182 ast_ctx->Idents.get(name.GetStringRef());
184 clang::ObjCInterfaceDecl *new_iface_decl = clang::ObjCInterfaceDecl::Create(
185 *ast_ctx, ast_ctx->getTranslationUnitDecl(), clang::SourceLocation(),
186 &identifier_info, nullptr, nullptr);
188 ClangASTMetadata meta_data;
189 meta_data.SetISAPtr(isa);
190 m_external_source->SetMetadata(new_iface_decl, meta_data);
192 new_iface_decl->setHasExternalVisibleStorage();
193 new_iface_decl->setHasExternalLexicalStorage();
195 ast_ctx->getTranslationUnitDecl()->addDecl(new_iface_decl);
197 m_isa_to_interface[isa] = new_iface_decl;
199 return new_iface_decl;
202 class ObjCRuntimeMethodType {
204 ObjCRuntimeMethodType(const char *types) : m_is_valid(false) {
205 const char *cursor = types;
206 enum ParserState { Start = 0, InType, InPos } state = Start;
207 const char *type = NULL;
210 uint32_t stepsLeft = 256;
213 if (--stepsLeft == 0) {
260 m_type_vector.push_back(std::string(type, (cursor - type)));
318 clang::ObjCMethodDecl *
319 BuildMethod(clang::ObjCInterfaceDecl *interface_decl, const char *name,
321 ObjCLanguageRuntime::EncodingToTypeSP type_realizer_sp) {
322 if (!m_is_valid || m_type_vector.size() < 3)
325 clang::ASTContext &ast_ctx(interface_decl->getASTContext());
327 const bool isInstance = instance;
328 const bool isVariadic = false;
329 const bool isSynthesized = false;
330 const bool isImplicitlyDeclared = true;
331 const bool isDefined = false;
332 const clang::ObjCMethodDecl::ImplementationControl impControl =
333 clang::ObjCMethodDecl::None;
334 const bool HasRelatedResultType = false;
335 const bool for_expression = true;
337 std::vector<clang::IdentifierInfo *> selector_components;
339 const char *name_cursor = name;
340 bool is_zero_argument = true;
342 while (*name_cursor != '\0') {
343 const char *colon_loc = strchr(name_cursor, ':');
345 selector_components.push_back(
346 &ast_ctx.Idents.get(llvm::StringRef(name_cursor)));
349 is_zero_argument = false;
350 selector_components.push_back(&ast_ctx.Idents.get(
351 llvm::StringRef(name_cursor, colon_loc - name_cursor)));
352 name_cursor = colon_loc + 1;
356 clang::IdentifierInfo **identifier_infos = selector_components.data();
357 if (!identifier_infos) {
361 clang::Selector sel = ast_ctx.Selectors.getSelector(
362 is_zero_argument ? 0 : selector_components.size(),
365 clang::QualType ret_type =
366 ClangUtil::GetQualType(type_realizer_sp->RealizeType(
367 interface_decl->getASTContext(), m_type_vector[0].c_str(),
370 if (ret_type.isNull())
373 clang::ObjCMethodDecl *ret = clang::ObjCMethodDecl::Create(
374 ast_ctx, clang::SourceLocation(), clang::SourceLocation(), sel,
375 ret_type, NULL, interface_decl, isInstance, isVariadic, isSynthesized,
376 isImplicitlyDeclared, isDefined, impControl, HasRelatedResultType);
378 std::vector<clang::ParmVarDecl *> parm_vars;
380 for (size_t ai = 3, ae = m_type_vector.size(); ai != ae; ++ai) {
381 const bool for_expression = true;
382 clang::QualType arg_type =
383 ClangUtil::GetQualType(type_realizer_sp->RealizeType(
384 ast_ctx, m_type_vector[ai].c_str(), for_expression));
386 if (arg_type.isNull())
387 return NULL; // well, we just wasted a bunch of time. Wish we could
388 // delete the stuff we'd just made!
390 parm_vars.push_back(clang::ParmVarDecl::Create(
391 ast_ctx, ret, clang::SourceLocation(), clang::SourceLocation(), NULL,
392 arg_type, NULL, clang::SC_None, NULL));
395 ret->setMethodParams(ast_ctx,
396 llvm::ArrayRef<clang::ParmVarDecl *>(parm_vars),
397 llvm::ArrayRef<clang::SourceLocation>());
402 explicit operator bool() { return m_is_valid; }
404 size_t GetNumTypes() { return m_type_vector.size(); }
406 const char *GetTypeAtIndex(size_t idx) { return m_type_vector[idx].c_str(); }
409 typedef std::vector<std::string> TypeVector;
411 TypeVector m_type_vector;
415 bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) {
416 Log *log(GetLogIfAllCategoriesSet(
417 LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel?
419 ClangASTMetadata *metadata = m_external_source->GetMetadata(interface_decl);
420 ObjCLanguageRuntime::ObjCISA objc_isa = 0;
422 objc_isa = metadata->GetISAPtr();
427 if (!interface_decl->hasExternalVisibleStorage())
430 interface_decl->startDefinition();
432 interface_decl->setHasExternalVisibleStorage(false);
433 interface_decl->setHasExternalLexicalStorage(false);
435 ObjCLanguageRuntime::ClassDescriptorSP descriptor =
436 m_runtime.GetClassDescriptorFromISA(objc_isa);
441 auto superclass_func = [interface_decl,
442 this](ObjCLanguageRuntime::ObjCISA isa) {
443 clang::ObjCInterfaceDecl *superclass_decl = GetDeclForISA(isa);
445 if (!superclass_decl)
448 FinishDecl(superclass_decl);
449 clang::ASTContext *context = m_ast_ctx.getASTContext();
450 interface_decl->setSuperClass(context->getTrivialTypeSourceInfo(
451 context->getObjCInterfaceType(superclass_decl)));
454 auto instance_method_func =
455 [log, interface_decl, this](const char *name, const char *types) -> bool {
457 return false; // skip this one
459 ObjCRuntimeMethodType method_type(types);
461 clang::ObjCMethodDecl *method_decl =
462 method_type.BuildMethod(interface_decl, name, true, m_type_realizer_sp);
465 log->Printf("[ AOTV::FD] Instance method [%s] [%s]", name, types);
468 interface_decl->addDecl(method_decl);
473 auto class_method_func = [log, interface_decl,
474 this](const char *name, const char *types) -> bool {
476 return false; // skip this one
478 ObjCRuntimeMethodType method_type(types);
480 clang::ObjCMethodDecl *method_decl = method_type.BuildMethod(
481 interface_decl, name, false, m_type_realizer_sp);
484 log->Printf("[ AOTV::FD] Class method [%s] [%s]", name, types);
487 interface_decl->addDecl(method_decl);
492 auto ivar_func = [log, interface_decl,
493 this](const char *name, const char *type,
494 lldb::addr_t offset_ptr, uint64_t size) -> bool {
498 const bool for_expression = false;
502 "[ AOTV::FD] Instance variable [%s] [%s], offset at %" PRIx64, name,
505 CompilerType ivar_type = m_runtime.GetEncodingToType()->RealizeType(
506 m_ast_ctx, type, for_expression);
508 if (ivar_type.IsValid()) {
509 clang::TypeSourceInfo *const type_source_info = nullptr;
510 const bool is_synthesized = false;
511 clang::ObjCIvarDecl *ivar_decl = clang::ObjCIvarDecl::Create(
512 *m_ast_ctx.getASTContext(), interface_decl, clang::SourceLocation(),
513 clang::SourceLocation(), &m_ast_ctx.getASTContext()->Idents.get(name),
514 ClangUtil::GetQualType(ivar_type),
515 type_source_info, // TypeSourceInfo *
516 clang::ObjCIvarDecl::Public, 0, is_synthesized);
519 interface_decl->addDecl(ivar_decl);
527 ASTDumper method_dumper((clang::Decl *)interface_decl);
529 log->Printf("[AppleObjCDeclVendor::FinishDecl] Finishing Objective-C "
531 descriptor->GetClassName().AsCString());
534 if (!descriptor->Describe(superclass_func, instance_method_func,
535 class_method_func, ivar_func))
539 ASTDumper method_dumper((clang::Decl *)interface_decl);
542 "[AppleObjCDeclVendor::FinishDecl] Finished Objective-C interface");
544 method_dumper.ToLog(log, " [AOTV::FD] ");
551 AppleObjCDeclVendor::FindDecls(const ConstString &name, bool append,
552 uint32_t max_matches,
553 std::vector<clang::NamedDecl *> &decls) {
554 static unsigned int invocation_id = 0;
555 unsigned int current_id = invocation_id++;
557 Log *log(GetLogIfAllCategoriesSet(
558 LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel?
561 log->Printf("AppleObjCDeclVendor::FindTypes [%u] ('%s', %s, %u, )",
562 current_id, (const char *)name.AsCString(),
563 append ? "true" : "false", max_matches);
571 // See if the type is already in our ASTContext.
573 clang::ASTContext *ast_ctx = m_ast_ctx.getASTContext();
575 clang::IdentifierInfo &identifier_info =
576 ast_ctx->Idents.get(name.GetStringRef());
577 clang::DeclarationName decl_name =
578 ast_ctx->DeclarationNames.getIdentifier(&identifier_info);
580 clang::DeclContext::lookup_result lookup_result =
581 ast_ctx->getTranslationUnitDecl()->lookup(decl_name);
583 if (!lookup_result.empty()) {
584 if (clang::ObjCInterfaceDecl *result_iface_decl =
585 llvm::dyn_cast<clang::ObjCInterfaceDecl>(lookup_result[0])) {
587 clang::QualType result_iface_type =
588 ast_ctx->getObjCInterfaceType(result_iface_decl);
589 ASTDumper dumper(result_iface_type);
591 uint64_t isa_value = LLDB_INVALID_ADDRESS;
592 ClangASTMetadata *metadata =
593 m_external_source->GetMetadata(result_iface_decl);
595 isa_value = metadata->GetISAPtr();
597 log->Printf("AOCTV::FT [%u] Found %s (isa 0x%" PRIx64
598 ") in the ASTContext",
599 current_id, dumper.GetCString(), isa_value);
602 decls.push_back(result_iface_decl);
607 log->Printf("AOCTV::FT [%u] There's something in the ASTContext, but "
608 "it's not something we know about",
613 log->Printf("AOCTV::FT [%u] Couldn't find %s in the ASTContext",
614 current_id, name.AsCString());
617 // It's not. If it exists, we have to put it into our ASTContext.
619 ObjCLanguageRuntime::ObjCISA isa = m_runtime.GetISA(name);
623 log->Printf("AOCTV::FT [%u] Couldn't find the isa", current_id);
628 clang::ObjCInterfaceDecl *iface_decl = GetDeclForISA(isa);
632 log->Printf("AOCTV::FT [%u] Couldn't get the Objective-C interface for "
634 current_id, (uint64_t)isa);
640 clang::QualType new_iface_type =
641 ast_ctx->getObjCInterfaceType(iface_decl);
642 ASTDumper dumper(new_iface_type);
643 log->Printf("AOCTV::FT [%u] Created %s (isa 0x%" PRIx64 ")", current_id,
644 dumper.GetCString(), (uint64_t)isa);
647 decls.push_back(iface_decl);
655 clang::ExternalASTMerger::ImporterSource
656 AppleObjCDeclVendor::GetImporterSource() {
657 return {*m_ast_ctx.getASTContext(),
658 *m_ast_ctx.getFileManager(),
659 m_ast_ctx.GetOriginMap()