15ffd83dbSDimitry Andric //===-- AppleObjCDeclVendor.cpp -------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "AppleObjCDeclVendor.h"
100b57cec5SDimitry Andric 
115ffd83dbSDimitry Andric #include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h"
125ffd83dbSDimitry Andric #include "Plugins/ExpressionParser/Clang/ClangUtil.h"
130b57cec5SDimitry Andric #include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"
140b57cec5SDimitry Andric #include "lldb/Core/Module.h"
150b57cec5SDimitry Andric #include "lldb/Target/Process.h"
160b57cec5SDimitry Andric #include "lldb/Target/Target.h"
1781ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
180b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
210b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h"
22480093f4SDimitry Andric #include "clang/AST/ExternalASTSource.h"
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric using namespace lldb_private;
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric class lldb_private::AppleObjCExternalASTSource
27480093f4SDimitry Andric     : public clang::ExternalASTSource {
280b57cec5SDimitry Andric public:
290b57cec5SDimitry Andric   AppleObjCExternalASTSource(AppleObjCDeclVendor &decl_vendor)
300b57cec5SDimitry Andric       : m_decl_vendor(decl_vendor) {}
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric   bool FindExternalVisibleDeclsByName(const clang::DeclContext *decl_ctx,
330b57cec5SDimitry Andric                                       clang::DeclarationName name) override {
340b57cec5SDimitry Andric 
3581ad6265SDimitry Andric     Log *log(GetLog(
3681ad6265SDimitry Andric         LLDBLog::Expressions)); // FIXME - a more appropriate log channel?
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric     if (log) {
399dba64beSDimitry Andric       LLDB_LOGF(log,
405ffd83dbSDimitry Andric                 "AppleObjCExternalASTSource::FindExternalVisibleDeclsByName"
415ffd83dbSDimitry Andric                 " on (ASTContext*)%p Looking for %s in (%sDecl*)%p",
420b57cec5SDimitry Andric                 static_cast<void *>(&decl_ctx->getParentASTContext()),
430b57cec5SDimitry Andric                 name.getAsString().c_str(), decl_ctx->getDeclKindName(),
440b57cec5SDimitry Andric                 static_cast<const void *>(decl_ctx));
450b57cec5SDimitry Andric     }
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric     do {
480b57cec5SDimitry Andric       const clang::ObjCInterfaceDecl *interface_decl =
490b57cec5SDimitry Andric           llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl_ctx);
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric       if (!interface_decl)
520b57cec5SDimitry Andric         break;
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric       clang::ObjCInterfaceDecl *non_const_interface_decl =
550b57cec5SDimitry Andric           const_cast<clang::ObjCInterfaceDecl *>(interface_decl);
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric       if (!m_decl_vendor.FinishDecl(non_const_interface_decl))
580b57cec5SDimitry Andric         break;
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric       clang::DeclContext::lookup_result result =
610b57cec5SDimitry Andric           non_const_interface_decl->lookup(name);
620b57cec5SDimitry Andric 
63fe6060f1SDimitry Andric       return (!result.empty());
640b57cec5SDimitry Andric     } while (false);
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric     SetNoExternalVisibleDeclsForName(decl_ctx, name);
670b57cec5SDimitry Andric     return false;
680b57cec5SDimitry Andric   }
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric   void CompleteType(clang::TagDecl *tag_decl) override {
710b57cec5SDimitry Andric 
7281ad6265SDimitry Andric     Log *log(GetLog(
7381ad6265SDimitry Andric         LLDBLog::Expressions)); // FIXME - a more appropriate log channel?
740b57cec5SDimitry Andric 
759dba64beSDimitry Andric     LLDB_LOGF(log,
765ffd83dbSDimitry Andric               "AppleObjCExternalASTSource::CompleteType on "
770b57cec5SDimitry Andric               "(ASTContext*)%p Completing (TagDecl*)%p named %s",
785ffd83dbSDimitry Andric               static_cast<void *>(&tag_decl->getASTContext()),
79480093f4SDimitry Andric               static_cast<void *>(tag_decl), tag_decl->getName().str().c_str());
800b57cec5SDimitry Andric 
815ffd83dbSDimitry Andric     LLDB_LOG(log, "  AOEAS::CT Before:\n{1}", ClangUtil::DumpDecl(tag_decl));
820b57cec5SDimitry Andric 
835ffd83dbSDimitry Andric     LLDB_LOG(log, "  AOEAS::CT After:{1}", ClangUtil::DumpDecl(tag_decl));
840b57cec5SDimitry Andric   }
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   void CompleteType(clang::ObjCInterfaceDecl *interface_decl) override {
870b57cec5SDimitry Andric 
8881ad6265SDimitry Andric     Log *log(GetLog(
8981ad6265SDimitry Andric         LLDBLog::Expressions)); // FIXME - a more appropriate log channel?
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric     if (log) {
929dba64beSDimitry Andric       LLDB_LOGF(log,
935ffd83dbSDimitry Andric                 "AppleObjCExternalASTSource::CompleteType on "
940b57cec5SDimitry Andric                 "(ASTContext*)%p Completing (ObjCInterfaceDecl*)%p named %s",
950b57cec5SDimitry Andric                 static_cast<void *>(&interface_decl->getASTContext()),
960b57cec5SDimitry Andric                 static_cast<void *>(interface_decl),
970b57cec5SDimitry Andric                 interface_decl->getName().str().c_str());
980b57cec5SDimitry Andric 
995ffd83dbSDimitry Andric       LLDB_LOGF(log, "  AOEAS::CT Before:");
100480093f4SDimitry Andric       LLDB_LOG(log, "    [CT] {0}", ClangUtil::DumpDecl(interface_decl));
1010b57cec5SDimitry Andric     }
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric     m_decl_vendor.FinishDecl(interface_decl);
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric     if (log) {
1069dba64beSDimitry Andric       LLDB_LOGF(log, "  [CT] After:");
107480093f4SDimitry Andric       LLDB_LOG(log, "    [CT] {0}", ClangUtil::DumpDecl(interface_decl));
1080b57cec5SDimitry Andric     }
1090b57cec5SDimitry Andric   }
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric   bool layoutRecordType(
1120b57cec5SDimitry Andric       const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,
1130b57cec5SDimitry Andric       llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets,
1140b57cec5SDimitry Andric       llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
1150b57cec5SDimitry Andric           &BaseOffsets,
1160b57cec5SDimitry Andric       llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
1170b57cec5SDimitry Andric           &VirtualBaseOffsets) override {
1180b57cec5SDimitry Andric     return false;
1190b57cec5SDimitry Andric   }
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric   void StartTranslationUnit(clang::ASTConsumer *Consumer) override {
1220b57cec5SDimitry Andric     clang::TranslationUnitDecl *translation_unit_decl =
123bdd1243dSDimitry Andric         m_decl_vendor.m_ast_ctx->getASTContext().getTranslationUnitDecl();
1240b57cec5SDimitry Andric     translation_unit_decl->setHasExternalVisibleStorage();
1250b57cec5SDimitry Andric     translation_unit_decl->setHasExternalLexicalStorage();
1260b57cec5SDimitry Andric   }
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric private:
1290b57cec5SDimitry Andric   AppleObjCDeclVendor &m_decl_vendor;
1300b57cec5SDimitry Andric };
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric AppleObjCDeclVendor::AppleObjCDeclVendor(ObjCLanguageRuntime &runtime)
1339dba64beSDimitry Andric     : ClangDeclVendor(eAppleObjCDeclVendor), m_runtime(runtime),
1340b57cec5SDimitry Andric       m_type_realizer_sp(m_runtime.GetEncodingToType()) {
135bdd1243dSDimitry Andric   m_ast_ctx = std::make_shared<TypeSystemClang>(
136bdd1243dSDimitry Andric       "AppleObjCDeclVendor AST",
137bdd1243dSDimitry Andric       runtime.GetProcess()->GetTarget().GetArchitecture().GetTriple());
1380b57cec5SDimitry Andric   m_external_source = new AppleObjCExternalASTSource(*this);
1390b57cec5SDimitry Andric   llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> external_source_owning_ptr(
1400b57cec5SDimitry Andric       m_external_source);
141bdd1243dSDimitry Andric   m_ast_ctx->getASTContext().setExternalSource(external_source_owning_ptr);
1420b57cec5SDimitry Andric }
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric clang::ObjCInterfaceDecl *
1450b57cec5SDimitry Andric AppleObjCDeclVendor::GetDeclForISA(ObjCLanguageRuntime::ObjCISA isa) {
1460b57cec5SDimitry Andric   ISAToInterfaceMap::const_iterator iter = m_isa_to_interface.find(isa);
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric   if (iter != m_isa_to_interface.end())
1490b57cec5SDimitry Andric     return iter->second;
1500b57cec5SDimitry Andric 
151bdd1243dSDimitry Andric   clang::ASTContext &ast_ctx = m_ast_ctx->getASTContext();
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric   ObjCLanguageRuntime::ClassDescriptorSP descriptor =
1540b57cec5SDimitry Andric       m_runtime.GetClassDescriptorFromISA(isa);
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric   if (!descriptor)
1570b57cec5SDimitry Andric     return nullptr;
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric   ConstString name(descriptor->GetClassName());
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric   clang::IdentifierInfo &identifier_info =
162480093f4SDimitry Andric       ast_ctx.Idents.get(name.GetStringRef());
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric   clang::ObjCInterfaceDecl *new_iface_decl = clang::ObjCInterfaceDecl::Create(
165480093f4SDimitry Andric       ast_ctx, ast_ctx.getTranslationUnitDecl(), clang::SourceLocation(),
1660b57cec5SDimitry Andric       &identifier_info, nullptr, nullptr);
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   ClangASTMetadata meta_data;
1690b57cec5SDimitry Andric   meta_data.SetISAPtr(isa);
170bdd1243dSDimitry Andric   m_ast_ctx->SetMetadata(new_iface_decl, meta_data);
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric   new_iface_decl->setHasExternalVisibleStorage();
1730b57cec5SDimitry Andric   new_iface_decl->setHasExternalLexicalStorage();
1740b57cec5SDimitry Andric 
175480093f4SDimitry Andric   ast_ctx.getTranslationUnitDecl()->addDecl(new_iface_decl);
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric   m_isa_to_interface[isa] = new_iface_decl;
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric   return new_iface_decl;
1800b57cec5SDimitry Andric }
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric class ObjCRuntimeMethodType {
1830b57cec5SDimitry Andric public:
18481ad6265SDimitry Andric   ObjCRuntimeMethodType(const char *types) {
1850b57cec5SDimitry Andric     const char *cursor = types;
1860b57cec5SDimitry Andric     enum ParserState { Start = 0, InType, InPos } state = Start;
1870b57cec5SDimitry Andric     const char *type = nullptr;
1880b57cec5SDimitry Andric     int brace_depth = 0;
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric     uint32_t stepsLeft = 256;
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric     while (true) {
1930b57cec5SDimitry Andric       if (--stepsLeft == 0) {
1940b57cec5SDimitry Andric         m_is_valid = false;
1950b57cec5SDimitry Andric         return;
1960b57cec5SDimitry Andric       }
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric       switch (state) {
1990b57cec5SDimitry Andric       case Start: {
2000b57cec5SDimitry Andric         switch (*cursor) {
2010b57cec5SDimitry Andric         default:
2020b57cec5SDimitry Andric           state = InType;
2030b57cec5SDimitry Andric           type = cursor;
2040b57cec5SDimitry Andric           break;
2050b57cec5SDimitry Andric         case '\0':
2060b57cec5SDimitry Andric           m_is_valid = true;
2070b57cec5SDimitry Andric           return;
2080b57cec5SDimitry Andric         case '0':
2090b57cec5SDimitry Andric         case '1':
2100b57cec5SDimitry Andric         case '2':
2110b57cec5SDimitry Andric         case '3':
2120b57cec5SDimitry Andric         case '4':
2130b57cec5SDimitry Andric         case '5':
2140b57cec5SDimitry Andric         case '6':
2150b57cec5SDimitry Andric         case '7':
2160b57cec5SDimitry Andric         case '8':
2170b57cec5SDimitry Andric         case '9':
2180b57cec5SDimitry Andric           m_is_valid = false;
2190b57cec5SDimitry Andric           return;
2200b57cec5SDimitry Andric         }
2210b57cec5SDimitry Andric       } break;
2220b57cec5SDimitry Andric       case InType: {
2230b57cec5SDimitry Andric         switch (*cursor) {
2240b57cec5SDimitry Andric         default:
2250b57cec5SDimitry Andric           ++cursor;
2260b57cec5SDimitry Andric           break;
2270b57cec5SDimitry Andric         case '0':
2280b57cec5SDimitry Andric         case '1':
2290b57cec5SDimitry Andric         case '2':
2300b57cec5SDimitry Andric         case '3':
2310b57cec5SDimitry Andric         case '4':
2320b57cec5SDimitry Andric         case '5':
2330b57cec5SDimitry Andric         case '6':
2340b57cec5SDimitry Andric         case '7':
2350b57cec5SDimitry Andric         case '8':
2360b57cec5SDimitry Andric         case '9':
2370b57cec5SDimitry Andric           if (!brace_depth) {
2380b57cec5SDimitry Andric             state = InPos;
2390b57cec5SDimitry Andric             if (type) {
2400b57cec5SDimitry Andric               m_type_vector.push_back(std::string(type, (cursor - type)));
2410b57cec5SDimitry Andric             } else {
2420b57cec5SDimitry Andric               m_is_valid = false;
2430b57cec5SDimitry Andric               return;
2440b57cec5SDimitry Andric             }
2450b57cec5SDimitry Andric             type = nullptr;
2460b57cec5SDimitry Andric           } else {
2470b57cec5SDimitry Andric             ++cursor;
2480b57cec5SDimitry Andric           }
2490b57cec5SDimitry Andric           break;
2500b57cec5SDimitry Andric         case '[':
2510b57cec5SDimitry Andric         case '{':
2520b57cec5SDimitry Andric         case '(':
2530b57cec5SDimitry Andric           ++brace_depth;
2540b57cec5SDimitry Andric           ++cursor;
2550b57cec5SDimitry Andric           break;
2560b57cec5SDimitry Andric         case ']':
2570b57cec5SDimitry Andric         case '}':
2580b57cec5SDimitry Andric         case ')':
2590b57cec5SDimitry Andric           if (!brace_depth) {
2600b57cec5SDimitry Andric             m_is_valid = false;
2610b57cec5SDimitry Andric             return;
2620b57cec5SDimitry Andric           }
2630b57cec5SDimitry Andric           --brace_depth;
2640b57cec5SDimitry Andric           ++cursor;
2650b57cec5SDimitry Andric           break;
2660b57cec5SDimitry Andric         case '\0':
2670b57cec5SDimitry Andric           m_is_valid = false;
2680b57cec5SDimitry Andric           return;
2690b57cec5SDimitry Andric         }
2700b57cec5SDimitry Andric       } break;
2710b57cec5SDimitry Andric       case InPos: {
2720b57cec5SDimitry Andric         switch (*cursor) {
2730b57cec5SDimitry Andric         default:
2740b57cec5SDimitry Andric           state = InType;
2750b57cec5SDimitry Andric           type = cursor;
2760b57cec5SDimitry Andric           break;
2770b57cec5SDimitry Andric         case '0':
2780b57cec5SDimitry Andric         case '1':
2790b57cec5SDimitry Andric         case '2':
2800b57cec5SDimitry Andric         case '3':
2810b57cec5SDimitry Andric         case '4':
2820b57cec5SDimitry Andric         case '5':
2830b57cec5SDimitry Andric         case '6':
2840b57cec5SDimitry Andric         case '7':
2850b57cec5SDimitry Andric         case '8':
2860b57cec5SDimitry Andric         case '9':
2870b57cec5SDimitry Andric           ++cursor;
2880b57cec5SDimitry Andric           break;
2890b57cec5SDimitry Andric         case '\0':
2900b57cec5SDimitry Andric           m_is_valid = true;
2910b57cec5SDimitry Andric           return;
2920b57cec5SDimitry Andric         }
2930b57cec5SDimitry Andric       } break;
2940b57cec5SDimitry Andric       }
2950b57cec5SDimitry Andric     }
2960b57cec5SDimitry Andric   }
2970b57cec5SDimitry Andric 
2980b57cec5SDimitry Andric   clang::ObjCMethodDecl *
2995ffd83dbSDimitry Andric   BuildMethod(TypeSystemClang &clang_ast_ctxt,
300480093f4SDimitry Andric               clang::ObjCInterfaceDecl *interface_decl, const char *name,
3010b57cec5SDimitry Andric               bool instance,
3020b57cec5SDimitry Andric               ObjCLanguageRuntime::EncodingToTypeSP type_realizer_sp) {
3030b57cec5SDimitry Andric     if (!m_is_valid || m_type_vector.size() < 3)
3040b57cec5SDimitry Andric       return nullptr;
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric     clang::ASTContext &ast_ctx(interface_decl->getASTContext());
3070b57cec5SDimitry Andric 
3080b57cec5SDimitry Andric     const bool isInstance = instance;
3090b57cec5SDimitry Andric     const bool isVariadic = false;
310480093f4SDimitry Andric     const bool isPropertyAccessor = false;
311480093f4SDimitry Andric     const bool isSynthesizedAccessorStub = false;
3120b57cec5SDimitry Andric     const bool isImplicitlyDeclared = true;
3130b57cec5SDimitry Andric     const bool isDefined = false;
3145f757f3fSDimitry Andric     const clang::ObjCImplementationControl impControl =
3155f757f3fSDimitry Andric         clang::ObjCImplementationControl::None;
3160b57cec5SDimitry Andric     const bool HasRelatedResultType = false;
3170b57cec5SDimitry Andric     const bool for_expression = true;
3180b57cec5SDimitry Andric 
319*0fca6ea1SDimitry Andric     std::vector<const clang::IdentifierInfo *> selector_components;
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric     const char *name_cursor = name;
3220b57cec5SDimitry Andric     bool is_zero_argument = true;
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric     while (*name_cursor != '\0') {
3250b57cec5SDimitry Andric       const char *colon_loc = strchr(name_cursor, ':');
3260b57cec5SDimitry Andric       if (!colon_loc) {
3270b57cec5SDimitry Andric         selector_components.push_back(
3280b57cec5SDimitry Andric             &ast_ctx.Idents.get(llvm::StringRef(name_cursor)));
3290b57cec5SDimitry Andric         break;
3300b57cec5SDimitry Andric       } else {
3310b57cec5SDimitry Andric         is_zero_argument = false;
3320b57cec5SDimitry Andric         selector_components.push_back(&ast_ctx.Idents.get(
3330b57cec5SDimitry Andric             llvm::StringRef(name_cursor, colon_loc - name_cursor)));
3340b57cec5SDimitry Andric         name_cursor = colon_loc + 1;
3350b57cec5SDimitry Andric       }
3360b57cec5SDimitry Andric     }
3370b57cec5SDimitry Andric 
338*0fca6ea1SDimitry Andric     const clang::IdentifierInfo **identifier_infos = selector_components.data();
3390b57cec5SDimitry Andric     if (!identifier_infos) {
3400b57cec5SDimitry Andric       return nullptr;
3410b57cec5SDimitry Andric     }
3420b57cec5SDimitry Andric 
3430b57cec5SDimitry Andric     clang::Selector sel = ast_ctx.Selectors.getSelector(
3440b57cec5SDimitry Andric         is_zero_argument ? 0 : selector_components.size(),
3450b57cec5SDimitry Andric         identifier_infos);
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric     clang::QualType ret_type =
3480b57cec5SDimitry Andric         ClangUtil::GetQualType(type_realizer_sp->RealizeType(
349480093f4SDimitry Andric             clang_ast_ctxt, m_type_vector[0].c_str(), for_expression));
3500b57cec5SDimitry Andric 
3510b57cec5SDimitry Andric     if (ret_type.isNull())
3520b57cec5SDimitry Andric       return nullptr;
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric     clang::ObjCMethodDecl *ret = clang::ObjCMethodDecl::Create(
3550b57cec5SDimitry Andric         ast_ctx, clang::SourceLocation(), clang::SourceLocation(), sel,
3560b57cec5SDimitry Andric         ret_type, nullptr, interface_decl, isInstance, isVariadic,
357480093f4SDimitry Andric         isPropertyAccessor, isSynthesizedAccessorStub, isImplicitlyDeclared,
358480093f4SDimitry Andric         isDefined, impControl, HasRelatedResultType);
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric     std::vector<clang::ParmVarDecl *> parm_vars;
3610b57cec5SDimitry Andric 
3620b57cec5SDimitry Andric     for (size_t ai = 3, ae = m_type_vector.size(); ai != ae; ++ai) {
3630b57cec5SDimitry Andric       const bool for_expression = true;
3640b57cec5SDimitry Andric       clang::QualType arg_type =
3650b57cec5SDimitry Andric           ClangUtil::GetQualType(type_realizer_sp->RealizeType(
366480093f4SDimitry Andric               clang_ast_ctxt, m_type_vector[ai].c_str(), for_expression));
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric       if (arg_type.isNull())
3690b57cec5SDimitry Andric         return nullptr; // well, we just wasted a bunch of time.  Wish we could
3700b57cec5SDimitry Andric                         // delete the stuff we'd just made!
3710b57cec5SDimitry Andric 
3720b57cec5SDimitry Andric       parm_vars.push_back(clang::ParmVarDecl::Create(
3730b57cec5SDimitry Andric           ast_ctx, ret, clang::SourceLocation(), clang::SourceLocation(),
3740b57cec5SDimitry Andric           nullptr, arg_type, nullptr, clang::SC_None, nullptr));
3750b57cec5SDimitry Andric     }
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric     ret->setMethodParams(ast_ctx,
3780b57cec5SDimitry Andric                          llvm::ArrayRef<clang::ParmVarDecl *>(parm_vars),
3790b57cec5SDimitry Andric                          llvm::ArrayRef<clang::SourceLocation>());
3800b57cec5SDimitry Andric 
3810b57cec5SDimitry Andric     return ret;
3820b57cec5SDimitry Andric   }
3830b57cec5SDimitry Andric 
3840b57cec5SDimitry Andric   explicit operator bool() { return m_is_valid; }
3850b57cec5SDimitry Andric 
3860b57cec5SDimitry Andric   size_t GetNumTypes() { return m_type_vector.size(); }
3870b57cec5SDimitry Andric 
3880b57cec5SDimitry Andric   const char *GetTypeAtIndex(size_t idx) { return m_type_vector[idx].c_str(); }
3890b57cec5SDimitry Andric 
3900b57cec5SDimitry Andric private:
3910b57cec5SDimitry Andric   typedef std::vector<std::string> TypeVector;
3920b57cec5SDimitry Andric 
3930b57cec5SDimitry Andric   TypeVector m_type_vector;
39481ad6265SDimitry Andric   bool m_is_valid = false;
3950b57cec5SDimitry Andric };
3960b57cec5SDimitry Andric 
3970b57cec5SDimitry Andric bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) {
39881ad6265SDimitry Andric   Log *log(
39981ad6265SDimitry Andric       GetLog(LLDBLog::Expressions)); // FIXME - a more appropriate log channel?
4000b57cec5SDimitry Andric 
401bdd1243dSDimitry Andric   ClangASTMetadata *metadata = m_ast_ctx->GetMetadata(interface_decl);
4020b57cec5SDimitry Andric   ObjCLanguageRuntime::ObjCISA objc_isa = 0;
4030b57cec5SDimitry Andric   if (metadata)
4040b57cec5SDimitry Andric     objc_isa = metadata->GetISAPtr();
4050b57cec5SDimitry Andric 
4060b57cec5SDimitry Andric   if (!objc_isa)
4070b57cec5SDimitry Andric     return false;
4080b57cec5SDimitry Andric 
4090b57cec5SDimitry Andric   if (!interface_decl->hasExternalVisibleStorage())
4100b57cec5SDimitry Andric     return true;
4110b57cec5SDimitry Andric 
4120b57cec5SDimitry Andric   interface_decl->startDefinition();
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric   interface_decl->setHasExternalVisibleStorage(false);
4150b57cec5SDimitry Andric   interface_decl->setHasExternalLexicalStorage(false);
4160b57cec5SDimitry Andric 
4170b57cec5SDimitry Andric   ObjCLanguageRuntime::ClassDescriptorSP descriptor =
4180b57cec5SDimitry Andric       m_runtime.GetClassDescriptorFromISA(objc_isa);
4190b57cec5SDimitry Andric 
4200b57cec5SDimitry Andric   if (!descriptor)
4210b57cec5SDimitry Andric     return false;
4220b57cec5SDimitry Andric 
4230b57cec5SDimitry Andric   auto superclass_func = [interface_decl,
4240b57cec5SDimitry Andric                           this](ObjCLanguageRuntime::ObjCISA isa) {
4250b57cec5SDimitry Andric     clang::ObjCInterfaceDecl *superclass_decl = GetDeclForISA(isa);
4260b57cec5SDimitry Andric 
4270b57cec5SDimitry Andric     if (!superclass_decl)
4280b57cec5SDimitry Andric       return;
4290b57cec5SDimitry Andric 
4300b57cec5SDimitry Andric     FinishDecl(superclass_decl);
431bdd1243dSDimitry Andric     clang::ASTContext &context = m_ast_ctx->getASTContext();
432480093f4SDimitry Andric     interface_decl->setSuperClass(context.getTrivialTypeSourceInfo(
433480093f4SDimitry Andric         context.getObjCInterfaceType(superclass_decl)));
4340b57cec5SDimitry Andric   };
4350b57cec5SDimitry Andric 
4360b57cec5SDimitry Andric   auto instance_method_func =
4370b57cec5SDimitry Andric       [log, interface_decl, this](const char *name, const char *types) -> bool {
4380b57cec5SDimitry Andric     if (!name || !types)
4390b57cec5SDimitry Andric       return false; // skip this one
4400b57cec5SDimitry Andric 
4410b57cec5SDimitry Andric     ObjCRuntimeMethodType method_type(types);
4420b57cec5SDimitry Andric 
443480093f4SDimitry Andric     clang::ObjCMethodDecl *method_decl = method_type.BuildMethod(
444bdd1243dSDimitry Andric         *m_ast_ctx, interface_decl, name, true, m_type_realizer_sp);
4450b57cec5SDimitry Andric 
4469dba64beSDimitry Andric     LLDB_LOGF(log, "[  AOTV::FD] Instance method [%s] [%s]", name, types);
4470b57cec5SDimitry Andric 
4480b57cec5SDimitry Andric     if (method_decl)
4490b57cec5SDimitry Andric       interface_decl->addDecl(method_decl);
4500b57cec5SDimitry Andric 
4510b57cec5SDimitry Andric     return false;
4520b57cec5SDimitry Andric   };
4530b57cec5SDimitry Andric 
4540b57cec5SDimitry Andric   auto class_method_func = [log, interface_decl,
4550b57cec5SDimitry Andric                             this](const char *name, const char *types) -> bool {
4560b57cec5SDimitry Andric     if (!name || !types)
4570b57cec5SDimitry Andric       return false; // skip this one
4580b57cec5SDimitry Andric 
4590b57cec5SDimitry Andric     ObjCRuntimeMethodType method_type(types);
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric     clang::ObjCMethodDecl *method_decl = method_type.BuildMethod(
462bdd1243dSDimitry Andric         *m_ast_ctx, interface_decl, name, false, m_type_realizer_sp);
4630b57cec5SDimitry Andric 
4649dba64beSDimitry Andric     LLDB_LOGF(log, "[  AOTV::FD] Class method [%s] [%s]", name, types);
4650b57cec5SDimitry Andric 
4660b57cec5SDimitry Andric     if (method_decl)
4670b57cec5SDimitry Andric       interface_decl->addDecl(method_decl);
4680b57cec5SDimitry Andric 
4690b57cec5SDimitry Andric     return false;
4700b57cec5SDimitry Andric   };
4710b57cec5SDimitry Andric 
4720b57cec5SDimitry Andric   auto ivar_func = [log, interface_decl,
4730b57cec5SDimitry Andric                     this](const char *name, const char *type,
4740b57cec5SDimitry Andric                           lldb::addr_t offset_ptr, uint64_t size) -> bool {
4750b57cec5SDimitry Andric     if (!name || !type)
4760b57cec5SDimitry Andric       return false;
4770b57cec5SDimitry Andric 
4780b57cec5SDimitry Andric     const bool for_expression = false;
4790b57cec5SDimitry Andric 
4809dba64beSDimitry Andric     LLDB_LOGF(log,
4819dba64beSDimitry Andric               "[  AOTV::FD] Instance variable [%s] [%s], offset at %" PRIx64,
4829dba64beSDimitry Andric               name, type, offset_ptr);
4830b57cec5SDimitry Andric 
4840b57cec5SDimitry Andric     CompilerType ivar_type = m_runtime.GetEncodingToType()->RealizeType(
485bdd1243dSDimitry Andric         *m_ast_ctx, type, for_expression);
4860b57cec5SDimitry Andric 
4870b57cec5SDimitry Andric     if (ivar_type.IsValid()) {
4880b57cec5SDimitry Andric       clang::TypeSourceInfo *const type_source_info = nullptr;
4890b57cec5SDimitry Andric       const bool is_synthesized = false;
4900b57cec5SDimitry Andric       clang::ObjCIvarDecl *ivar_decl = clang::ObjCIvarDecl::Create(
491bdd1243dSDimitry Andric           m_ast_ctx->getASTContext(), interface_decl, clang::SourceLocation(),
492bdd1243dSDimitry Andric           clang::SourceLocation(), &m_ast_ctx->getASTContext().Idents.get(name),
4930b57cec5SDimitry Andric           ClangUtil::GetQualType(ivar_type),
4940b57cec5SDimitry Andric           type_source_info, // TypeSourceInfo *
4950b57cec5SDimitry Andric           clang::ObjCIvarDecl::Public, nullptr, is_synthesized);
4960b57cec5SDimitry Andric 
4970b57cec5SDimitry Andric       if (ivar_decl) {
4980b57cec5SDimitry Andric         interface_decl->addDecl(ivar_decl);
4990b57cec5SDimitry Andric       }
5000b57cec5SDimitry Andric     }
5010b57cec5SDimitry Andric 
5020b57cec5SDimitry Andric     return false;
5030b57cec5SDimitry Andric   };
5040b57cec5SDimitry Andric 
50506c3fb27SDimitry Andric   LLDB_LOGF(log,
5069dba64beSDimitry Andric             "[AppleObjCDeclVendor::FinishDecl] Finishing Objective-C "
5070b57cec5SDimitry Andric             "interface for %s",
5080b57cec5SDimitry Andric             descriptor->GetClassName().AsCString());
5090b57cec5SDimitry Andric 
5100b57cec5SDimitry Andric   if (!descriptor->Describe(superclass_func, instance_method_func,
5110b57cec5SDimitry Andric                             class_method_func, ivar_func))
5120b57cec5SDimitry Andric     return false;
5130b57cec5SDimitry Andric 
5140b57cec5SDimitry Andric   if (log) {
5159dba64beSDimitry Andric     LLDB_LOGF(
5169dba64beSDimitry Andric         log,
5170b57cec5SDimitry Andric         "[AppleObjCDeclVendor::FinishDecl] Finished Objective-C interface");
5180b57cec5SDimitry Andric 
519480093f4SDimitry Andric     LLDB_LOG(log, "  [AOTV::FD] {0}", ClangUtil::DumpDecl(interface_decl));
5200b57cec5SDimitry Andric   }
5210b57cec5SDimitry Andric 
5220b57cec5SDimitry Andric   return true;
5230b57cec5SDimitry Andric }
5240b57cec5SDimitry Andric 
525480093f4SDimitry Andric uint32_t AppleObjCDeclVendor::FindDecls(ConstString name, bool append,
5260b57cec5SDimitry Andric                                         uint32_t max_matches,
527480093f4SDimitry Andric                                         std::vector<CompilerDecl> &decls) {
5280b57cec5SDimitry Andric 
52981ad6265SDimitry Andric   Log *log(
53081ad6265SDimitry Andric       GetLog(LLDBLog::Expressions)); // FIXME - a more appropriate log channel?
5310b57cec5SDimitry Andric 
5325ffd83dbSDimitry Andric   LLDB_LOGF(log, "AppleObjCDeclVendor::FindDecls ('%s', %s, %u, )",
5335ffd83dbSDimitry Andric             (const char *)name.AsCString(), append ? "true" : "false",
5345ffd83dbSDimitry Andric             max_matches);
5350b57cec5SDimitry Andric 
5360b57cec5SDimitry Andric   if (!append)
5370b57cec5SDimitry Andric     decls.clear();
5380b57cec5SDimitry Andric 
5390b57cec5SDimitry Andric   uint32_t ret = 0;
5400b57cec5SDimitry Andric 
5410b57cec5SDimitry Andric   do {
5420b57cec5SDimitry Andric     // See if the type is already in our ASTContext.
5430b57cec5SDimitry Andric 
544bdd1243dSDimitry Andric     clang::ASTContext &ast_ctx = m_ast_ctx->getASTContext();
5450b57cec5SDimitry Andric 
5460b57cec5SDimitry Andric     clang::IdentifierInfo &identifier_info =
547480093f4SDimitry Andric         ast_ctx.Idents.get(name.GetStringRef());
5480b57cec5SDimitry Andric     clang::DeclarationName decl_name =
549480093f4SDimitry Andric         ast_ctx.DeclarationNames.getIdentifier(&identifier_info);
5500b57cec5SDimitry Andric 
5510b57cec5SDimitry Andric     clang::DeclContext::lookup_result lookup_result =
552480093f4SDimitry Andric         ast_ctx.getTranslationUnitDecl()->lookup(decl_name);
5530b57cec5SDimitry Andric 
5540b57cec5SDimitry Andric     if (!lookup_result.empty()) {
5550b57cec5SDimitry Andric       if (clang::ObjCInterfaceDecl *result_iface_decl =
556fe6060f1SDimitry Andric              llvm::dyn_cast<clang::ObjCInterfaceDecl>(*lookup_result.begin())) {
5570b57cec5SDimitry Andric         if (log) {
5580b57cec5SDimitry Andric           clang::QualType result_iface_type =
559480093f4SDimitry Andric               ast_ctx.getObjCInterfaceType(result_iface_decl);
5600b57cec5SDimitry Andric 
5610b57cec5SDimitry Andric           uint64_t isa_value = LLDB_INVALID_ADDRESS;
562bdd1243dSDimitry Andric           ClangASTMetadata *metadata = m_ast_ctx->GetMetadata(result_iface_decl);
5630b57cec5SDimitry Andric           if (metadata)
5640b57cec5SDimitry Andric             isa_value = metadata->GetISAPtr();
5650b57cec5SDimitry Andric 
56606c3fb27SDimitry Andric           LLDB_LOGF(log,
5675ffd83dbSDimitry Andric                     "AOCTV::FT Found %s (isa 0x%" PRIx64 ") in the ASTContext",
56806c3fb27SDimitry Andric                     result_iface_type.getAsString().data(), isa_value);
5690b57cec5SDimitry Andric         }
5700b57cec5SDimitry Andric 
571bdd1243dSDimitry Andric         decls.push_back(m_ast_ctx->GetCompilerDecl(result_iface_decl));
5720b57cec5SDimitry Andric         ret++;
5730b57cec5SDimitry Andric         break;
5740b57cec5SDimitry Andric       } else {
5755ffd83dbSDimitry Andric         LLDB_LOGF(log, "AOCTV::FT There's something in the ASTContext, but "
5765ffd83dbSDimitry Andric                        "it's not something we know about");
5770b57cec5SDimitry Andric         break;
5780b57cec5SDimitry Andric       }
5790b57cec5SDimitry Andric     } else if (log) {
5805ffd83dbSDimitry Andric       LLDB_LOGF(log, "AOCTV::FT Couldn't find %s in the ASTContext",
5815ffd83dbSDimitry Andric                 name.AsCString());
5820b57cec5SDimitry Andric     }
5830b57cec5SDimitry Andric 
5840b57cec5SDimitry Andric     // It's not.  If it exists, we have to put it into our ASTContext.
5850b57cec5SDimitry Andric 
5860b57cec5SDimitry Andric     ObjCLanguageRuntime::ObjCISA isa = m_runtime.GetISA(name);
5870b57cec5SDimitry Andric 
5880b57cec5SDimitry Andric     if (!isa) {
5895ffd83dbSDimitry Andric       LLDB_LOGF(log, "AOCTV::FT Couldn't find the isa");
5900b57cec5SDimitry Andric 
5910b57cec5SDimitry Andric       break;
5920b57cec5SDimitry Andric     }
5930b57cec5SDimitry Andric 
5940b57cec5SDimitry Andric     clang::ObjCInterfaceDecl *iface_decl = GetDeclForISA(isa);
5950b57cec5SDimitry Andric 
5960b57cec5SDimitry Andric     if (!iface_decl) {
5979dba64beSDimitry Andric       LLDB_LOGF(log,
5985ffd83dbSDimitry Andric                 "AOCTV::FT Couldn't get the Objective-C interface for "
5990b57cec5SDimitry Andric                 "isa 0x%" PRIx64,
6005ffd83dbSDimitry Andric                 (uint64_t)isa);
6010b57cec5SDimitry Andric 
6020b57cec5SDimitry Andric       break;
6030b57cec5SDimitry Andric     }
6040b57cec5SDimitry Andric 
6050b57cec5SDimitry Andric     if (log) {
606480093f4SDimitry Andric       clang::QualType new_iface_type = ast_ctx.getObjCInterfaceType(iface_decl);
607480093f4SDimitry Andric 
6085ffd83dbSDimitry Andric       LLDB_LOG(log, "AOCTV::FT Created {1} (isa 0x{2:x})",
609480093f4SDimitry Andric                new_iface_type.getAsString(), (uint64_t)isa);
6100b57cec5SDimitry Andric     }
6110b57cec5SDimitry Andric 
612bdd1243dSDimitry Andric     decls.push_back(m_ast_ctx->GetCompilerDecl(iface_decl));
6130b57cec5SDimitry Andric     ret++;
6140b57cec5SDimitry Andric     break;
6150b57cec5SDimitry Andric   } while (false);
6160b57cec5SDimitry Andric 
6170b57cec5SDimitry Andric   return ret;
6180b57cec5SDimitry Andric }
619