Coverage Report

Created: 2023-09-30 09:22

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- AppleObjCDeclVendor.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 "AppleObjCDeclVendor.h"
10
11
#include "Plugins/ExpressionParser/Clang/ClangASTMetadata.h"
12
#include "Plugins/ExpressionParser/Clang/ClangUtil.h"
13
#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"
14
#include "lldb/Core/Module.h"
15
#include "lldb/Target/Process.h"
16
#include "lldb/Target/Target.h"
17
#include "lldb/Utility/LLDBLog.h"
18
#include "lldb/Utility/Log.h"
19
20
#include "clang/AST/ASTContext.h"
21
#include "clang/AST/DeclObjC.h"
22
#include "clang/AST/ExternalASTSource.h"
23
24
using namespace lldb_private;
25
26
class lldb_private::AppleObjCExternalASTSource
27
    : public clang::ExternalASTSource {
28
public:
29
  AppleObjCExternalASTSource(AppleObjCDeclVendor &decl_vendor)
30
898
      : m_decl_vendor(decl_vendor) {}
31
32
  bool FindExternalVisibleDeclsByName(const clang::DeclContext *decl_ctx,
33
34
                                      clang::DeclarationName name) override {
34
35
34
    Log *log(GetLog(
36
34
        LLDBLog::Expressions)); // FIXME - a more appropriate log channel?
37
38
34
    if (log) {
39
0
      LLDB_LOGF(log,
40
0
                "AppleObjCExternalASTSource::FindExternalVisibleDeclsByName"
41
0
                " on (ASTContext*)%p Looking for %s in (%sDecl*)%p",
42
0
                static_cast<void *>(&decl_ctx->getParentASTContext()),
43
0
                name.getAsString().c_str(), decl_ctx->getDeclKindName(),
44
0
                static_cast<const void *>(decl_ctx));
45
0
    }
46
47
34
    do {
48
34
      const clang::ObjCInterfaceDecl *interface_decl =
49
34
          llvm::dyn_cast<clang::ObjCInterfaceDecl>(decl_ctx);
50
51
34
      if (!interface_decl)
52
0
        break;
53
54
34
      clang::ObjCInterfaceDecl *non_const_interface_decl =
55
34
          const_cast<clang::ObjCInterfaceDecl *>(interface_decl);
56
57
34
      if (!m_decl_vendor.FinishDecl(non_const_interface_decl))
58
0
        break;
59
60
34
      clang::DeclContext::lookup_result result =
61
34
          non_const_interface_decl->lookup(name);
62
63
34
      return (!result.empty());
64
34
    } while (
false0
);
65
66
0
    SetNoExternalVisibleDeclsForName(decl_ctx, name);
67
0
    return false;
68
34
  }
69
70
0
  void CompleteType(clang::TagDecl *tag_decl) override {
71
72
0
    Log *log(GetLog(
73
0
        LLDBLog::Expressions)); // FIXME - a more appropriate log channel?
74
75
0
    LLDB_LOGF(log,
76
0
              "AppleObjCExternalASTSource::CompleteType on "
77
0
              "(ASTContext*)%p Completing (TagDecl*)%p named %s",
78
0
              static_cast<void *>(&tag_decl->getASTContext()),
79
0
              static_cast<void *>(tag_decl), tag_decl->getName().str().c_str());
80
81
0
    LLDB_LOG(log, "  AOEAS::CT Before:\n{1}", ClangUtil::DumpDecl(tag_decl));
82
83
0
    LLDB_LOG(log, "  AOEAS::CT After:{1}", ClangUtil::DumpDecl(tag_decl));
84
0
  }
85
86
112
  void CompleteType(clang::ObjCInterfaceDecl *interface_decl) override {
87
88
112
    Log *log(GetLog(
89
112
        LLDBLog::Expressions)); // FIXME - a more appropriate log channel?
90
91
112
    if (log) {
92
0
      LLDB_LOGF(log,
93
0
                "AppleObjCExternalASTSource::CompleteType on "
94
0
                "(ASTContext*)%p Completing (ObjCInterfaceDecl*)%p named %s",
95
0
                static_cast<void *>(&interface_decl->getASTContext()),
96
0
                static_cast<void *>(interface_decl),
97
0
                interface_decl->getName().str().c_str());
98
99
0
      LLDB_LOGF(log, "  AOEAS::CT Before:");
100
0
      LLDB_LOG(log, "    [CT] {0}", ClangUtil::DumpDecl(interface_decl));
101
0
    }
102
103
112
    m_decl_vendor.FinishDecl(interface_decl);
104
105
112
    if (log) {
106
0
      LLDB_LOGF(log, "  [CT] After:");
107
0
      LLDB_LOG(log, "    [CT] {0}", ClangUtil::DumpDecl(interface_decl));
108
0
    }
109
112
  }
110
111
  bool layoutRecordType(
112
      const clang::RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,
113
      llvm::DenseMap<const clang::FieldDecl *, uint64_t> &FieldOffsets,
114
      llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
115
          &BaseOffsets,
116
      llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
117
0
          &VirtualBaseOffsets) override {
118
0
    return false;
119
0
  }
120
121
0
  void StartTranslationUnit(clang::ASTConsumer *Consumer) override {
122
0
    clang::TranslationUnitDecl *translation_unit_decl =
123
0
        m_decl_vendor.m_ast_ctx->getASTContext().getTranslationUnitDecl();
124
0
    translation_unit_decl->setHasExternalVisibleStorage();
125
0
    translation_unit_decl->setHasExternalLexicalStorage();
126
0
  }
127
128
private:
129
  AppleObjCDeclVendor &m_decl_vendor;
130
};
131
132
AppleObjCDeclVendor::AppleObjCDeclVendor(ObjCLanguageRuntime &runtime)
133
898
    : ClangDeclVendor(eAppleObjCDeclVendor), m_runtime(runtime),
