Skip to content

Commit d5df5d7

Browse files
committed
Remove funcsWithPointerBounds, add experimental langopt
Pass around hasSafePointer as a parameter flag instead, and only call importBoundsAttributes when the imported function has a parameter or return value with CountAttributedType. Enables importing bounds safety pointers using -enable-experimental-bounds-safety-interop rather than based on a compile time define.
1 parent be1db64 commit d5df5d7

File tree

11 files changed

+102
-84
lines changed

11 files changed

+102
-84
lines changed

include/swift/Basic/LangOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,10 @@ namespace swift {
325325
/// disabled because it is not complete.
326326
bool EnableCXXInterop = false;
327327

328+
/// Enable C interop importing bounds safety and lifetime attributes to
329+
/// generate Swift wrappers with safe pointer types (experimental).
330+
bool EnableBoundsSafetyInterop = false;
331+
328332
/// The C++ interoperability source compatibility version. Defaults
329333
/// to the Swift language version.
330334
version::Version cxxInteropCompatVersion;

include/swift/Option/Options.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,11 @@ def enable_experimental_concise_pound_file : Flag<["-"],
792792
Flags<[FrontendOption, ModuleInterfaceOption]>,
793793
HelpText<"Enable experimental concise '#file' identifier">;
794794

795+
def enable_experimental_bounds_safety_interop :
796+
Flag<["-"], "enable-experimental-bounds-safety-interop">,
797+
Flags<[NoDriverOption, FrontendOption, HelpHidden, ModuleInterfaceOption]>,
798+
HelpText<"Enable experimental C bounds safety interop code generation and config directives">;
799+
795800
def enable_experimental_cxx_interop :
796801
Flag<["-"], "enable-experimental-cxx-interop">,
797802
Flags<[NoDriverOption, FrontendOption, HelpHidden, ModuleInterfaceOption]>,

lib/ClangImporter/ClangImporter.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -576,9 +576,8 @@ void importer::getNormalInvocationArguments(
576576
}
577577
}
578578

579-
#ifdef SWIFT_ENABLE_EXPERIMENTAL_POINTER_BOUNDS
580-
invokationsArgStrs.push_back("-fexperimental-bounds-safety-attributes");
581-
#endif
579+
if (LangOpts.EnableBoundsSafetyInterop)
580+
invocationArgStrs.push_back("-fexperimental-bounds-safety-attributes");
582581

583582
// Set C language options.
584583
if (triple.isOSDarwin()) {

lib/ClangImporter/ImportDecl.cpp

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,8 @@ createFuncOrAccessor(ClangImporter::Implementation &impl, SourceLoc funcLoc,
109109
std::optional<AccessorInfo> accessorInfo, DeclName name,
110110
SourceLoc nameLoc, GenericParamList *genericParams,
111111
ParameterList *bodyParams, Type resultTy, bool async,
112-
bool throws, DeclContext *dc, ClangNode clangNode) {
112+
bool throws, DeclContext *dc, ClangNode clangNode,
113+
bool hasSafePointer) {
113114
FuncDecl *decl;
114115
if (accessorInfo) {
115116
decl = AccessorDecl::create(
@@ -125,7 +126,9 @@ createFuncOrAccessor(ClangImporter::Implementation &impl, SourceLoc funcLoc,
125126
genericParams, dc, clangNode);
126127
}
127128
impl.importSwiftAttrAttributes(decl);
128-
impl.importBoundsAttributes(decl);
129+
if (hasSafePointer)
130+
impl.importBoundsAttributes(decl);
131+
129132
return decl;
130133
}
131134

@@ -3254,7 +3257,8 @@ namespace {
32543257
}
32553258
return Impl.importFunctionParameterList(
32563259
dc, decl, nonSelfParams, decl->isVariadic(), allowNSUIntegerAsInt,
3257-
argNames, genericParams, /*resultType=*/nullptr);
3260+
argNames, genericParams, /*resultType=*/nullptr,
3261+
/*hasSafePointerParam=*/nullptr);
32583262
}
32593263

