Skip to content

[lldb] Add tests for Swift class with C++ ivars and STL types in Swift #6401

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
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
12 changes: 10 additions & 2 deletions lldb/packages/Python/lldbsuite/test/make/Makefile.rules
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,14 @@ ifeq "$(MAKE_GMODULES)" "YES"
endif

CFLAGS += $(CFLAGS_EXTRAS)
CXXFLAGS += -std=c++11 $(CFLAGS) $(ARCH_CXXFLAGS)

ifeq "$(SWIFT_CXX_INTEROP)" "1"
CXXFLAGS += -std=c++17
else
CXXFLAGS += -std=c++11

Choose a reason for hiding this comment

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

@Michael137 Could we generally bump this on llvm.org for all tests by default?

Copy link

@Michael137 Michael137 Mar 8, 2023

Choose a reason for hiding this comment

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

Think it could be worthwhile. Easy enough to test whether anything breaks
We'd just have to be careful with the buildbot matrix for older compilers. But I think Clang 7.0 is the oldest version that supports libc++ with -std=c++17 properly, which is also the oldest clang version on the buildbots, so it might be time to make the switch.

endif
CXXFLAGS += $(CFLAGS) $(ARCH_CXXFLAGS)

LD = $(CC)
LDFLAGS ?= $(CFLAGS)
LDFLAGS += $(LD_EXTRAS) $(ARCH_LDFLAGS)
Expand Down Expand Up @@ -602,6 +609,7 @@ endif
#----------------------------------------------------------------------
ifeq "$(SWIFT_CXX_INTEROP)" "1"
SWIFTFLAGS += -Xfrontend -enable-experimental-cxx-interop -Xfrontend -validate-tbd-against-ir=none
SWIFTFLAGS += -Xcc -std=c++17
endif

