Skip to content

Commit 00afb8b

Browse files
authored
Merge pull request #82076 from hnrklssn/skip-bounds-safety-types2
When instantiating templated functions with pointers to the templated type, the ClangImporter does not strip type sugar. This strips type sugar for bounds attributes, to make sure that they import the same regardless of whether they are parsed or not. rdar://151041990
2 parents 276261c + bd714f5 commit 00afb8b

File tree

3 files changed

+87
-0
lines changed

3 files changed

+87
-0
lines changed

lib/ClangImporter/ImportType.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2282,6 +2282,7 @@ ImportedType ClangImporter::Implementation::importFunctionReturnType(
22822282
}
22832283

22842284
clang::QualType returnType = desugarIfElaborated(clangDecl->getReturnType());
2285+
returnType = desugarIfBoundsAttributed(returnType);
22852286
// In C interop mode, the return type of library builtin functions
22862287
// like 'memcpy' from headers like 'string.h' drops
22872288
// any nullability specifiers from their return type, and preserves it on the
@@ -2388,6 +2389,7 @@ ImportedType ClangImporter::Implementation::importFunctionParamsAndReturnType(
23882389
ImportDiagnosticAdder addDiag(*this, clangDecl,
23892390
clangDecl->getSourceRange().getBegin());
23902391
clang::QualType returnType = desugarIfElaborated(clangDecl->getReturnType());
2392+
returnType = desugarIfBoundsAttributed(returnType);
23912393

23922394
ImportedType importedType = importer::findOptionSetEnum(returnType, *this);
23932395

@@ -2454,6 +2456,7 @@ ClangImporter::Implementation::importParameterType(
24542456
ArrayRef<GenericTypeParamDecl *> genericParams,
24552457
llvm::function_ref<void(Diagnostic &&)> addImportDiagnosticFn) {
24562458
auto paramTy = desugarIfElaborated(param->getType());
2459+
paramTy = desugarIfBoundsAttributed(paramTy);
24572460

24582461
ImportTypeKind importKind = paramIsCompletionHandler
24592462
? ImportTypeKind::CompletionHandlerParameter

lib/ClangImporter/ImporterImpl.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2102,6 +2102,22 @@ inline clang::QualType desugarIfElaborated(clang::QualType type) {
21022102
return type;
21032103
}
21042104

2105+
inline clang::QualType desugarIfBoundsAttributed(clang::QualType type) {
2106+
if (auto BAT = dyn_cast<clang::BoundsAttributedType>(type))
2107+
return BAT->desugar();
2108+
if (auto VT = dyn_cast<clang::ValueTerminatedType>(type))
2109+
return VT->desugar();
2110+
if (auto AT = dyn_cast<clang::AttributedType>(type))
2111+
switch (AT->getAttrKind()) {
2112+
case clang::attr::PtrUnsafeIndexable:
2113+
case clang::attr::PtrSingle:
2114+
return AT->desugar();
2115+
default:
2116+
break;
2117+
}
2118+
return type;
2119+
}
2120+
21052121
/// Option set enums are sometimes imported as typedefs which assign a name to
21062122
/// the type, but are unavailable in Swift.
21072123
///
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// REQUIRES: swift_feature_SafeInteropWrappers
2+
3+
// RUN: rm -rf %t
4+
// RUN: split-file %s %t
5+
// RUN: %target-swift-frontend -plugin-path %swift-plugin-dir -I %t/Inputs -cxx-interoperability-mode=default -enable-experimental-feature SafeInteropWrappers %t/template.swift -dump-macro-expansions -emit-ir -o %t/out -verify
6+
// RUN: %target-swift-ide-test -plugin-path %swift-plugin-dir -I %t/Inputs -cxx-interoperability-mode=default -enable-experimental-feature SafeInteropWrappers -print-module -module-to-print=Template -source-filename=x | %FileCheck %s
7+
8+
// CHECK: func cb_template<T>(_ p: UnsafePointer<T>, _ size: Int{{.*}}) -> UnsafePointer<T>
9+
// CHECK: func eb_template<T>(_ p: UnsafePointer<T>, _ end: UnsafePointer<T>) -> UnsafePointer<T>
10+
// CHECK: func s_template<T>(_ p: UnsafePointer<T>) -> UnsafePointer<T>
11+
// CHECK: func ui_template<T>(_ p: UnsafePointer<T>) -> UnsafePointer<T>
12+
13+
//--- Inputs/module.modulemap
14+
module Template {
15+
header "template.h"
16+
requires cplusplus
17+
}
18+
19+
//--- Inputs/template.h
20+
#include <ptrcheck.h>
21+
#include <lifetimebound.h>
22+
23+
template <class T>
24+
inline const T* __counted_by(size) cb_template(const T* __counted_by(size) p __noescape, int size) { return p; }
25+
26+
template <class T>
27+
inline const T* __ended_by(end) eb_template(const T* __ended_by(end) p __noescape, const T* end) { return p; }
28+
29+
template <class T>
30+
inline const T* __single s_template(const T* __single p) { return p; }
31+
32+
template <class T>
33+
inline const T* __unsafe_indexable ui_template(const T* __unsafe_indexable p) { return p; }
34+
35+
// FIXME: parse null_terminated in templated contexts
36+
// template <class T>
37+
// inline const T* __null_terminated nt_template(const T* __null_terminated p) {}
38+
39+
//--- template.swift
40+
import Template
41+
42+
// make sure the original functions are still available when parsing bounds attributes
43+
func testOriginalCB(p: UnsafePointer<CInt>, len: CInt) {
44+
let _ = cb_template(p, len)
45+
}
46+
func testOriginalEB(p: UnsafePointer<CInt>, end: UnsafePointer<CInt>) {
47+
let _ = eb_template(p, end)
48+
}
49+
func testOriginalS(s: UnsafePointer<CInt>) {
50+
let _ = s_template(s)
51+
}
52+
func testOriginalUI(s: UnsafePointer<CInt>) {
53+
let _ = ui_template(s)
54+
}
55+
56+
// FIXME: generate safe overloads for templated functions (rdar://151481042)
57+
func testSafeOverloadCB(s: Span<CInt>) {
58+
// expected-error@+3{{generic parameter 'T' could not be inferred}}
59+
// expected-error@+2{{cannot convert value of type 'Span<CInt>'}}
60+
// expected-error@+1{{missing argument for parameter #2 in call}}
61+
cb_template(s)
62+
}
63+
func testSafeOverloadEB(s: Span<CInt>) {
64+
// expected-error@+3{{generic parameter 'T' could not be inferred}}
65+
// expected-error@+2{{cannot convert value of type 'Span<CInt>'}}
66+
// expected-error@+1{{missing argument for parameter #2 in call}}
67+
eb_template(s)
68+
}

0 commit comments

Comments
 (0)