Files
swift-mirror/validation-test/Reflection/reflect_Enum_TwoCaseNoPayload.swift
tbkka 0d361bd3ea Teach RemoteMirror how to project enum values (#30161)
Teach RemoteMirror how to project enum values

This adds two new functions to the SwiftRemoteMirror
facility that support inspecting enum values.

Currently, these support non-payload enums and
single-payload enums, including nested enums and
payloads with struct, tuple, and reference payloads.
In particular, it handles nested `Optional` types.

TODO: Multi-payload enums use different strategies for
encoding the cases that aren't yet supported by this
code.

Note: This relies on information from dataLayoutQuery
to correctly decode invalid pointer values that are used
to encode enums.  Existing clients will need to augment
their DLQ functions before using these new APIs.

Resolves rdar://59961527

```
/// Projects the value of an enum.
///
/// Takes the address and typeref for an enum and determines the
/// index of the currently-selected case within the enum.
///
/// Returns true iff the enum case could be successfully determined.
/// In particular, note that this code may fail for valid in-memory data
/// if the compiler is using a strategy we do not yet understand.
SWIFT_REMOTE_MIRROR_LINKAGE
int swift_reflection_projectEnumValue(SwiftReflectionContextRef ContextRef,
                                      swift_addr_t EnumAddress,
                                      swift_typeref_t EnumTypeRef,
                                      uint64_t *CaseIndex);

/// Finds information about a particular enum case.
///
/// Given an enum typeref and index of a case, returns:
/// * Typeref of the associated payload or zero if there is no payload
/// * Name of the case if known.
///
/// The Name points to a freshly-allocated C string on the heap.  You
/// are responsible for freeing the string (via `free()`) when you are finished.
SWIFT_REMOTE_MIRROR_LINKAGE
int swift_reflection_getEnumCaseTypeRef(SwiftReflectionContextRef ContextRef,
                                        swift_typeref_t EnumTypeRef,
                                        unsigned CaseIndex,
                                        char **CaseName,
                                        swift_typeref_t *PayloadTypeRef);
```


Co-authored-by: Mike Ash <mikeash@apple.com>
2020-03-06 13:17:40 -08:00

257 lines
11 KiB
Swift

// RUN: %empty-directory(%t)
// RUN: %target-build-swift -g -lswiftSwiftReflectionTest %s -o %t/reflect_Enum_TwoCaseNoPayload
// RUN: %target-codesign %t/reflect_Enum_TwoCaseNoPayload
// RUN: %target-run %target-swift-reflection-test %t/reflect_Enum_TwoCaseNoPayload | %FileCheck %s --check-prefix=CHECK-%target-ptrsize
// REQUIRES: objc_interop
// REQUIRES: executable_test
// UNSUPPORTED: use_os_stdlib
import SwiftReflectionTest
struct Marker {
let value = 1
}
enum TwoCaseNoPayloadEnum {
case preferred
case other
}
class ClassWithTwoCaseNoPayloadEnum {
var e1: TwoCaseNoPayloadEnum?
var e2: TwoCaseNoPayloadEnum = .preferred
var e3: TwoCaseNoPayloadEnum = .other
var e4: TwoCaseNoPayloadEnum? = .preferred
var e5: TwoCaseNoPayloadEnum? = .other
let marker = Marker()
}
reflect(object: ClassWithTwoCaseNoPayloadEnum())
// CHECK-64: Reflecting an object.
// CHECK-64: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-64: Type reference:
// CHECK-64: (class reflect_Enum_TwoCaseNoPayload.ClassWithTwoCaseNoPayloadEnum)
// CHECK-64: Type info:
// CHECK-64: (class_instance size=32 alignment=8 stride=32 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-64: (field name=e1 offset=16
// CHECK-64: (single_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=253 bitwise_takable=1
// CHECK-64: (case name=some index=0 offset=0
// CHECK-64: (no_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1
// CHECK-64: (case name=preferred index=0)
// CHECK-64: (case name=other index=1)))
// CHECK-64: (case name=none index=1)))
// CHECK-64: (field name=e2 offset=17
// CHECK-64: (no_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1
// CHECK-64: (case name=preferred index=0)
// CHECK-64: (case name=other index=1)))
// CHECK-64: (field name=e3 offset=18
// CHECK-64: (no_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1
// CHECK-64: (case name=preferred index=0)
// CHECK-64: (case name=other index=1)))
// CHECK-64: (field name=e4 offset=19
// CHECK-64: (single_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=253 bitwise_takable=1
// CHECK-64: (case name=some index=0 offset=0
// CHECK-64: (no_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1
// CHECK-64: (case name=preferred index=0)
// CHECK-64: (case name=other index=1)))
// CHECK-64: (case name=none index=1)))
// CHECK-64: (field name=e5 offset=20
// CHECK-64: (single_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=253 bitwise_takable=1
// CHECK-64: (case name=some index=0 offset=0
// CHECK-64: (no_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1
// CHECK-64: (case name=preferred index=0)
// CHECK-64: (case name=other index=1)))
// CHECK-64: (case name=none index=1)))
// CHECK-64: (field name=marker offset=24
// CHECK-64: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-64: (field name=value offset=0
// CHECK-64: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-64: (field name=_value offset=0
// CHECK-64: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1)))))))
// CHECK-32: Reflecting an object.
// CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-32: Type reference:
// CHECK-32: (class reflect_Enum_TwoCaseNoPayload.ClassWithTwoCaseNoPayloadEnum)
// CHECK-32: Type info:
// CHECK-32: (class_instance size=20 alignment=4 stride=20 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-32: (field name=e1 offset=8
// CHECK-32: (single_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=253 bitwise_takable=1
// CHECK-32: (case name=some index=0 offset=0
// CHECK-32: (no_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1
// CHECK-32: (case name=preferred index=0)
// CHECK-32: (case name=other index=1)))
// CHECK-32: (case name=none index=1)))
// CHECK-32: (field name=e2 offset=9
// CHECK-32: (no_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1
// CHECK-32: (case name=preferred index=0)
// CHECK-32: (case name=other index=1)))
// CHECK-32: (field name=e3 offset=10
// CHECK-32: (no_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1
// CHECK-32: (case name=preferred index=0)
// CHECK-32: (case name=other index=1)))
// CHECK-32: (field name=e4 offset=11
// CHECK-32: (single_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=253 bitwise_takable=1
// CHECK-32: (case name=some index=0 offset=0
// CHECK-32: (no_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1
// CHECK-32: (case name=preferred index=0)
// CHECK-32: (case name=other index=1)))
// CHECK-32: (case name=none index=1)))
// CHECK-32: (field name=e5 offset=12
// CHECK-32: (single_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=253 bitwise_takable=1
// CHECK-32: (case name=some index=0 offset=0
// CHECK-32: (no_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1
// CHECK-32: (case name=preferred index=0)
// CHECK-32: (case name=other index=1)))
// CHECK-32: (case name=none index=1)))
// CHECK-32: (field name=marker offset=16
// CHECK-32: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-32: (field name=value offset=0
// CHECK-32: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-32: (field name=_value offset=0
// CHECK-32: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1)))))))
reflect(enum: TwoCaseNoPayloadEnum.preferred)
// CHECK-64: Reflecting an enum.
// CHECK-64: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-64: Type reference:
// CHECK-64: (enum reflect_Enum_TwoCaseNoPayload.TwoCaseNoPayloadEnum)
// CHECK-64: Type info:
// CHECK-64: (no_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1
// CHECK-64: (case name=preferred index=0)
// CHECK-64: (case name=other index=1))
// CHECK-64: Enum value:
// CHECK-64: (enum_value name=preferred index=0)
// CHECK-32: Reflecting an enum.
// CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-32: Type reference:
// CHECK-32: (enum reflect_Enum_TwoCaseNoPayload.TwoCaseNoPayloadEnum)
// CHECK-32: Type info:
// CHECK-32: (no_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1
// CHECK-32: (case name=preferred index=0)
// CHECK-32: (case name=other index=1))
// CHECK-32: Enum value:
// CHECK-32: (enum_value name=preferred index=0)
reflect(enum: TwoCaseNoPayloadEnum.other)
// CHECK-64: Reflecting an enum.
// CHECK-64: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-64: Type reference:
// CHECK-64: (enum reflect_Enum_TwoCaseNoPayload.TwoCaseNoPayloadEnum)
// CHECK-64: Type info:
// CHECK-64: (no_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1
// CHECK-64: (case name=preferred index=0)
// CHECK-64: (case name=other index=1))
// CHECK-64: Enum value:
// CHECK-64: (enum_value name=other index=1)
// CHECK-32: Reflecting an enum.
// CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-32: Type reference:
// CHECK-32: (enum reflect_Enum_TwoCaseNoPayload.TwoCaseNoPayloadEnum)
// CHECK-32: Type info:
// CHECK-32: (no_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1
// CHECK-32: (case name=preferred index=0)
// CHECK-32: (case name=other index=1))
// CHECK-32: Enum value:
// CHECK-32: (enum_value name=other index=1)
reflect(enum: Optional<TwoCaseNoPayloadEnum>.some(.other))
// CHECK-64: Reflecting an enum.
// CHECK-64: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-64: Type reference:
// CHECK-64: (bound_generic_enum Swift.Optional
// CHECK-64: (enum reflect_Enum_TwoCaseNoPayload.TwoCaseNoPayloadEnum))
// CHECK-64: Type info:
// CHECK-64: (single_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=253 bitwise_takable=1
// CHECK-64: (case name=some index=0
// CHECK-64: (no_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1
// CHECK-64: (case name=preferred index=0)
// CHECK-64: (case name=other index=1)))
// CHECK-64: (case name=none index=1))
// CHECK-64: Enum value:
// CHECK-64: (enum_value name=some index=0
// CHECK-64: (enum reflect_Enum_TwoCaseNoPayload.TwoCaseNoPayloadEnum)
// CHECK-64: )
// CHECK-32: Reflecting an enum.
// CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-32: Type reference:
// CHECK-32: (bound_generic_enum Swift.Optional
// CHECK-32: (enum reflect_Enum_TwoCaseNoPayload.TwoCaseNoPayloadEnum))
// CHECK-32: Type info:
// CHECK-32: (single_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=253 bitwise_takable=1
// CHECK-32: (case name=some index=0
// CHECK-32: (no_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1
// CHECK-32: (case name=preferred index=0)
// CHECK-32: (case name=other index=1)))
// CHECK-32: (case name=none index=1))
// CHECK-32: Enum value:
// CHECK-32: (enum_value name=some index=0
// CHECK-32: (enum reflect_Enum_TwoCaseNoPayload.TwoCaseNoPayloadEnum)
// CHECK-32: )
reflect(enum: Optional<TwoCaseNoPayloadEnum>.none)
// CHECK-64: Reflecting an enum.
// CHECK-64: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-64: Type reference:
// CHECK-64: (bound_generic_enum Swift.Optional
// CHECK-64: (enum reflect_Enum_TwoCaseNoPayload.TwoCaseNoPayloadEnum))
// CHECK-64: Type info:
// CHECK-64: (single_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=253 bitwise_takable=1
// CHECK-64: (case name=some index=0
// CHECK-64: (no_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1
// CHECK-64: (case name=preferred index=0)
// CHECK-64: (case name=other index=1)))
// CHECK-64: (case name=none index=1))
// CHECK-64: Enum value:
// CHECK-64: (enum_value name=none index=1)
// CHECK-32: Reflecting an enum.
// CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-32: Type reference:
// CHECK-32: (bound_generic_enum Swift.Optional
// CHECK-32: (enum reflect_Enum_TwoCaseNoPayload.TwoCaseNoPayloadEnum))
// CHECK-32: Type info:
// CHECK-32: (single_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=253 bitwise_takable=1
// CHECK-32: (case name=some index=0
// CHECK-32: (no_payload_enum size=1 alignment=1 stride=1 num_extra_inhabitants=254 bitwise_takable=1
// CHECK-32: (case name=preferred index=0)
// CHECK-32: (case name=other index=1)))
// CHECK-32: (case name=none index=1))
// CHECK-32: Enum value:
// CHECK-32: (enum_value name=none index=1)
doneReflecting()
// CHECK-64: Done.
// CHECK-32: Done.