#----------------------------------------------------------------------
Expand Down Expand Up @@ -659,7 +667,7 @@ VPATHSOURCES=$(patsubst %,$(VPATH)/%,$(SWIFT_SOURCES)) $(patsubst %,$(VPATH)/%,$
$(SWIFT_FE) -c -primary-file $< \
$(filter-out $(VPATH)/$<,$(filter-out $<,$(VPATHSOURCES))) \
$(SWIFT_FEFLAGS) $(SWIFT_HFLAGS) $(PARSE_AS_LIBRARY) \
-module-name $(MODULENAME) -emit-module-path \
-module-name $(MODULENAME) -emit-module-path \
$(patsubst %.o,$(BUILDDIR)/%.partial.swiftmodule,$@) \
-o $(BUILDDIR)/$@

Expand Down
16 changes: 16 additions & 0 deletions lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,16 @@ CompilerType TypeSystemSwiftTypeRef::GetBuiltinRawPointerType() {
}


static bool IsImportedType(swift::Demangle::NodePointer node) {
if (!node)
return false;
if (node->hasText() && node->getText() == "__C")
return true;
if (node->hasChildren())
return IsImportedType(node->getFirstChild());
return false;
}

swift::Demangle::NodePointer
TypeSystemSwiftTypeRef::GetSwiftified(swift::Demangle::Demangler &dem,
swift::Demangle::NodePointer node,
Expand Down Expand Up @@ -3273,6 +3283,12 @@ bool TypeSystemSwiftTypeRef::IsImportedType(opaque_compiler_type_t type,
"an imported type",
AsMangledName(type));

if (!::IsImportedType(node))
return false;
// Early return if we don't need to look up the original type.
if (!original_type)
return true;

// This is an imported Objective-C type; look it up in the debug info.
llvm::SmallVector<CompilerContext, 2> decl_context;
if (!IsClangImportedType(node, decl_context))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
SWIFT_SOURCES := main.swift
SWIFT_CXX_INTEROP := 1
SWIFTFLAGS_EXTRAS = -Xcc -I$(SRCDIR)
include Makefile.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@

"""
Test that a Swift class with C++ ivars is printed correctly
"""
from lldbsuite.test.lldbtest import *
from lldbsuite.test.decorators import *


class TestSwiftClassWithCxxIvars(TestBase):

@swiftTest
def test(self):
self.build()
self.runCmd('setting set target.experimental.swift-enable-cxx-interop true')
_, _, _, _= lldbutil.run_to_source_breakpoint(
self, 'Set breakpoint here', lldb.SBFileSpec('main.swift'))

self.expect('v swiftClass', substrs=['SwiftClass', 'cxxClass', 'a1', '10', 'a2', '20', 'a3', '30',
'cxxSubclass', 'a1', '10', 'a2', '20', 'a3', '30', 'a4', '40'])
self.expect('expr swiftClass', substrs=['SwiftClass', 'cxxClass', 'a1', '10', 'a2', '20', 'a3', '30',
'cxxSubclass', 'a1', '10', 'a2', '20', 'a3', '30', 'a4', '40'])

self.expect('v swiftStruct', substrs=['SwiftStruct', 'cxxClass', 'a1', '10', 'a2', '20', 'a3', '30',
'cxxSubclass', 'a1', '10', 'a2', '20', 'a3', '30', 'a4', '40'])
self.expect('expr swiftStruct', substrs=['SwiftStruct', 'cxxClass', 'a1', '10', 'a2', '20', 'a3', '30',
'cxxSubclass', 'a1', '10', 'a2', '20', 'a3', '30', 'a4', '40'])


self.expect('v swiftEnum1', substrs=['SwiftEnum', 'first', 'a1', '10', 'a2', '20', 'a3', '30'])
self.expect('expr swiftEnum1', substrs=['SwiftEnum', 'first', 'a1', '10', 'a2', '20', 'a3', '30'])

self.expect('v swiftEnum2', substrs=['SwiftEnum', 'second', 'a1', '10', 'a2', '20', 'a3', '30',
'a4', '40'])
self.expect('expr swiftEnum2', substrs=['SwiftEnum', 'second', 'a1', '10', 'a2', '20', 'a3', '30',
'a4', '40'])
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import ReturnsClass

class SwiftClass {
let cxxClass = CxxClass()
let cxxSubclass = InheritedCxxClass()
}

struct SwiftStruct {
let cxxClass = CxxClass()
let cxxSubclass = InheritedCxxClass()
}

enum SwiftEnum {
case first(CxxClass)
case second(InheritedCxxClass)

}

func main() {
let swiftClass = SwiftClass()
let swiftStruct = SwiftStruct()
let swiftEnum1 = SwiftEnum.first(CxxClass())
let swiftEnum2 = SwiftEnum.second(InheritedCxxClass())
print(1) // Set breakpoint here
}
main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module ReturnsClass {
header "returns-class.h"
requires cplusplus
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

struct CxxClass {
long long a1 = 10;
long long a2 = 20;
long long a3 = 30;
};

struct InheritedCxxClass: CxxClass {
long long a4 = 40;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
SWIFT_SOURCES := main.swift
SWIFT_CXX_INTEROP := 1
SWIFTFLAGS_EXTRAS = -Xcc -I$(SRCDIR) -Xlinker -lm
include Makefile.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@

"""
Test that a C++ class is visible in Swift.
"""
from lldbsuite.test.lldbtest import *
from lldbsuite.test.decorators import *


class TestSTLTypes(TestBase):

@skipIfLinux # rdar://106532498
@skipIf(setting=('symbols.use-swift-clangimporter', 'false')) # rdar://106438227 (TestSTLTypes fails when clang importer is disabled)
@swiftTest
def test(self):
self.build()
self.runCmd('setting set target.experimental.swift-enable-cxx-interop true')
_, _, _, _= lldbutil.run_to_source_breakpoint(
self, 'Set breakpoint here', lldb.SBFileSpec('main.swift'))

self.expect('v map', substrs=['CxxMap', 'first = 1, second = 3',
'first = 2, second = 2', 'first = 3, second = 3'])

# This should work (rdar://106374745), check all 'expr' cases after it's fixed.
self.expect('expr map', substrs=['error while processing module import: failed to '
'get module "std" from AST context'], error=True)

self.expect('v optional', substrs=['CxxOptional', 'optional', 'Has Value=true',
'Value = "In optional!"'])

self.expect('v emptyOptional', substrs=['CxxOptional', 'emptyOptional',
'Has Value=false'])

self.expect('v set', substrs=['CxxSet', 'size=3', '3.7', '4.2', '9.19'])

self.expect('v string', substrs=['string', 'Hello from C++!'])

self.expect('v unorderedMap', substrs=['CxxUnorderedMap',
'(first = 3, second = "three")', '(first = 2, second = "two")',
'(first = 1, second = "one")'], ordered=False)

self.expect('v unorderedSet', substrs=['CxxUnorderedSet',
'first', 'second', 'third'], ordered=False)

self.expect('v vector', substrs=['CxxVector', '[0] = 4.1', '[1] = 3.7',
'[2] = 9.19'])
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import ReturnsSTL
import CxxStdlib

func main() {
var map = returnMap()
var optional = returnOptional()
var emptyOptional = returnEmtpyOptional()
var set = returnSet()
var string = returnString()
var unorderedMap = returnUnorderedMap()
var unorderedSet = returnUnorderedSet()
var vector = returnVector()

print(1) // Set breakpoint here
}
main()
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module ReturnsSTL {
header "returns-stl.h"
requires cplusplus
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include <map>
#include <optional>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using CxxMap = std::map<int, int>;
using CxxOptional = std::optional<std::string>;
using CxxSet = std::set<double>;
using CxxString = std::string;
using CxxUnorderedMap = std::unordered_map<int, std::string>;
using CxxUnorderedSet = std::unordered_set<std::string>;
using CxxVector = std::vector<float>;

inline CxxMap returnMap() { return {{1, 3}, {2, 2}, {3, 3}}; }

inline CxxOptional returnOptional() { return {"In optional!"}; }
inline CxxOptional returnEmtpyOptional() { return {}; }

inline CxxSet returnSet() { return {4.2, 3.7, 9.2}; }

inline CxxString returnString() { return "Hello from C++!"; }

inline CxxUnorderedMap returnUnorderedMap() {
return {{1, "one"}, {2, "two"}, {3, "three"}};
}

inline CxxUnorderedSet returnUnorderedSet() {
return {"first", "second", "third"};
}

inline CxxVector returnVector() { return {4.2, 3.7, 9.2}; }