Skip to content

Commit 0d46a6c

Browse files
authored
Merge pull request #7850 from augusto2112/fix-anon-struct
[lldb] Handle formatting C anonymous struct and unions in Swift
2 parents 38f744a + 8f297ca commit 0d46a6c

File tree

6 files changed

+142
-2
lines changed

6 files changed

+142
-2
lines changed

lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3263,6 +3263,34 @@ CompilerType TypeSystemSwiftTypeRef::GetChildCompilerTypeAtIndex(
32633263
clang_child_type = clang_child_type.GetTypedefedType();
32643264
}
32653265
if (clang_child_type) {
3266+
// TypeSystemSwiftTypeRef can't properly handle C anonymous types, as
3267+
// the only identifier CompilerTypes backed by this type system carry is
3268+
// the type's mangled name. This is problematic for anonymous types, as
3269+
// sibling anonymous types will share the exact same mangled name,
3270+
// making it impossible to diferentiate between them. For example, the
3271+
// following two anonymous structs in "MyStruct" share the same name
3272+
// (which is MyStruct::(anonymous struct)):
3273+
//
3274+
// struct MyStruct {
3275+
// struct {
3276+
// float x;
3277+
// float y;
3278+
// float z;
3279+
// };
3280+
// struct {
3281+
// int a;
3282+
// };
3283+
// };
3284+
//
3285+
// For this reason, forward any lookups of anonymous types to
3286+
// TypeSystemClang instead, as that type system carries enough
3287+
// information to handle anonymous types properly.
3288+
auto ts_clang = clang_child_type.GetTypeSystem()
3289+
.dyn_cast_or_null<TypeSystemClang>();
3290+
if (ts_clang &&
3291+
ts_clang->IsAnonymousType(clang_child_type.GetOpaqueQualType()))
3292+
return clang_child_type;
3293+
32663294
std::string prefix;
32673295
swift::Demangle::Demangler dem;
32683296
swift::Demangle::NodePointer node =
@@ -3305,6 +3333,7 @@ CompilerType TypeSystemSwiftTypeRef::GetChildCompilerTypeAtIndex(
33053333
if (!runtime)
33063334
return impl();
33073335
#ifndef NDEBUG
3336+
auto result = impl();
33083337
// FIXME:
33093338
// No point comparing the results if the reflection data has more
33103339
// information. There's a nasty chicken & egg problem buried here:
@@ -3314,9 +3343,18 @@ CompilerType TypeSystemSwiftTypeRef::GetChildCompilerTypeAtIndex(
33143343
if (get_ast_num_children() <
33153344
runtime->GetNumChildren({weak_from_this(), type}, exe_scope)
33163345
.value_or(0))
3317-
return impl();
3346+
return result;
33183347
if (ShouldSkipValidation(type))
3319-
return impl();
3348+
return result;
3349+
// When the child compiler type is an anonymous clang type,
3350+
// GetChildCompilerTypeAtIndex will return the clang type directly. In this
3351+
// case validation will fail as it can't correctly compare the mangled
3352+
// clang and Swift names, so return early.
3353+
if (auto ts_clang =
3354+
result.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>()) {
3355+
if (ts_clang->IsAnonymousType(result.GetOpaqueQualType()))
3356+
return result;
3357+
}
33203358
std::string ast_child_name;
33213359
uint32_t ast_child_byte_size = 0;
33223360
int32_t ast_child_byte_offset = 0;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
SWIFT_SOURCES := main.swift
2+
C_SOURCES := source.c
3+
SWIFT_BRIDGING_HEADER := bridging-header.h
4+
5+
include Makefile.rules
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import lldb
2+
from lldbsuite.test.decorators import *
3+
import lldbsuite.test.lldbtest as lldbtest
4+
import lldbsuite.test.lldbutil as lldbutil
5+
6+
7+
class TestSwiftAnonymousClangTypes(lldbtest.TestBase):
8+
@swiftTest
9+
def test(self):
10+
self.build()
11+
12+
lldbutil.run_to_source_breakpoint(
13+
self, "break here", lldb.SBFileSpec("main.swift")
14+
)
15+
self.expect(
16+
"frame variable twoStructs",
17+
substrs=[
18+
"(TwoAnonymousStructs) twoStructs = {",
19+
"= (x = 1, y = 2, z = 3)",
20+
"= (a = 4)",
21+
],
22+
)
23+
24+
self.expect(
25+
"frame variable twoUnions",
26+
substrs=[
27+
"(TwoAnonymousUnions) twoUnions = {",
28+
" = {",
29+
" = (x = 2)",
30+
" = (y = 2, z = 3)",
31+
" }",
32+
" = {",
33+
" = (a = 4, b = 5, c = 6)",
34+
" = (d = 4, e = 5)",
35+
],
36+
)
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
2+
typedef struct TwoAnonymousStructs {
3+
struct {
4+
float x;
5+
float y;
6+
float z;
7+
};
8+
struct {
9+
int a;
10+
};
11+
} TwoAnonymousStructs;
12+
13+
typedef struct TwoAnonymousUnions {
14+
union {
15+
struct {
16+
int x;
17+
};
18+
struct {
19+
int y;
20+
int z;
21+
};
22+
};
23+
union {
24+
struct {
25+
int a;
26+
int b;
27+
int c;
28+
};
29+
struct {
30+
int d;
31+
int e;
32+
};
33+
};
34+
} TwoAnonymousUnions;
35+
36+
TwoAnonymousStructs makeTwoAnonymousStructs();
37+
TwoAnonymousUnions makeTwoAnonymousUnions();
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
let twoStructs = makeTwoAnonymousStructs()
2+
let twoUnions = makeTwoAnonymousUnions()
3+
print("break here")
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include "bridging-header.h"
2+
3+
TwoAnonymousStructs makeTwoAnonymousStructs() {
4+
TwoAnonymousStructs anon_struct;
5+
anon_struct.x = 1;
6+
anon_struct.y = 2;
7+
anon_struct.z = 3;
8+
anon_struct.a = 4;
9+
return anon_struct;
10+
}
11+
12+
13+
TwoAnonymousUnions makeTwoAnonymousUnions() {
14+
TwoAnonymousUnions anon_unions;
15+
anon_unions.y = 2;
16+
anon_unions.z = 3;
17+
anon_unions.a = 4;
18+
anon_unions.b = 5;
19+
anon_unions.c = 6;
20+
return anon_unions;
21+
}

0 commit comments

Comments
 (0)