Skip to content

Commit 64367ff

Browse files
Xazax-hunGabor Horvath
authored andcommitted
[6.2][cxx-interop] Only swiftify template instantiations behind type aliases
Explanation: C++ template instantiations that are not behind type aliases don't have corresponding Swift names that are both syntactically and semantically valid types. This PR prevents generating swiftified overloads for those types. Issue: rdar://151422108 Risk: Low, we swiftify functions less often. Testing: Regression test added. Original PR: #81973 Reviewer: @hnrklssn
1 parent 4051ea2 commit 64367ff

File tree

3 files changed

+47
-10
lines changed

3 files changed

+47
-10
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,9 @@
6262
#include "clang/AST/DeclObjCCommon.h"
6363
#include "clang/AST/Expr.h"
6464
#include "clang/AST/PrettyPrinter.h"
65-
#include "clang/AST/StmtVisitor.h"
6665
#include "clang/AST/RecordLayout.h"
66+
#include "clang/AST/RecursiveASTVisitor.h"
67+
#include "clang/AST/StmtVisitor.h"
6768
#include "clang/AST/Type.h"
6869
#include "clang/Basic/Specifiers.h"
6970
#include "clang/Basic/TargetInfo.h"
@@ -9123,6 +9124,24 @@ static bool SwiftifiableCAT(const clang::CountAttributedType *CAT) {
91239124
return CAT && CATExprValidator().Visit(CAT->getCountExpr());
91249125
}
91259126

