Skip to content

Commit 1159332

Browse files
author
Gabor Horvath
committed
[cxx-interop] Fix transforming spans that are not behind type aliases
While we expect our users to use type aliases for template instantiations, there are some contexts when we import instantiations without aliases. Unfortunately, in case of C++ span we generated a name for the instantiation that cannot be a syntactically valid Swift type due to unary negation appearing in the type name. This PR replaces the unary negation with "Neg" in the type name and also fixed a bug that ended up printing certain unsigned values as signed. Moreover, this PR also fixes some other fallouts in the SwiftifyImport macro. rdar://146833480
1 parent 1bd0cd7 commit 1159332

File tree

6 files changed

+44
-15
lines changed

6 files changed

+44
-15
lines changed

lib/ClangImporter/ClangClassTemplateNamePrinter.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,12 @@ struct TemplateArgumentPrinter
203203
if (arg.getIntegralType()->isBuiltinType()) {
204204
buffer << typePrinter.Visit(arg.getIntegralType().getTypePtr()) << "_";
205205
}
206-
arg.getAsIntegral().print(buffer, true);
206+
auto value = arg.getAsIntegral();
207+
if (value.isNegative()) {
208+
value.negate();
209+
buffer << "Neg_";
210+
}
211+
value.print(buffer, arg.getIntegralType()->isSignedIntegerType());
207212
}
208213

