Skip to content

Commit f4ebef9

Browse files
author
Gabor Horvath
committed
[cxx-interop] Support generic types with isValueType trait
In some circumstances the missing trait resulted in picking the wrong branch of some compile time conditionals resulting in code that would not compile. rdar://126709253
1 parent c998bbc commit f4ebef9

File tree

4 files changed

+39
-5
lines changed

4 files changed

+39
-5
lines changed

lib/PrintAsClang/PrintClangValueType.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -675,14 +675,14 @@ void ClangValueTypePrinter::printTypeGenericTraits(
675675
os << "> = true;\n";
676676
}
677677

678-
if (!isa<ClassDecl>(typeDecl) && !typeDecl->hasClangNode() &&
679-
typeMetadataFuncRequirements.empty()) {
680-
// FIXME: generic support.
681-
os << "template<>\n";
678+
if (!isa<ClassDecl>(typeDecl) && !typeDecl->hasClangNode()) {
679+
assert(NTD && "not a nominal type?");
680+
if (printer.printNominalTypeOutsideMemberDeclTemplateSpecifiers(NTD))
681+
os << "template<>\n";
682682
os << "static inline const constexpr bool isValueType<";
683683
printer.printBaseName(typeDecl->getModuleContext());
684684
os << "::";
685-
printer.printBaseName(typeDecl);
685+
printer.printNominalTypeReference(NTD, moduleContext);
686686
os << "> = true;\n";
687687
}
688688
if (isOpaqueLayout) {
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: split-file %s %t
3+
4+
// RUN: %target-swift-frontend -typecheck %t/generics.swift -typecheck -module-name Generics -enable-experimental-cxx-interop -emit-clang-header-path %t/Generics-Swift.h
5+
6+
// RUN: %target-interop-build-clangxx -fno-exceptions -std=gnu++20 -c %t/generics.cpp -I %t -o %t/generics.o
7+
// RUN: %target-build-swift %t/generics.swift -o %t/generics -Xlinker %t/generics.o -module-name Generics -Xfrontend -entry-point-function-name -Xfrontend swiftMain
8+
9+
//--- generics.swift
10+
11+
public struct MyClass<T> {
12+
public var a: T
13+
public init(_ p: T) { self.a = p }
14+
}
15+
16+
public func genericFunc<T>(_ p: T) -> T {
17+
return p
18+
}
19+
20+
//--- generics.cpp
21+
22+
#import "Generics-Swift.h"
23+
using namespace Generics;
24+
25+
int main() {
26+
auto c = MyClass<int>::init(10);
27+
auto result = genericFunc<MyClass<int>>(c);
28+
}

test/Interop/SwiftToCxx/generics/generic-struct-in-cxx.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,11 @@ public func inoutConcretePair(_ x: UInt16, _ y: inout GenericPair<UInt16, UInt16
284284
// CHECK-NEXT: #ifdef __cpp_concepts
285285
// CHECK-NEXT: requires swift::isUsableInGenericContext<T_0_0> && swift::isUsableInGenericContext<T_0_1>
286286
// CHECK-NEXT: #endif // __cpp_concepts
287+
// CHECK-NEXT: static inline const constexpr bool isValueType<Generics::GenericPair<T_0_0, T_0_1>> = true;
288+
// CHECK-NEXT: template<class T_0_0, class T_0_1>
289+
// CHECK-NEXT: #ifdef __cpp_concepts
290+
// CHECK-NEXT: requires swift::isUsableInGenericContext<T_0_0> && swift::isUsableInGenericContext<T_0_1>
291+
// CHECK-NEXT: #endif // __cpp_concepts
287292
// CHECK-NEXT: static inline const constexpr bool isOpaqueLayout<Generics::GenericPair<T_0_0, T_0_1>> = true;
288293
// CHECK-NEXT: template<class T_0_0, class T_0_1>
289294
// CHECK-NEXT: #ifdef __cpp_concepts

test/Interop/SwiftToCxx/stdlib/swift-stdlib-in-cxx.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
// CHECK: template<class T_0_0>
5050
// CHECK: template<class T_0_0>
5151
// CHECK: template<class T_0_0>
52+
// CHECK: template<class T_0_0>
5253
// CHECK-NEXT: #ifdef __cpp_concepts
5354
// CHECK-NEXT: requires swift::isUsableInGenericContext<T_0_0>
5455
// CHECK-NEXT: #endif

0 commit comments

Comments
 (0)