134
898
      m_type_realizer_sp(m_runtime.GetEncodingToType()) {
135
898
  m_ast_ctx = std::make_shared<TypeSystemClang>(
136
898
      "AppleObjCDeclVendor AST",
137
898
      runtime.GetProcess()->GetTarget().GetArchitecture().GetTriple());
138
898
  m_external_source = new AppleObjCExternalASTSource(*this);
139
898
  llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> external_source_owning_ptr(
140
898
      m_external_source);
141
898
  m_ast_ctx->getASTContext().setExternalSource(external_source_owning_ptr);
142
898
}
143
144
clang::ObjCInterfaceDecl *
145
599
AppleObjCDeclVendor::GetDeclForISA(ObjCLanguageRuntime::ObjCISA isa) {
146
599
  ISAToInterfaceMap::const_iterator iter = m_isa_to_interface.find(isa);
147
148
599
  if (iter != m_isa_to_interface.end())
149
37
    return iter->second;
150
151
562
  clang::ASTContext &ast_ctx = m_ast_ctx->getASTContext();
152
153
562
  ObjCLanguageRuntime::ClassDescriptorSP descriptor =
154
562
      m_runtime.GetClassDescriptorFromISA(isa);
155
156
562
  if (!descriptor)
157
1
    return nullptr;
158
159
561
  ConstString name(descriptor->GetClassName());
160
161
561
  clang::IdentifierInfo &identifier_info =
162
561
      ast_ctx.Idents.get(name.GetStringRef());
163
164
561
  clang::ObjCInterfaceDecl *new_iface_decl = clang::ObjCInterfaceDecl::Create(
165
561
      ast_ctx, ast_ctx.getTranslationUnitDecl(), clang::SourceLocation(),
166
561
      &identifier_info, nullptr, nullptr);
167
168
561
  ClangASTMetadata meta_data;
169
561
  meta_data.SetISAPtr(isa);
170
561
  m_ast_ctx->SetMetadata(new_iface_decl, meta_data);
171
172
561
  new_iface_decl->setHasExternalVisibleStorage();
173
561
  new_iface_decl->setHasExternalLexicalStorage();
174
175
561
  ast_ctx.getTranslationUnitDecl()->addDecl(new_iface_decl);
176
177
561
  m_isa_to_interface[isa] = new_iface_decl;
178
179
561
  return new_iface_decl;
180
562
}
181
182
class ObjCRuntimeMethodType {
183
public:
184
20.4k
  ObjCRuntimeMethodType(const char *types) {
185
20.4k
    const char *cursor = types;
186
20.4k
    enum ParserState { Start = 0, InType, InPos } state = Start;
187
20.4k
    const char *type = nullptr;
188
20.4k
    int brace_depth = 0;
189
190
20.4k
    uint32_t stepsLeft = 256;
191
192
407k
    while (true) {
193
407k
      if (--stepsLeft == 0) {
194
0
        m_is_valid = false;
195
0
        return;
196
0
      }
197
198
407k
      switch (state) {
199
20.4k
      case Start: {
200
20.4k
        switch (*cursor) {
201
20.4k
        default:
202
20.4k
          state = InType;
203
20.4k
          type = cursor;
204
20.4k
          break;
205
0
        case '\0':
206
0
          m_is_valid = true;
207
0
          return;
208
0
        case '0':
209
0
        case '1':
210
0
        case '2':
211
0
        case '3':
212
0
        case '4':
213
0
        case '5':
214
0
        case '6':
215
0
        case '7':
216
0
        case '8':
217
0
        case '9':
218
0
          m_is_valid = false;
219
0
          return;
220
20.4k
        }
221
20.4k
      } break;
222
192k
      case InType: {
223
192k
        switch (*cursor) {
224
107k
        default:
225
107k
          ++cursor;
226
107k
          break;
227
20.4k
        case '0':
228
40.9k
        case '1':
229
52.4k
        case '2':
230
55.7k
        case '3':
231
57.8k
        case '4':
232
58.2k
        case '5':
233
58.3k
        case '6':
234
58.4k
        case '7':
235
78.9k
        case '8':
236
78.9k
        case '9':
237
78.9k
          if (!brace_depth) {
238
78.6k
            state = InPos;
239
78.6k
            if (type) {
240
78.6k
              m_type_vector.push_back(std::string(type, (cursor - type)));
241
78.6k
            } else {
242
0
              m_is_valid = false;
243
0
              return;
244
0
            }
245
78.6k
            type = nullptr;
246
78.6k
          } else {
247
358
            ++cursor;
248
358
          }
249
78.9k
          break;
250
78.9k
        case '[':
251
2.80k
        case '{':
252
2.80k
        case '(':
253
2.80k
          ++brace_depth;
254
2.80k
          ++cursor;
255
2.80k
          break;
256
148
        case ']':
257
2.80k
        case '}':
258
2.80k
        case ')':
259
2.80k
          if (!brace_depth) {
260
0
            m_is_valid = false;
261
0
            return;
262
0
          }
263
2.80k
          --brace_depth;
264
2.80k
          ++cursor;
265
2.80k
          break;
266
0
        case '\0':
267
0
          m_is_valid = false;
268
0
          return;
269
192k
        }
270
192k
      } break;
271
194k
      case InPos: {
272
194k
        switch (*cursor) {
273
58.1k
        default:
274
58.1k
          state = InType;
275
58.1k
          type = cursor;
276
58.1k
          break;
277
22.4k
        case '0':
278
42.8k
        case '1':
279
57.4k
        case '2':
280
60.6k
        case '3':
281
73.7k
        case '4':
282
74.1k
        case '5':
283
95.1k
        case '6':
284
95.2k
        case '7':
285
116k
        case '8':
286
116k
        case '9':
287
116k
          ++cursor;
288
116k
          break;
289
20.4k
        case '\0':
290
20.4k
          m_is_valid = true;
291
20.4k
          return;
292
194k
        }
293
194k
      } 
break174k
;
294
407k
      }
295
407k
    }
296
20.4k
  }
297
298
  clang::ObjCMethodDecl *
299
  BuildMethod(TypeSystemClang &clang_ast_ctxt,
300
              clang::ObjCInterfaceDecl *interface_decl, const char *name,
301
              bool instance,
302
20.4k
              ObjCLanguageRuntime::EncodingToTypeSP type_realizer_sp) {
303
20.4k
    if (!m_is_valid || m_type_vector.size() < 3)
304
0
      return nullptr;
305
306
20.4k
    clang::ASTContext &ast_ctx(interface_decl->getASTContext());
307
308
20.4k
    const bool isInstance = instance;
309
20.4k
    const bool isVariadic = false;
310
20.4k
    const bool isPropertyAccessor = false;
311
20.4k
    const bool isSynthesizedAccessorStub = false;
312
20.4k
    const bool isImplicitlyDeclared = true;
313
20.4k
    const bool isDefined = false;
314
20.4k
    const clang::ObjCMethodDecl::ImplementationControl impControl =
315
20.4k
        clang::ObjCMethodDecl::None;
316
20.4k
    const bool HasRelatedResultType = false;
317
20.4k
    const bool for_expression = true;
318
319
20.4k
    std::vector<clang::IdentifierInfo *> selector_components;
320
321
20.4k
    const char *name_cursor = name;
322
20.4k
    bool is_zero_argument = true;
323
324
37.7k
    while (*name_cursor != '\0') {
325
26.1k
      const char *colon_loc = strchr(name_cursor, ':');
326
26.1k
      if (!colon_loc) {
327
8.82k
        selector_components.push_back(
328
8.82k
            &ast_ctx.Idents.get(llvm::StringRef(name_cursor)));
329
8.82k
        break;
330
17.3k
      } else {
331
17.3k
        is_zero_argument = false;
332
17.3k
        selector_components.push_back(&ast_ctx.Idents.get(
333
17.3k
            llvm::StringRef(name_cursor, colon_loc - name_cursor)));
334
17.3k
        name_cursor = colon_loc + 1;
335
17.3k
      }
336
26.1k
    }
337
338
20.4k
    clang::IdentifierInfo **identifier_infos = selector_components.data();
339
20.4k
    if (!identifier_infos) {
340
0
      return nullptr;
341
0
    }
342
343
20.4k
    clang::Selector sel = ast_ctx.Selectors.getSelector(
344
20.4k
        is_zero_argument ? 
08.82k
:
selector_components.size()11.5k
,
345
20.4k
        identifier_infos);
346
347
20.4k
    clang::QualType ret_type =
348
20.4k
        ClangUtil::GetQualType(type_realizer_sp->RealizeType(
349
20.4k
            clang_ast_ctxt, m_type_vector[0].c_str(), for_expression));
350
351
20.4k
    if (ret_type.isNull())
352
678
      return nullptr;
353
354
19.7k
    clang::ObjCMethodDecl *ret = clang::ObjCMethodDecl::Create(
355
19.7k
        ast_ctx, clang::SourceLocation(), clang::SourceLocation(), sel,
356
19.7k
        ret_type, nullptr, interface_decl, isInstance, isVariadic,
357
19.7k
        isPropertyAccessor, isSynthesizedAccessorStub, isImplicitlyDeclared,
358
19.7k
        isDefined, impControl, HasRelatedResultType);
359
360
19.7k
    std::vector<clang::ParmVarDecl *> parm_vars;
361
362
34.8k
    for (size_t ai = 3, ae = m_type_vector.size(); ai != ae; 
++ai15.1k
) {
363
16.1k
      const bool for_expression = true;
364
16.1k
      clang::QualType arg_type =
365
16.1k
          ClangUtil::GetQualType(type_realizer_sp->RealizeType(
366
16.1k
              clang_ast_ctxt, m_type_vector[ai].c_str(), for_expression));
367
368
16.1k
      if (arg_type.isNull())
369
1.07k
        return nullptr; // well, we just wasted a bunch of time.  Wish we could
370
                        // delete the stuff we'd just made!
371
372
15.1k
      parm_vars.push_back(clang::ParmVarDecl::Create(
373
15.1k
          ast_ctx, ret, clang::SourceLocation(), clang::SourceLocation(),
374
15.1k
          nullptr, arg_type, nullptr, clang::SC_None, nullptr));
375
15.1k
    }
376
377
18.6k
    ret->setMethodParams(ast_ctx,
378
18.6k
                         llvm::ArrayRef<clang::ParmVarDecl *>(parm_vars),
379
18.6k
                         llvm::ArrayRef<clang::SourceLocation>());
380
381
18.6k
    return ret;
382
19.7k
  }
383
384
0
  explicit operator bool() { return m_is_valid; }
385
386
0
  size_t GetNumTypes() { return m_type_vector.size(); }
387
388
0
  const char *GetTypeAtIndex(size_t idx) { return m_type_vector[idx].c_str(); }
389
390
private:
391
  typedef std::vector<std::string> TypeVector;
392
393
  TypeVector m_type_vector;
394
  bool m_is_valid = false;
395
};
396
397
357
bool AppleObjCDeclVendor::FinishDecl(clang::ObjCInterfaceDecl *interface_decl) {
398
357
  Log *log(
399
357
      GetLog(LLDBLog::Expressions)); // FIXME - a more appropriate log channel?
400
401
357
  ClangASTMetadata *metadata = m_ast_ctx->GetMetadata(interface_decl);
402
357
  ObjCLanguageRuntime::ObjCISA objc_isa = 0;
403
357
  if (metadata)
404
357
    objc_isa = metadata->GetISAPtr();
405
406
357
  if (!objc_isa)
407
0
    return false;
408
409
357
  if (!interface_decl->hasExternalVisibleStorage())
410
37
    return true;
411
412
320
  interface_decl->startDefinition();
413
414
320
  interface_decl->setHasExternalVisibleStorage(false);
415
320
  interface_decl->setHasExternalLexicalStorage(false);
416
417
320
  ObjCLanguageRuntime::ClassDescriptorSP descriptor =
418
320
      m_runtime.GetClassDescriptorFromISA(objc_isa);
419
420
320
  if (!descriptor)
421
0
    return false;
422
423
320
  auto superclass_func = [interface_decl,
424
320
                          this](ObjCLanguageRuntime::ObjCISA isa) {
425
212
    clang::ObjCInterfaceDecl *superclass_decl = GetDeclForISA(isa);
426
427
212
    if (!superclass_decl)
428
1
      return;
429
430
211
    FinishDecl(superclass_decl);
431
211
    clang::ASTContext &context = m_ast_ctx->getASTContext();
432
211
    interface_decl->setSuperClass(context.getTrivialTypeSourceInfo(
433
211
        context.getObjCInterfaceType(superclass_decl)));
434
211
  };
435
436
320
  auto instance_method_func =
437
13.4k
      [log, interface_decl, this](const char *name, const char *types) -> bool {
438
13.4k
    if (!name || !types)
439
0
      return false; // skip this one
440
441
13.4k
    ObjCRuntimeMethodType method_type(types);
442
443
13.4k
    clang::ObjCMethodDecl *method_decl = method_type.BuildMethod(
444
13.4k
        *m_ast_ctx, interface_decl, name, true, m_type_realizer_sp);
445
446
13.4k
    LLDB_LOGF(log, "[  AOTV::FD] Instance method [%s] [%s]", name, types);
447
448
13.4k
    if (method_decl)
449
11.9k
      interface_decl->addDecl(method_decl);
450
451
13.4k
    return false;
452
13.4k
  };
453
454
320
  auto class_method_func = [log, interface_decl,
455
6.93k
                            this](const char *name, const char *types) -> bool {
456
6.93k
    if (!name || !types)
457
0
      return false; // skip this one
458
459
6.93k
    ObjCRuntimeMethodType method_type(types);
460
461
6.93k
    clang::ObjCMethodDecl *method_decl = method_type.BuildMethod(
462
6.93k
        *m_ast_ctx, interface_decl, name, false, m_type_realizer_sp);
463
464
6.93k
    LLDB_LOGF(log, "[  AOTV::FD] Class method [%s] [%s]", name, types);
465
466
6.93k
    if (method_decl)
467
6.68k
      interface_decl->addDecl(method_decl);
468
469
6.93k
    return false;
470
6.93k
  };
471
472
320
  auto ivar_func = [log, interface_decl,
473
320
                    this](const char *name, const char *type,
474
362
                          lldb::addr_t offset_ptr, uint64_t size) -> bool {
475
362
    if (!name || !type)
476
0
      return false;
477
478
362
    const bool for_expression = false;
479
480
362
    LLDB_LOGF(log,
481
362
              "[  AOTV::FD] Instance variable [%s] [%s], offset at %" PRIx64,
482
362
              name, type, offset_ptr);
483
484
362
    CompilerType ivar_type = m_runtime.GetEncodingToType()->RealizeType(
485
362
        *m_ast_ctx, type, for_expression);
486
487
362
    if (ivar_type.IsValid()) {
488
354
      clang::TypeSourceInfo *const type_source_info = nullptr;
489
354
      const bool is_synthesized = false;
490
354
      clang::ObjCIvarDecl *ivar_decl = clang::ObjCIvarDecl::Create(
491
354
          m_ast_ctx->getASTContext(), interface_decl, clang::SourceLocation(),
492
354
          clang::SourceLocation(), &m_ast_ctx->getASTContext().Idents.get(name),
493
354
          ClangUtil::GetQualType(ivar_type),
494
354
          type_source_info, // TypeSourceInfo *
495
354
          clang::ObjCIvarDecl::Public, nullptr, is_synthesized);
496
497
354
      if (ivar_decl) {
498
354
        interface_decl->addDecl(ivar_decl);
499
354
      }
500
354
    }
501
502
362
    return false;
503
362
  };
504
505
320
  LLDB_LOGF(log,
506
320
            "[AppleObjCDeclVendor::FinishDecl] Finishing Objective-C "
507
320
            "interface for %s",
508
320
            descriptor->GetClassName().AsCString());
509
510
320
  if (!descriptor->Describe(superclass_func, instance_method_func,
511
320
                            class_method_func, ivar_func))
512
4
    return false;
513
514
316
  if (log) {
515
0
    LLDB_LOGF(
516
0
        log,
517
0
        "[AppleObjCDeclVendor::FinishDecl] Finished Objective-C interface");
518
519
0
    LLDB_LOG(log, "  [AOTV::FD] {0}", ClangUtil::DumpDecl(interface_decl));
520
0
  }
521
522
316
  return true;
523
320
}
524
525
uint32_t AppleObjCDeclVendor::FindDecls(ConstString name, bool append,
526
                                        uint32_t max_matches,
527
10.6k
                                        std::vector<CompilerDecl> &decls) {
528
529
10.6k
  Log *log(
530
10.6k
      GetLog(LLDBLog::Expressions)); // FIXME - a more appropriate log channel?
531
532
10.6k
  LLDB_LOGF(log, "AppleObjCDeclVendor::FindDecls ('%s', %s, %u, )",
533
10.6k
            (const char *)name.AsCString(), append ? "true" : "false",
534
10.6k
            max_matches);
535
536
10.6k
  if (!append)
537
9.72k
    decls.clear();
538
539
10.6k
  uint32_t ret = 0;
540
541
10.6k
  do {
542
    // See if the type is already in our ASTContext.
543
544
10.6k
    clang::ASTContext &ast_ctx = m_ast_ctx->getASTContext();
545
546
10.6k
    clang::IdentifierInfo &identifier_info =
547
10.6k
        ast_ctx.Idents.get(name.GetStringRef());
548
10.6k
    clang::DeclarationName decl_name =
549
10.6k
        ast_ctx.DeclarationNames.getIdentifier(&identifier_info);
550
551
10.6k
    clang::DeclContext::lookup_result lookup_result =
552
10.6k
        ast_ctx.getTranslationUnitDecl()->lookup(decl_name);
553
554
10.6k
    if (!lookup_result.empty()) {
555
1.05k
      if (clang::ObjCInterfaceDecl *result_iface_decl =
556
1.05k
             llvm::dyn_cast<clang::ObjCInterfaceDecl>(*lookup_result.begin())) {
557
1.05k
        if (log) {
558
0
          clang::QualType result_iface_type =
559
0
              ast_ctx.getObjCInterfaceType(result_iface_decl);
560
561
0
          uint64_t isa_value = LLDB_INVALID_ADDRESS;
562
0
          ClangASTMetadata *metadata = m_ast_ctx->GetMetadata(result_iface_decl);
563
0
          if (metadata)
564
0
            isa_value = metadata->GetISAPtr();
565
566
0
          LLDB_LOGF(log,
567
0
                    "AOCTV::FT Found %s (isa 0x%" PRIx64 ") in the ASTContext",
568
0
                    result_iface_type.getAsString().data(), isa_value);
569
0
        }
570
571
1.05k
        decls.push_back(m_ast_ctx->GetCompilerDecl(result_iface_decl));
572
1.05k
        ret++;
573
1.05k
        break;
574
1.05k
      } else {
575
0
        LLDB_LOGF(log, "AOCTV::FT There's something in the ASTContext, but "
576
0
                       "it's not something we know about");
577
0
        break;
578
0
      }
579
9.56k
    } else if (log) {
580
14
      LLDB_LOGF(log, "AOCTV::FT Couldn't find %s in the ASTContext",
581
14
                name.AsCString());
582
14
    }
583
584
    // It's not.  If it exists, we have to put it into our ASTContext.
585
586
9.56k
    ObjCLanguageRuntime::ObjCISA isa = m_runtime.GetISA(name);
587
588
9.56k
    if (!isa) {
589
9.18k
      LLDB_LOGF(log, "AOCTV::FT Couldn't find the isa");
590
591
9.18k
      break;
592
9.18k
    }
593
594
387
    clang::ObjCInterfaceDecl *iface_decl = GetDeclForISA(isa);
595
596
387
    if (!iface_decl) {
597
0
      LLDB_LOGF(log,
598
0
                "AOCTV::FT Couldn't get the Objective-C interface for "
599
0
                "isa 0x%" PRIx64,
600
0
                (uint64_t)isa);
601
602
0
      break;
603
0
    }
604
605
387
    if (log) {
606
0
      clang::QualType new_iface_type = ast_ctx.getObjCInterfaceType(iface_decl);
607
608
0
      LLDB_LOG(log, "AOCTV::FT Created {1} (isa 0x{2:x})",
609
0
               new_iface_type.getAsString(), (uint64_t)isa);
610
0
    }
611
612
387
    decls.push_back(m_ast_ctx->GetCompilerDecl(iface_decl));
613
387
    ret++;
614
387
    break;
615
387
  } while (
false0
);
616
617
0
  return ret;
618
10.6k
}