Skip to content

[lldb] Improve handling of artificial subclasses #7423

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1080,6 +1080,11 @@ CompilerType SwiftLanguageRuntimeImpl::GetChildCompilerTypeAtIndex(
LLDBTypeInfoProvider tip(*this, *instance_ts);
reflection_ctx->ForEachSuperClassType(
&tip, pointer, [&](SuperClassType sc) -> bool {
// If the typeref is invalid, we don't want to process it (for
// example, this could be an artifical ObjC class).
if (!sc.get_typeref())
return false;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this an error, or expected? We might want to log it if it's an error.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's expected, because this is normal for artificial base classes, maybe the comment could be more explicit about that?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's expected if the current class is artificial, I'll add a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a way we can know that the current class is artificial? In the case where the current class is not artificial, then we'd want a log or better.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remote Mirrors doesn't really tell us why getting the typeref failed (it could be an artificial class or conceivably something else). It'd be pretty straight forward to add an API asking if the class is artificial or not, if we want that.


if (!found_start) {
// The ValueObject always points to the same class instance,
// even when querying base classes. Drop base classes until we
Expand Down Expand Up @@ -1561,7 +1566,8 @@ bool SwiftLanguageRuntimeImpl::GetDynamicTypeAndAddress_Class(
}
Log *log(GetLog(LLDBLog::Types));
ThreadSafeReflectionContext reflection_ctx = GetReflectionContext();
const auto *typeref = reflection_ctx->ReadTypeFromInstance(instance_ptr);
const auto *typeref =
reflection_ctx->ReadTypeFromInstance(instance_ptr, true);
if (!typeref) {
LLDB_LOGF(log,
"could not read typeref for type: %s (instance_ptr = 0x%" PRIx64
Expand Down
2 changes: 2 additions & 0 deletions lldb/test/API/lang/swift/artificial_subclass/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
SWIFT_SOURCES := main.swift
include Makefile.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import lldb
from lldbsuite.test.lldbtest import *
from lldbsuite.test.decorators import *
import lldbsuite.test.lldbutil as lldbutil
import unittest2


class TestSwiftArtificialSubclass(TestBase):
@skipUnlessObjCInterop
@swiftTest
def test(self):
""" Test that displaying an artificial type works correctly"""
self.build()
_, _, _, _ = lldbutil.run_to_source_breakpoint(
self, "break here", lldb.SBFileSpec("main.swift")
)


self.expect(
"frame variable m",
substrs=["Subclass)", "Superclass", "a = 42", "b = 97"]
)
19 changes: 19 additions & 0 deletions lldb/test/API/lang/swift/artificial_subclass/main.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import ObjectiveC

class Superclass {
let a = 42
}

class Subclass: Superclass {
let b = 97

override init() {
super.init()
let c: AnyClass = objc_allocateClassPair(Subclass.self, "DynamicSubclass", 0)!
objc_registerClassPair(c);
object_setClass(self, c)
}
}

let m = Subclass()
print(m) // break here