209214
void VisitPackTemplateArgument(const clang::TemplateArgument &arg,

lib/Macros/Sources/SwiftMacros/SwiftifyImportMacro.swift

+17-14
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,13 @@ enum Mutability {
168168
case Mutable
169169
}
170170

171+
func getUnattributedType(_ type: TypeSyntax) -> TypeSyntax {
172+
if let attributedType = type.as(AttributedTypeSyntax.self) {
173+
return attributedType.baseType.trimmed
174+
}
175+
return type.trimmed
176+
}
177+
171178
func getTypeName(_ type: TypeSyntax) throws -> TokenSyntax {
172179
switch type.kind {
173180
case .memberType:
@@ -410,7 +417,7 @@ struct CxxSpanThunkBuilder: ParamPointerBoundsThunkBuilder {
410417
func buildFunctionSignature(_ argTypes: [Int: TypeSyntax?], _ returnType: TypeSyntax?) throws
411418
-> (FunctionSignatureSyntax, Bool) {
412419
var types = argTypes
413-
let typeName = try getTypeName(oldType).text
420+
let typeName = getUnattributedType(oldType).description
414421
guard let desugaredType = typeMappings[typeName] else {
415422
throw DiagnosticError(
416423
"unable to desugar type with name '\(typeName)'", node: node)
@@ -426,7 +433,7 @@ struct CxxSpanThunkBuilder: ParamPointerBoundsThunkBuilder {
426433

427434
func buildFunctionCall(_ pointerArgs: [Int: ExprSyntax]) throws -> ExprSyntax {
428435
var args = pointerArgs
429-
let typeName = try getTypeName(oldType).text
436+
let typeName = getUnattributedType(oldType).description
430437
assert(args[index] == nil)
431438
args[index] = ExprSyntax("\(raw: typeName)(\(raw: name))")
432439
return try base.buildFunctionCall(args)
@@ -446,7 +453,7 @@ struct CxxSpanReturnThunkBuilder: BoundsCheckedThunkBuilder {
446453
func buildFunctionSignature(_ argTypes: [Int: TypeSyntax?], _ returnType: TypeSyntax?) throws
447454
-> (FunctionSignatureSyntax, Bool) {
448455
assert(returnType == nil)
449-
let typeName = try getTypeName(signature.returnClause!.type).text
456+
let typeName = getUnattributedType(signature.returnClause!.type).description
450457
guard let desugaredType = typeMappings[typeName] else {
451458
throw DiagnosticError(
452459
"unable to desugar type with name '\(typeName)'", node: node)
@@ -923,19 +930,15 @@ public struct SwiftifyImportMacro: PeerMacro {
923930
return []
924931
}
925932
var result : [ParamInfo] = []
926-
let process = { type, expr, orig in
927-
do {
928-
let typeName = try getTypeName(type).text
929-
if let desugaredType = typeMappings[typeName] {
930-
if let unqualifiedDesugaredType = getUnqualifiedStdName(desugaredType) {
931-
if unqualifiedDesugaredType.starts(with: "span<") {
932-
result.append(CxxSpan(pointerIndex: expr, nonescaping: false,
933-
dependencies: [], typeMappings: typeMappings, original: orig))
934-
}
933+
let process : (TypeSyntax, SwiftifyExpr, SyntaxProtocol) throws -> () = { type, expr, orig in
934+
let typeName = getUnattributedType(type).description
935+
if let desugaredType = typeMappings[typeName] {
936+
if let unqualifiedDesugaredType = getUnqualifiedStdName(desugaredType) {
937+
if unqualifiedDesugaredType.starts(with: "span<") {
938+
result.append(CxxSpan(pointerIndex: expr, nonescaping: false,
939+
dependencies: [], typeMappings: typeMappings, original: orig))
935940
}
936941
}
937-
} catch is DiagnosticError {
938-
// type doesn't match expected pattern
939942
}
940943
}
941944
for (idx, param) in signature.parameterClause.parameters.enumerated() {

test/Interop/Cxx/stdlib/Inputs/std-span.h

+5
Original file line numberDiff line numberDiff line change
@@ -121,4 +121,9 @@ inline ConstSpanOfInt mixedFuncWithSafeWrapper7(const int * __counted_by(len) p,
121121
return ConstSpanOfInt(p, len);
122122
}
123123

124+
struct SpanWithoutTypeAlias {
125+
std::span<const int> bar() [[clang::lifetimebound]];
126+
void foo(std::span<const int> s [[clang::noescape]]);
127+
};
128+
124129
#endif // TEST_INTEROP_CXX_STDLIB_INPUTS_STD_SPAN_H

test/Interop/Cxx/stdlib/std-span-interface.swift

+8
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@ import CxxStdlib
2727
// CHECK-NEXT: @_alwaysEmitIntoClient public mutating func methodWithSafeWrapper(_ s: Span<CInt>)
2828
// CHECK-NEXT: mutating func methodWithSafeWrapper(_ s: ConstSpanOfInt)
2929
// CHECK-NEXT: }
30+
// CHECK: struct SpanWithoutTypeAlias {
31+
// CHECK-NEXT: init()
32+
// CHECK-NEXT: @lifetime(borrow self)
33+
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public mutating func bar() -> Span<CInt>
34+
// CHECK-NEXT: mutating func bar() -> std.{{.*}}span<__cxxConst<CInt>, _C{{.*}}_{{.*}}>
35+
// CHECK-NEXT: @_alwaysEmitIntoClient public mutating func foo(_ s: Span<CInt>)
36+
// CHECK-NEXT: mutating func foo(_ s: std.{{.*}}span<__cxxConst<CInt>, _C{{.*}}_{{.*}}>)
37+
// CHECK-NEXT: }
3038
// CHECK: @_alwaysEmitIntoClient public func funcWithSafeWrapper(_ s: Span<CInt>)
3139
// CHECK-NEXT: @lifetime(s)
3240
// CHECK-NEXT: @_alwaysEmitIntoClient public func funcWithSafeWrapper2(_ s: Span<CInt>) -> Span<CInt>

test/Interop/Cxx/templates/Inputs/class-template-non-type-parameter.h

+7
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,11 @@ template <class T, size_t Size> struct MagicArray { T t[Size]; };
1010
typedef MagicArray<int, 2> MagicIntPair;
1111
typedef MagicArray<int, 3> MagicIntTriple;
1212

13+
template <typename T, T Val>
14+
struct integral_constant {
15+
constexpr static T value = Val;
16+
};
17+
18+
typedef integral_constant<int, -3> NegativeThree;
19+
1320
#endif // TEST_INTEROP_CXX_TEMPLATES_INPUTS_CLASS_TEMPLATE_NON_TYPE_PARAMETER_H

test/Interop/Cxx/templates/class-template-non-type-parameter-module-interface.swift

+1
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@
1717

1818
// CHECK: typealias MagicIntPair = MagicArray<CInt, _C{{.*}}_2>
1919
// CHECK: typealias MagicIntTriple = MagicArray<CInt, _C{{.*}}_3>
20+
// CHECK: typealias NegativeThree = integral_constant<CInt, _C{{.*}}_Neg_3>

0 commit comments

Comments
 (0)