32603264
Decl *
@@ -3635,6 +3639,7 @@ namespace {
36353639

36363640
bool importFuncWithoutSignature =
36373641
isa<clang::CXXMethodDecl>(decl) && Impl.importSymbolicCXXDecls;
3642+
bool hasSafePointer = false;
36383643
if (!dc->isModuleScopeContext() && !isa<clang::CXXMethodDecl>(decl)) {
36393644
// Handle initializers.
36403645
if (name.getBaseName().isConstructor()) {
@@ -3731,7 +3736,7 @@ namespace {
37313736
importedType = Impl.importFunctionParamsAndReturnType(
37323737
dc, decl, {decl->param_begin(), decl->param_size()},
37333738
decl->isVariadic(), isInSystemModule(dc), name, bodyParams,
3734-
templateParams);
3739+
templateParams, &hasSafePointer);
37353740
}
37363741

37373742
if (auto *mdecl = dyn_cast<clang::CXXMethodDecl>(decl)) {
@@ -3797,11 +3802,10 @@ namespace {
37973802
} else {
37983803
auto resultTy = importedType.getType();
37993804

3800-
FuncDecl *func =
3801-
createFuncOrAccessor(Impl, loc, accessorInfo, name,
3802-
nameLoc, genericParams, bodyParams, resultTy,
3803-
/*async=*/false, /*throws=*/false, dc,
3804-
clangNode);
3805+
FuncDecl *func = createFuncOrAccessor(
3806+
Impl, loc, accessorInfo, name, nameLoc, genericParams, bodyParams,
3807+
resultTy,
3808+
/*async=*/false, /*throws=*/false, dc, clangNode, hasSafePointer);
38053809
result = func;
38063810

38073811
if (!dc->isModuleScopeContext()) {
@@ -4840,12 +4844,13 @@ namespace {
48404844
}
48414845
}
48424846

4843-
auto result = createFuncOrAccessor(Impl,
4844-
/*funcLoc*/ SourceLoc(), accessorInfo,
4845-
importedName.getDeclName(),
4846-
/*nameLoc*/ SourceLoc(),
4847-
/*genericParams=*/nullptr, bodyParams,
4848-
resultTy, async, throws, dc, decl);
4847+
bool hasSafePointer = false; // currently only implemented for functions
4848+
auto result = createFuncOrAccessor(
4849+
Impl,
4850+
/*funcLoc*/ SourceLoc(), accessorInfo, importedName.getDeclName(),
4851+
/*nameLoc*/ SourceLoc(),
4852+
/*genericParams=*/nullptr, bodyParams, resultTy, async, throws, dc,
4853+
decl, hasSafePointer);
48494854

48504855
result->setAccess(decl->isDirectMethod() ? AccessLevel::Public
48514856
: getOverridableAccessLevel(dc));
@@ -6488,7 +6493,8 @@ Decl *SwiftDeclConverter::importGlobalAsInitializer(
64886493
} else {
64896494
parameterList = Impl.importFunctionParameterList(
64906495
dc, decl, {decl->param_begin(), decl->param_end()}, decl->isVariadic(),
6491-
allowNSUIntegerAsInt, argNames, /*genericParams=*/{}, /*resultType=*/nullptr);
6496+
allowNSUIntegerAsInt, argNames, /*genericParams=*/{},
6497+
/*resultType=*/nullptr, /*hasSafePointerParam=*/nullptr);
64926498
}
64936499
if (!parameterList)
64946500
return nullptr;
@@ -8574,12 +8580,13 @@ class PointerParamInfoPrinter {
85748580

85758581
void ClangImporter::Implementation::importBoundsAttributes(
85768582
FuncDecl *MappedDecl) {
8583+
assert(SwiftContext.LangOpts.EnableBoundsSafetyInterop);
85778584
auto ClangDecl =
85788585
dyn_cast_or_null<clang::FunctionDecl>(MappedDecl->getClangDecl());
8586+
// any function with safe pointer imports should have a clang decl
8587+
assert(ClangDecl);
85798588
if (!ClangDecl)
85808589
return;
8581-
if (!funcsWithPointerBounds.count(ClangDecl))
8582-
return;
85838590

85848591
llvm::SmallString<128> MacroString;
85858592
{

lib/ClangImporter/ImportType.cpp

Lines changed: 44 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ namespace {
216216
Bridgeability Bridging;
217217
const clang::FunctionType *CompletionHandlerType;
218218
std::optional<unsigned> CompletionHandlerErrorParamIndex;
219+
bool isSafePointer = false;
219220

220221
public:
221222
SwiftTypeConverter(ClangImporter::Implementation &impl,
@@ -238,6 +239,8 @@ namespace {
238239
return IR;
239240
}
240241

242+
bool hasSafePointer() { return isSafePointer; }
243+
241244
ImportResult VisitType(const Type*) = delete;
242245

243246
// TODO(https://github.com/apple/swift/issues/56206): Add support for dependent types.
@@ -412,13 +415,8 @@ namespace {
412415

413416
ImportResult VisitCountAttributedType(
414417
const clang::CountAttributedType *type) {
415-
// CountAttributedType is a clang type representing a pointer with
416-
// a "counted_by" type attribute. For now, we don't import these
417-
// into Swift.
418-
// In the future we could do something more clever (such as trying to
419-
// import as an Array where possible) or less clever (such as importing
420-
// as the desugared, underlying pointer type).
421-
return Type();
418+
isSafePointer = true;
419+
return Visit(type->desugar());
422420
}
423421

424422
ImportResult VisitMemberPointerType(const clang::MemberPointerType *type) {
@@ -470,7 +468,9 @@ namespace {
470468
// without special hints.
471469
Type pointeeType = Impl.importTypeIgnoreIUO(
472470
pointeeQualType, ImportTypeKind::Value, addImportDiagnostic,
473-
AllowNSUIntegerAsInt, Bridgeability::None, ImportTypeAttrs());
471+
AllowNSUIntegerAsInt, Bridgeability::None, ImportTypeAttrs(),
472+
OTK_ImplicitlyUnwrappedOptional, /*resugarNSErrorPointer=*/true,
473+
&isSafePointer);
474474

475475
// If this is imported as a reference type, ignore the innermost pointer.
476476
// (`T *` becomes `T`, but `T **` becomes `UnsafeMutablePointer<T>`.)
@@ -1689,7 +1689,8 @@ ImportedType ClangImporter::Implementation::importType(
16891689
llvm::function_ref<void(Diagnostic &&)> addImportDiagnosticFn,
16901690
bool allowNSUIntegerAsInt, Bridgeability bridging, ImportTypeAttrs attrs,
16911691
OptionalTypeKind optionality, bool resugarNSErrorPointer,
1692-
std::optional<unsigned> completionHandlerErrorParamIndex) {
1692+
std::optional<unsigned> completionHandlerErrorParamIndex,
1693+
bool *isSafePointer) {
16931694
if (type.isNull())
16941695
return {Type(), false};
16951696

@@ -1751,6 +1752,8 @@ ImportedType ClangImporter::Implementation::importType(
17511752
*this, addImportDiagnosticFn, allowNSUIntegerAsInt, bridging,
17521753
completionHandlerType, completionHandlerErrorParamIndex);
17531754
auto importResult = converter.Visit(type);
1755+
if (isSafePointer)
1756+
*isSafePointer |= converter.hasSafePointer();
17541757

17551758
// Now fix up the type based on how we're concretely using it.
17561759
auto adjustedType = adjustTypeForConcreteImport(
@@ -1764,13 +1767,13 @@ ImportedType ClangImporter::Implementation::importType(
17641767
Type ClangImporter::Implementation::importTypeIgnoreIUO(
17651768
clang::QualType type, ImportTypeKind importKind,
17661769
llvm::function_ref<void(Diagnostic &&)> addImportDiagnosticFn,
1767-
bool allowNSUIntegerAsInt, Bridgeability bridging,
1768-
ImportTypeAttrs attrs, OptionalTypeKind optionality,
1769-
bool resugarNSErrorPointer) {
1770+
bool allowNSUIntegerAsInt, Bridgeability bridging, ImportTypeAttrs attrs,
1771+
OptionalTypeKind optionality, bool resugarNSErrorPointer,
1772+
bool *isSafePointer) {
17701773

1771-
auto importedType = importType(type, importKind, addImportDiagnosticFn,
1772-
allowNSUIntegerAsInt, bridging, attrs,
1773-
optionality, resugarNSErrorPointer);
1774+
auto importedType = importType(
1775+
type, importKind, addImportDiagnosticFn, allowNSUIntegerAsInt, bridging,
1776+
attrs, optionality, resugarNSErrorPointer, std::nullopt, isSafePointer);
17741777

17751778
return importedType.getType();
17761779
}
@@ -2155,7 +2158,7 @@ applyImportTypeAttrs(ImportTypeAttrs attrs, Type type,
21552158

21562159
ImportedType ClangImporter::Implementation::importFunctionReturnType(
21572160
DeclContext *dc, const clang::FunctionDecl *clangDecl,
2158-
bool allowNSUIntegerAsInt) {
2161+
bool allowNSUIntegerAsInt, bool *isSafePointer) {
21592162

21602163
// Hardcode handling of certain result types for builtins.
21612164
if (auto builtinID = clangDecl->getBuiltinID()) {
@@ -2264,13 +2267,13 @@ ImportedType ClangImporter::Implementation::importFunctionReturnType(
22642267
}
22652268

22662269
// Import the result type.
2267-
return importType(returnType,
2268-
(isAuditedResult ? ImportTypeKind::AuditedResult
2269-
: ImportTypeKind::Result),
2270-
ImportDiagnosticAdder(*this, clangDecl,
2271-
clangDecl->getLocation()),
2272-
allowNSUIntegerAsInt, Bridgeability::Full,
2273-
getImportTypeAttrs(clangDecl), OptionalityOfReturn);
2270+
return importType(
2271+
returnType,
2272+
(isAuditedResult ? ImportTypeKind::AuditedResult
2273+
: ImportTypeKind::Result),
2274+
ImportDiagnosticAdder(*this, clangDecl, clangDecl->getLocation()),
2275+
allowNSUIntegerAsInt, Bridgeability::Full, getImportTypeAttrs(clangDecl),
2276+
OptionalityOfReturn, isSafePointer);
22742277
}
22752278

22762279
static Type
@@ -2305,7 +2308,7 @@ ImportedType ClangImporter::Implementation::importFunctionParamsAndReturnType(
23052308
DeclContext *dc, const clang::FunctionDecl *clangDecl,
23062309
ArrayRef<const clang::ParmVarDecl *> params, bool isVariadic,
23072310
bool isFromSystemModule, DeclName name, ParameterList *&parameterList,
2308-
ArrayRef<GenericTypeParamDecl *> genericParams) {
2311+
ArrayRef<GenericTypeParamDecl *> genericParams, bool *hasSafePointer) {
23092312

23102313
bool allowNSUIntegerAsInt =
23112314
shouldAllowNSUIntegerAsInt(isFromSystemModule, clangDecl);
@@ -2362,8 +2365,8 @@ ImportedType ClangImporter::Implementation::importFunctionParamsAndReturnType(
23622365
// If importedType is already initialized, it means we found the enum that
23632366
// was supposed to be used (instead of the typedef type).
23642367
if (!importedType) {
2365-
importedType =
2366-
importFunctionReturnType(dc, clangDecl, allowNSUIntegerAsInt);
2368+
importedType = importFunctionReturnType(
2369+
dc, clangDecl, allowNSUIntegerAsInt, hasSafePointer);
23672370
if (!importedType) {
23682371
addDiag(Diagnostic(diag::return_type_not_imported));
23692372
return {Type(), false};
@@ -2373,9 +2376,9 @@ ImportedType ClangImporter::Implementation::importFunctionParamsAndReturnType(
23732376

23742377
Type swiftResultTy = importedType.getType();
23752378
ArrayRef<Identifier> argNames = name.getArgumentNames();
2376-
parameterList = importFunctionParameterList(dc, clangDecl, params, isVariadic,
2377-
allowNSUIntegerAsInt, argNames,
2378-
genericParams, swiftResultTy);
2379+
parameterList = importFunctionParameterList(
2380+
dc, clangDecl, params, isVariadic, allowNSUIntegerAsInt, argNames,
2381+
genericParams, swiftResultTy, hasSafePointer);
23792382
if (!parameterList)
23802383
return {Type(), false};
23812384

@@ -2424,13 +2427,6 @@ ClangImporter::Implementation::importParameterType(
24242427
}
24252428
}
24262429
}
2427-
} else if (auto CAT = dyn_cast<clang::CountAttributedType>(paramTy)) {
2428-
// Treat as a normal pointer. importBoundsAttributes() will generate a safe
2429-
// overload later.
2430-
paramTy = CAT->desugar();
2431-
if (auto FuncD =
2432-
dyn_cast<clang::FunctionDecl>(param->getParentFunctionOrMethod()))
2433-
funcsWithPointerBounds.insert(FuncD);
24342430
} else if (isa<clang::PointerType>(paramTy) &&
24352431
isa<clang::TemplateTypeParmType>(paramTy->getPointeeType())) {
24362432
auto pointeeType = paramTy->getPointeeType();
@@ -2519,6 +2515,7 @@ ClangImporter::Implementation::importParameterType(
25192515
}
25202516
}
25212517

2518+
bool isSafePointer = false;
25222519
if (!swiftParamTy) {
25232520
// If this is the throws error parameter, we don't need to convert any
25242521
// NSError** arguments to the sugared NSErrorPointer typealias form,
@@ -2528,11 +2525,11 @@ ClangImporter::Implementation::importParameterType(
25282525
// for the specific case when the throws conversion works, but is not
25292526
// sufficient if it fails. (The correct, overarching fix is ClangImporter
25302527
// being lazier.)
2531-
auto importedType = importType(paramTy, importKind, addImportDiagnosticFn,
2532-
allowNSUIntegerAsInt, Bridgeability::Full,
2533-
attrs, optionalityOfParam,
2534-
/*resugarNSErrorPointer=*/!paramIsError,
2535-
completionHandlerErrorParamIndex);
2528+
auto importedType = importType(
2529+
paramTy, importKind, addImportDiagnosticFn, allowNSUIntegerAsInt,
2530+
Bridgeability::Full, attrs, optionalityOfParam,
2531+
/*resugarNSErrorPointer=*/!paramIsError,
2532+
completionHandlerErrorParamIndex, &isSafePointer);
25362533
if (!importedType)
25372534
return std::nullopt;
25382535

@@ -2549,8 +2546,8 @@ ClangImporter::Implementation::importParameterType(
25492546
if (isInOut && isDirectUseOfForeignReferenceType(paramTy, swiftParamTy))
25502547
isInOut = false;
25512548

2552-
return ImportParameterTypeResult{swiftParamTy, isInOut,
2553-
isParamTypeImplicitlyUnwrapped};
2549+
return ImportParameterTypeResult{
2550+
swiftParamTy, isInOut, isParamTypeImplicitlyUnwrapped, isSafePointer};
25542551
}
25552552

25562553
bool ClangImporter::Implementation::isDefaultArgSafeToImport(
@@ -2661,7 +2658,8 @@ ParameterList *ClangImporter::Implementation::importFunctionParameterList(
26612658
DeclContext *dc, const clang::FunctionDecl *clangDecl,
26622659
ArrayRef<const clang::ParmVarDecl *> params, bool isVariadic,
26632660
bool allowNSUIntegerAsInt, ArrayRef<Identifier> argNames,
2664-
ArrayRef<GenericTypeParamDecl *> genericParams, Type resultType) {
2661+
ArrayRef<GenericTypeParamDecl *> genericParams, Type resultType,
2662+
bool *hasSafePointerParam) {
26652663
// Import the parameters.
26662664
SmallVector<ParamDecl *, 4> parameters;
26672665
unsigned index = 0;
@@ -2701,6 +2699,8 @@ ParameterList *ClangImporter::Implementation::importFunctionParameterList(
27012699
bool isInOut = swiftParamTyOpt->isInOut;
27022700
bool isParamTypeImplicitlyUnwrapped =
27032701
swiftParamTyOpt->isParamTypeImplicitlyUnwrapped;
2702+
if (swiftParamTyOpt->isSafePointer && hasSafePointerParam)
2703+
*hasSafePointerParam = true;
27042704

27052705
// Retrieve the argument name.
27062706
Identifier name;

0 commit comments

Comments
 (0)