Skip to content

Commit 3bbb126

Browse files
authored
Merge pull request #78522 from swiftlang/gaborh/instantiation-unsafe
[cxx-interop] Check the safety of C++ template arguments
2 parents 752cb36 + f12b48a commit 3bbb126

File tree

2 files changed

+61
-1
lines changed

2 files changed

+61
-1
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2194,6 +2194,39 @@ namespace {
21942194
dc);
21952195
Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}] = result;
21962196

2197+
// We have to do this after populating ImportedDecls to avoid importing
2198+
// the same multiple times.
2199+
if (Impl.SwiftContext.LangOpts.hasFeature(Feature::SafeInterop) &&
2200+
Impl.SwiftContext.LangOpts.hasFeature(
2201+
Feature::AllowUnsafeAttribute)) {
2202+
if (const auto *ctsd =
2203+
dyn_cast<clang::ClassTemplateSpecializationDecl>(decl)) {
2204+
for (auto arg : ctsd->getTemplateArgs().asArray()) {
2205+
llvm::SmallVector<clang::TemplateArgument, 1> nonPackArgs;
2206+
if (arg.getKind() == clang::TemplateArgument::Pack) {
2207+
auto pack = arg.getPackAsArray();
2208+
nonPackArgs.assign(pack.begin(), pack.end());
2209+
} else {
2210+
nonPackArgs.push_back(arg);
2211+
}
2212+
for (auto realArg : nonPackArgs) {
2213+
if (realArg.getKind() != clang::TemplateArgument::Type)
2214+
continue;
2215+
auto SwiftType = Impl.importTypeIgnoreIUO(
2216+
realArg.getAsType(), ImportTypeKind::Abstract,
2217+
[](Diagnostic &&diag) {}, false, Bridgeability::None,
2218+
ImportTypeAttrs());
2219+
if (SwiftType && SwiftType->isUnsafe()) {
2220+
auto attr =
2221+
new (Impl.SwiftContext) UnsafeAttr(/*implicit=*/true);
2222+
result->getAttrs().add(attr);
2223+
break;
2224+
}
2225+
}
2226+
}
2227+
}
2228+
}
2229+
21972230
if (recordHasMoveOnlySemantics(decl)) {
21982231
if (decl->isInStdNamespace() && decl->getName() == "promise") {
21992232
// Do not import std::promise.
@@ -8405,6 +8438,13 @@ static bool importAsUnsafe(ClangImporter::Implementation &impl,
84058438
if (isa<ClassDecl>(MappedDecl))
84068439
return false;
84078440

8441+
// Most STL containers have std::allocator as their default allocator. We need
8442+
// to consider std::allocator safe for the STL containers to be ever
8443+
// considered safe.
8444+
if (decl->isInStdNamespace() && decl->getIdentifier() &&
8445+
decl->getName() == "allocator")
8446+
return false;
8447+
84088448
if (const auto *record = dyn_cast<clang::RecordDecl>(decl))
84098449
return evaluateOrDefault(
84108450
context.evaluator,

test/Interop/Cxx/class/safe-interop-mode.swift

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ module Test {
1818
//--- Inputs/nonescapable.h
1919
#include "swift/bridging"
2020
#include <span>
21+
#include <vector>
22+
#include <tuple>
2123

2224
struct SWIFT_NONESCAPABLE View {
2325
__attribute__((swift_attr("@lifetime(immortal)")))
@@ -54,6 +56,10 @@ struct MyContainer {
5456

5557
using SpanOfInt = std::span<int>;
5658
using SpanOfIntAlias = SpanOfInt;
59+
using VecOfPtr = std::vector<int*>;
60+
using VecOfInt = std::vector<int>;
61+
using SafeTuple = std::tuple<int, int, int>;
62+
using UnsafeTuple = std::tuple<int, int*, int>;
5763

5864
//--- test.swift
5965

@@ -85,7 +91,21 @@ func useCfType(x: CFArray) {
8591
func useString(x: std.string) {
8692
}
8793

88-
// expected-warning@+1{{global function 'useCppSpan' has an interface that is not memory-safe}}
94+
// expected-warning@+1{{global function 'useVecOfPtr' has an interface that is not memory-safe; use '@unsafe' to indicate that its use is unsafe}}
95+
func useVecOfPtr(x: VecOfPtr) { // expected-note{{reference to unsafe type alias 'VecOfPtr'}}
96+
}
97+
98+
func useVecOfInt(x: VecOfInt) {
99+
}
100+
101+
func useSafeTuple(x: SafeTuple) {
102+
}
103+
104+
// expected-warning@+1{{global function 'useUnsafeTuple' has an interface that is not memory-safe; use '@unsafe' to indicate that its use is unsafe}}
105+
func useUnsafeTuple(x: UnsafeTuple) { // expected-note{{reference to unsafe type alias 'UnsafeTuple'}}
106+
}
107+
108+
// expected-warning@+1{{global function 'useCppSpan' has an interface that is not memory-safe; use '@unsafe' to indicate that its use is unsafe}}
89109
func useCppSpan(x: SpanOfInt) { // expected-note{{reference to unsafe type alias 'SpanOfInt'}}
90110
}
91111

0 commit comments

Comments
 (0)