9127+
namespace {
9128+
// Searches for template instantiations that are not behind type aliases.
9129+
// FIXME: make sure the generated code compiles for template
9130+
// instantiations that are not behind type aliases.
9131+
struct UnaliasedInstantiationVisitor
9132+
: clang::RecursiveASTVisitor<UnaliasedInstantiationVisitor> {
9133+
bool hasUnaliasedInstantiation = false;
9134+
9135+
bool TraverseTypedefType(const clang::TypedefType *) { return true; }
9136+
9137+
bool
9138+
VisitTemplateSpecializationType(const clang::TemplateSpecializationType *) {
9139+
hasUnaliasedInstantiation = true;
9140+
return false;
9141+
}
9142+
};
9143+
} // namespace
9144+
91269145
static bool SwiftifiablePointerType(Type swiftType) {
91279146
// don't try to transform any Swift types that _SwiftifyImport doesn't know how to handle
91289147
Type nonnullType = swiftType->lookThroughSingleOptionalType();
@@ -9144,6 +9163,13 @@ void ClangImporter::Implementation::swiftify(FuncDecl *MappedDecl) {
91449163
if (ClangDecl->getNumParams() != MappedDecl->getParameters()->size())
91459164
return;
91469165

9166+
{
9167+
UnaliasedInstantiationVisitor visitor;
9168+
visitor.TraverseType(ClangDecl->getType());
9169+
if (visitor.hasUnaliasedInstantiation)
9170+
return;
9171+
}
9172+
91479173
llvm::SmallString<128> MacroString;
91489174
// We only attach the macro if it will produce an overload. Any __counted_by
91499175
// will produce an overload, since UnsafeBufferPointer is still an improvement

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,12 +165,20 @@ inline SpanOfInt MixedFuncWithMutableSafeWrapper7(int * __counted_by(len) p, int
165165
return SpanOfInt(p, len);
166166
}
167167

168+
template <typename X>
169+
struct S {};
170+
168171
struct SpanWithoutTypeAlias {
169172
std::span<const int> bar() [[clang::lifetimebound]];
170173
void foo(std::span<const int> s [[clang::noescape]]);
174+
void otherTemplatedType(ConstSpanOfInt copy [[clang::noescape]], S<int>);
175+
void otherTemplatedType2(ConstSpanOfInt copy [[clang::noescape]], S<int> *);
171176
};
172177

173178
inline void func(ConstSpanOfInt copy [[clang::noescape]]) {}
174179
inline void mutableKeyword(SpanOfInt copy [[clang::noescape]]) {}
175180

181+
inline void spanWithoutTypeAlias(std::span<const int> s [[clang::noescape]]) {}
182+
inline void mutableSpanWithoutTypeAlias(std::span<int> s [[clang::noescape]]) {}
183+
176184
#endif // TEST_INTEROP_CXX_STDLIB_INPUTS_STD_SPAN_H

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

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// RUN: %FileCheck %s < %t/interface.swift
44

55
// Make sure we trigger typechecking and SIL diagnostics
6-
// RUN: %target-swift-frontend -emit-module -plugin-path %swift-plugin-dir -I %S/Inputs -enable-experimental-feature SafeInteropWrappers -enable-experimental-feature LifetimeDependence -cxx-interoperability-mode=default -strict-memory-safety -warnings-as-errors -Xcc -std=c++20 %s
6+
// RUN: %target-swift-frontend -emit-module -plugin-path %swift-plugin-dir -I %S/Inputs -enable-experimental-feature SafeInteropWrappers -enable-experimental-feature LifetimeDependence -cxx-interoperability-mode=default -strict-memory-safety -warnings-as-errors -verify -Xcc -std=c++20 %s
77

88
// REQUIRES: swift_feature_SafeInteropWrappers
99
// REQUIRES: swift_feature_LifetimeDependence
@@ -34,15 +34,10 @@ import CxxStdlib
3434
// CHECK-NEXT: }
3535
// CHECK: struct SpanWithoutTypeAlias {
3636
// CHECK-NEXT: init()
37-
// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop
38-
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
39-
// CHECK-NEXT: @lifetime(borrow self)
40-
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public mutating func bar() -> Span<CInt>
4137
// CHECK-NEXT: mutating func bar() -> std.{{.*}}span<__cxxConst<CInt>, _C{{.*}}_{{.*}}>
42-
// CHECK-NEXT: /// This is an auto-generated wrapper for safer interop
43-
// CHECK-NEXT: @available(visionOS 1.1, tvOS 12.2, watchOS 5.2, iOS 12.2, macOS 10.14.4, *)
44-
// CHECK-NEXT: @_alwaysEmitIntoClient @_disfavoredOverload public mutating func foo(_ s: Span<CInt>)
4538
// CHECK-NEXT: mutating func foo(_ s: std.{{.*}}span<__cxxConst<CInt>, _C{{.*}}_{{.*}}>)
39+
// CHECK-NEXT: mutating func otherTemplatedType(_ copy: ConstSpanOfInt, _: S<CInt>)
40+
// CHECK-NEXT: mutating func otherTemplatedType2(_ copy: ConstSpanOfInt, _: UnsafeMutablePointer<S<CInt>>!)
4641
// CHECK-NEXT: }
4742

4843
// CHECK: /// This is an auto-generated wrapper for safer interop
@@ -150,7 +145,7 @@ func callMethodWithSafeWrapper(_ x: inout X, s: Span<CInt>) {
150145
}
151146

152147
func callFooBar(_ x: inout SpanWithoutTypeAlias, _ s: ConstSpanOfInt) {
153-
let _: Span<CInt> = x.bar()
148+
let _: Span<CInt> = x.bar() // expected-error {{cannot convert value of type}}
154149
unsafe x.foo(s)
155150
}
156151

@@ -242,3 +237,11 @@ func callMixedFuncWithSafeWrapper7(_ p: UnsafeBufferPointer<CInt>) {
242237
func callMutableKeyword(_ span: inout MutableSpan<CInt>) {
243238
mutableKeyword(&span)
244239
}
240+
241+
func callSpanWithoutTypeAlias(_ span: Span<CInt>) {
242+
spanWithoutTypeAlias(span) // expected-error {{cannot convert value of type}}
243+
}
244+
245+
func callMutableSpanWithoutTypeAlias(_ span: consuming MutableSpan<CInt>) {
246+
mutableSpanWithoutTypeAlias(&span) // expected-error {{cannot convert value of type}}
247+
}

0 commit comments

Comments
 (0)