Skip to content

Commit e2ab10b

Browse files
authored
Merge pull request #81973 from swiftlang/gaborh/disable-non-aliased-instantiations
[cxx-interop] Only swiftify template instantiations behind type aliases
2 parents f5b30b0 + 868c85d commit e2ab10b

File tree

3 files changed

+48
-10
lines changed

3 files changed

+48
-10
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 28 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"
@@ -9180,6 +9181,25 @@ static bool SwiftifiableCAT(const clang::ASTContext &ctx,
91809181
: SwiftifiableCountedByPointerType(swiftType));
91819182
}
91829183

9184+
namespace {
9185+
9186+
// Searches for template instantiations that are not behind type aliases.
9187+
// FIXME: make sure the generated code compiles for template
9188+
// instantiations that are not behind type aliases.
9189+
struct UnaliasedInstantiationVisitor
9190+
: clang::RecursiveASTVisitor<UnaliasedInstantiationVisitor> {
9191+
bool hasUnaliasedInstantiation = false;
9192+
9193+
bool TraverseTypedefType(const clang::TypedefType *) { return true; }
9194+
9195+
bool
9196+
VisitTemplateSpecializationType(const clang::TemplateSpecializationType *) {
9197+
hasUnaliasedInstantiation = true;
9198+
return false;
9199+
}
9200+
};
9201+
} // namespace
9202+
91839203
void ClangImporter::Implementation::swiftify(AbstractFunctionDecl *MappedDecl) {
91849204
if (!SwiftContext.LangOpts.hasFeature(Feature::SafeInteropWrappers))
91859205
return;
@@ -9191,6 +9211,13 @@ void ClangImporter::Implementation::swiftify(AbstractFunctionDecl *MappedDecl) {
91919211
if (ClangDecl->getNumParams() != MappedDecl->getParameters()->size())
91929212
return;
91939213

9214+
{
9215+
UnaliasedInstantiationVisitor visitor;
9216+
visitor.TraverseType(ClangDecl->getType());
9217+
if (visitor.hasUnaliasedInstantiation)
9218+
return;
9219+
}
9220+
91949221
llvm::SmallString<128> MacroString;
91959222
// We only attach the macro if it will produce an overload. Any __counted_by
91969223
// 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)