Files
swift-mirror/test/Interop/SwiftToCxx/generics/generic-enum-execution.cpp
Gabor Horvath b5384bc8a6 [cxx-interop] Support optional generic cases in enums
This PR implements proper support for optional generic associated values
in enum cases. Most of the code changes are supporting generic types in
more contexts in the printer, the rest are making sure we handle the
null pointer case when we try to get the declaration from the type that
represents a generic parameter.

rdar://131112273
2024-07-09 16:08:27 +01:00

137 lines
4.0 KiB
C++

// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend %S/generic-enum-in-cxx.swift -typecheck -module-name Generics -clang-header-expose-decls=all-public -emit-clang-header-path %t/generics.h
// RUN: %target-interop-build-clangxx -std=gnu++20 -c %s -I %t -o %t/swift-generics-execution.o
// RUN: %target-interop-build-swift %S/generic-enum-in-cxx.swift -o %t/swift-generics-execution -Xlinker %t/swift-generics-execution.o -module-name Generics -Xfrontend -entry-point-function-name -Xfrontend swiftMain
// RUN: %target-codesign %t/swift-generics-execution
// RUN: %target-run %t/swift-generics-execution | %FileCheck %s
// REQUIRES: executable_test
#include "generics.h"
#include <cassert>
#include <cstdio>
extern "C" size_t swift_retainCount(void * _Nonnull obj);
size_t getRetainCount(const Generics::TracksDeinit & swiftClass) {
void *p = swift::_impl::_impl_RefCountedClass::getOpaquePointer(swiftClass);
return swift_retainCount(p);
}
int main() {
using namespace Generics;
{
auto x = makeGenericOpt<int>(42);
takeGenericOpt(x);
// CHECK: some(42)
inoutGenericOpt(x, -11);
takeGenericOpt(x);
// CHECK-NEXT: none
inoutGenericOpt(x, -11);
takeGenericOpt(x);
// CHECK-NEXT: some(-11)
x.method();
// CHECK-NEXT: GenericOpt<T>::testme::some(-11);
assert(x.getComputedProp() == 42);
assert(x.isSome());
auto val = x.getSome();
assert(val == -11);
x.reset();
assert(x.isNone());
assert(x.genericMethod<double>(5.25) == 5.25);
// CHECK-NEXT: GenericOpt<T>::genericMethod<T>::none,5.25;
}
{
auto x = makeConcreteOpt(0xFA);
takeConcreteOpt(x);
// CHECK-NEXT: CONCRETE opt: some(250) ;
inoutConcreteOpt(x);
takeConcreteOpt(x);
// CHECK-NEXT: CONCRETE opt: some(750) ;
inoutConcreteOpt(x);
takeConcreteOpt(x);
// CHECK-NEXT: CONCRETE opt: some(2250) ;
x.method();
// CHECK-NEXT: GenericOpt<T>::testme::some(2250);
assert(x.getComputedProp() == 42);
assert(x.isSome());
auto val = x.getSome();
assert(val == 2250);
x.reset();
assert(x.isNone());
assert(x.genericMethod<double>(-1.25) == -1.25);
// CHECK-NEXT: GenericOpt<T>::genericMethod<T>::none,-1.25;
}
{
auto x = makeGenericOpt<StructForEnum>(StructForEnum::init());
auto val = x.getSome();
// CHECK-NEXT: init-TracksDeinit
// CHECK-NEXT: destroy-TracksDeinit
}
{
auto ptr = constructTracksDeinit();
// CHECK-NEXT: init-TracksDeinit
assert(getRetainCount(ptr) == 1);
{
auto x = makeGenericOpt<TracksDeinit>(ptr);
assert(getRetainCount(ptr) == 2);
auto ptr2 = x.getSome();
assert(getRetainCount(ptr) == 3);
}
puts("after some");
assert(getRetainCount(ptr) == 1);
// CHECK-NEXT: after some
// CHECK-NEXT: destroy-TracksDeinit
}
{
auto x = GenericOpt<int>::some(14);
takeGenericOpt(x);
assert(x.isSome());
assert(x.getSome() == 14);
// CHECK-NEXT: some(14)
auto y = GenericOpt<int>::none();
takeGenericOpt(y);
assert(y.isNone());
// CHECK-NEXT: none
}
{
auto x = GenericOpt<StructForEnum>::some(StructForEnum::init());
takeGenericOpt(x);
assert(x.isSome());
// CHECK-NEXT: init-TracksDeinit
// CHECK-NEXT: some(Generics.StructForEnum(x: Generics.TracksDeinit))
// CHECK-NEXT: destroy-TracksDeinit
auto y = GenericOpt<StructForEnum>::none();
assert(y.isNone());
}
{
auto ptr = constructTracksDeinit();
// CHECK-NEXT: init-TracksDeinit
assert(getRetainCount(ptr) == 1);
{
auto x = GenericOpt<TracksDeinit>::some(ptr);
assert(getRetainCount(ptr) == 2);
auto ptr2 = x.getSome();
assert(getRetainCount(ptr) == 3);
}
puts("after some");
assert(getRetainCount(ptr) == 1);
// CHECK-NEXT: after some
// CHECK-NEXT: destroy-TracksDeinit
}
{
auto opt = swift::Optional<int>::some(14);
auto x = GenericCustomType<int>::success(opt);
auto y = x;
assert(y.isSuccess());
assert(y.getSuccess().getSome() == 14);
}
puts("EOF");
// CHECK-NEXT: EOF
return 0;
}