Skip to content

Commit 4590d55

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 5d24373 commit 4590d55

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"
@@ -9119,6 +9120,24 @@ namespace {
91199120
};
91209121
} // namespace
91219122

9123+
namespace {
9124+
// Searches for template instantiations that are not behind type aliases.
9125+
// FIXME: make sure the generated code compiles for template
9126+
// instantiations that are not behind type aliases.
9127+
struct UnaliasedInstantiationVisitor
9128+
: clang::RecursiveASTVisitor<UnaliasedInstantiationVisitor> {
9129+
bool hasUnaliasedInstantiation = false;
9130+
9131+
bool TraverseTypedefType(const clang::TypedefType *) { return true; }
9132+
9133+
bool
9134+
VisitTemplateSpecializationType(const clang::TemplateSpecializationType *) {
9135+
hasUnaliasedInstantiation = true;
9136+
return false;
9137+
}
9138+
};
9139+
} // namespace
9140+
91229141
// Don't try to transform any Swift types that _SwiftifyImport doesn't know how
91239142
// to handle.
91249143
static bool SwiftifiableCountedByPointerType(Type swiftType) {
@@ -9173,6 +9192,13 @@ void ClangImporter::Implementation::swiftify(AbstractFunctionDecl *MappedDecl) {
91739192
if (ClangDecl->getNumParams() != MappedDecl->getParameters()->size())
91749193
return;
91759194

9195+
{
9196+
UnaliasedInstantiationVisitor visitor;
9197+
visitor.TraverseType(ClangDecl->getType());
9198+
if (visitor.hasUnaliasedInstantiation)
9199+
return;
9200+
}
9201+
91769202
llvm::SmallString<128> MacroString;
91779203
// We only attach the macro if it will produce an overload. Any __counted_by
91789204
// 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 Lifetimes -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 Lifetimes -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_Lifetimes
@@ -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)