@@ -108,7 +108,8 @@ createFuncOrAccessor(ClangImporter::Implementation &impl, SourceLoc funcLoc,
108
108
std::optional<AccessorInfo> accessorInfo, DeclName name,
109
109
SourceLoc nameLoc, GenericParamList *genericParams,
110
110
ParameterList *bodyParams, Type resultTy, bool async,
111
- bool throws, DeclContext *dc, ClangNode clangNode) {
111
+ bool throws, DeclContext *dc, ClangNode clangNode,
112
+ bool hasBoundsAnnotation) {
112
113
FuncDecl *decl;
113
114
if (accessorInfo) {
114
115
decl = AccessorDecl::create (
@@ -124,6 +125,9 @@ createFuncOrAccessor(ClangImporter::Implementation &impl, SourceLoc funcLoc,
124
125
genericParams, dc, clangNode);
125
126
}
126
127
impl.importSwiftAttrAttributes (decl);
128
+ if (hasBoundsAnnotation)
129
+ impl.importBoundsAttributes (decl);
130
+
127
131
return decl;
128
132
}
129
133
@@ -3272,7 +3276,8 @@ namespace {
3272
3276
}
3273
3277
return Impl.importFunctionParameterList (
3274
3278
dc, decl, nonSelfParams, decl->isVariadic (), allowNSUIntegerAsInt,
3275
- argNames, genericParams, /* resultType=*/ nullptr );
3279
+ argNames, genericParams, /* resultType=*/ nullptr ,
3280
+ /* hasBoundsAnnotatedParam=*/ nullptr );
3276
3281
}
3277
3282
3278
3283
Decl *
@@ -3690,6 +3695,7 @@ namespace {
3690
3695
3691
3696
bool importFuncWithoutSignature =
3692
3697
isa<clang::CXXMethodDecl>(decl) && Impl.importSymbolicCXXDecls ;
3698
+ bool hasBoundsAnnotation = false ;
3693
3699
if (!dc->isModuleScopeContext () && !isa<clang::CXXMethodDecl>(decl)) {
3694
3700
// Handle initializers.
3695
3701
if (name.getBaseName ().isConstructor ()) {
@@ -3786,7 +3792,7 @@ namespace {
3786
3792
importedType = Impl.importFunctionParamsAndReturnType (
3787
3793
dc, decl, {decl->param_begin (), decl->param_size ()},
3788
3794
decl->isVariadic (), isInSystemModule (dc), name, bodyParams,
3789
- templateParams);
3795
+ templateParams, &hasBoundsAnnotation );
3790
3796
}
3791
3797
3792
3798
if (auto *mdecl = dyn_cast<clang::CXXMethodDecl>(decl)) {
@@ -3853,10 +3859,10 @@ namespace {
3853
3859
auto resultTy = importedType.getType ();
3854
3860
3855
3861
FuncDecl *func =
3856
- createFuncOrAccessor (Impl, loc, accessorInfo, name,
3857
- nameLoc, genericParams, bodyParams, resultTy,
3862
+ createFuncOrAccessor (Impl, loc, accessorInfo, name, nameLoc,
3863
+ genericParams, bodyParams, resultTy,
3858
3864
/* async=*/ false , /* throws=*/ false , dc,
3859
- clangNode);
3865
+ clangNode, hasBoundsAnnotation );
3860
3866
result = func;
3861
3867
3862
3868
if (!dc->isModuleScopeContext ()) {
@@ -4899,12 +4905,14 @@ namespace {
4899
4905
}
4900
4906
}
4901
4907
4902
- auto result = createFuncOrAccessor (Impl,
4903
- /* funcLoc*/ SourceLoc (), accessorInfo,
4904
- importedName.getDeclName (),
4905
- /* nameLoc*/ SourceLoc (),
4906
- /* genericParams=*/ nullptr , bodyParams,
4907
- resultTy, async, throws, dc, decl);
4908
+ bool hasBoundsAnnotation =
4909
+ false ; // currently only implemented for functions
4910
+ auto result = createFuncOrAccessor (
4911
+ Impl,
4912
+ /* funcLoc*/ SourceLoc (), accessorInfo, importedName.getDeclName (),
4913
+ /* nameLoc*/ SourceLoc (),
4914
+ /* genericParams=*/ nullptr , bodyParams, resultTy, async, throws, dc,
4915
+ decl, hasBoundsAnnotation);
4908
4916
4909
4917
result->setAccess (decl->isDirectMethod () ? AccessLevel::Public
4910
4918
: getOverridableAccessLevel (dc));
@@ -6544,7 +6552,8 @@ Decl *SwiftDeclConverter::importGlobalAsInitializer(
6544
6552
} else {
6545
6553
parameterList = Impl.importFunctionParameterList (
6546
6554
dc, decl, {decl->param_begin (), decl->param_end ()}, decl->isVariadic (),
6547
- allowNSUIntegerAsInt, argNames, /* genericParams=*/ {}, /* resultType=*/ nullptr );
6555
+ allowNSUIntegerAsInt, argNames, /* genericParams=*/ {},
6556
+ /* resultType=*/ nullptr , /* hasBoundsAnnotatedParam=*/ nullptr );
6548
6557
}
6549
6558
if (!parameterList)
6550
6559
return nullptr ;
@@ -8344,6 +8353,53 @@ static bool importAsUnsafe(ClangImporter::Implementation &impl,
8344
8353
return false ;
8345
8354
}
8346
8355
8356
+ void ClangImporter::Implementation::importNontrivialAttribute (
8357
+ Decl *MappedDecl, llvm::StringRef AttrString) {
8358
+ bool cached = true ;
8359
+ while (true ) {
8360
+ // Dig out a source file we can use for parsing.
8361
+ auto &sourceFile = getClangSwiftAttrSourceFile (
8362
+ *MappedDecl->getDeclContext ()->getParentModule (), AttrString, cached);
8363
+
8364
+ auto topLevelDecls = sourceFile.getTopLevelDecls ();
8365
+
8366
+ // If we're using the cached version, check whether we can correctly
8367
+ // clone the attribute.
8368
+ if (cached) {
8369
+ bool hasNonclonableAttribute = false ;
8370
+ for (auto decl : topLevelDecls) {
8371
+ if (hasNonclonableAttribute)
8372
+ break ;
8373
+
8374
+ for (auto attr : decl->getAttrs ()) {
8375
+ if (!attr->canClone ()) {
8376
+ hasNonclonableAttribute = true ;
8377
+ break ;
8378
+ }
8379
+ }
8380
+ }
8381
+
8382
+ // We cannot clone one of the attributes. Go back and build a new
8383
+ // source file without caching it.
8384
+ if (hasNonclonableAttribute) {
8385
+ cached = false ;
8386
+ continue ;
8387
+ }
8388
+ }
8389
+
8390
+ // Collect the attributes from the synthesized top-level declaration in
8391
+ // the source file. If we're using a cached copy, clone the attribute.
8392
+ for (auto decl : topLevelDecls) {
8393
+ SmallVector<DeclAttribute *, 2 > attrs (decl->getAttrs ().begin (),
8394
+ decl->getAttrs ().end ());
8395
+ for (auto attr : attrs) {
8396
+ MappedDecl->getAttrs ().add (cached ? attr->clone (SwiftContext) : attr);
8397
+ }
8398
+ }
8399
+ break ;
8400
+ }
8401
+ }
8402
+
8347
8403
void
8348
8404
ClangImporter::Implementation::importSwiftAttrAttributes (Decl *MappedDecl) {
8349
8405
auto ClangDecl =
@@ -8481,53 +8537,7 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
8481
8537
continue ;
8482
8538
}
8483
8539
8484
- bool cached = true ;
8485
- while (true ) {
8486
- // Dig out a source file we can use for parsing.
8487
- auto &sourceFile = getClangSwiftAttrSourceFile (
8488
- *MappedDecl->getDeclContext ()->getParentModule (),
8489
- swiftAttr->getAttribute (),
8490
- cached);
8491
-
8492
- auto topLevelDecls = sourceFile.getTopLevelDecls ();
8493
-
8494
- // If we're using the cached version, check whether we can correctly
8495
- // clone the attribute.
8496
- if (cached) {
8497
- bool hasNonclonableAttribute = false ;
8498
- for (auto decl : topLevelDecls) {
8499
- if (hasNonclonableAttribute)
8500
- break ;
8501
-
8502
- for (auto attr : decl->getAttrs ()) {
8503
- if (!attr->canClone ()) {
8504
- hasNonclonableAttribute = true ;
8505
- break ;
8506
- }
8507
- }
8508
- }
8509
-
8510
- // We cannot clone one of the attributes. Go back and build a new
8511
- // source file without caching it.
8512
- if (hasNonclonableAttribute) {
8513
- cached = false ;
8514
- continue ;
8515
- }
8516
- }
8517
-
8518
- // Collect the attributes from the synthesized top-level declaration in
8519
- // the source file. If we're using a cached copy, clone the attribute.
8520
- for (auto decl : topLevelDecls) {
8521
- SmallVector<DeclAttribute *, 2 > attrs (decl->getAttrs ().begin (),
8522
- decl->getAttrs ().end ());
8523
- for (auto attr : attrs) {
8524
- MappedDecl->getAttrs ().add (cached ? attr->clone (SwiftContext)
8525
- : attr);
8526
- }
8527
- }
8528
-
8529
- break ;
8530
- }
8540
+ importNontrivialAttribute (MappedDecl, swiftAttr->getAttribute ());
8531
8541
}
8532
8542
8533
8543
if (seenUnsafe || importAsUnsafe (*this , ClangDecl, MappedDecl)) {
@@ -8613,6 +8623,70 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
8613
8623
}
8614
8624
}
8615
8625
8626
+ namespace {
8627
+ class PointerParamInfoPrinter {
8628
+ public:
8629
+ clang::ASTContext &ctx;
8630
+ llvm::raw_ostream &out;
8631
+ bool firstParam = true ;
8632
+ PointerParamInfoPrinter (clang::ASTContext &ctx, llvm::raw_ostream &out)
8633
+ : ctx(ctx), out(out) {
8634
+ out << " @PointerBounds(" ;
8635
+ }
8636
+ ~PointerParamInfoPrinter () { out << " )" ; }
8637
+
8638
+ void printCountedBy (const clang::CountAttributedType *CAT,
8639
+ size_t pointerIndex) {
8640
+ if (!firstParam) {
8641
+ out << " , " ;
8642
+ } else {
8643
+ firstParam = false ;
8644
+ }
8645
+ clang::Expr *countExpr = CAT->getCountExpr ();
8646
+ bool isSizedBy = CAT->isCountInBytes ();
8647
+ out << " ." ;
8648
+ if (isSizedBy)
8649
+ out << " sizedBy" ;
8650
+ else
8651
+ out << " countedBy" ;
8652
+ out << " (pointer: " << pointerIndex + 1 << " , " ;
8653
+ if (isSizedBy)
8654
+ out << " size" ;
8655
+ else
8656
+ out << " count" ;
8657
+ out << " : \" " ;
8658
+ countExpr->printPretty (
8659
+ out, {}, {ctx.getLangOpts ()}); // TODO: map clang::Expr to Swift Expr
8660
+ out << " \" )" ;
8661
+ }
8662
+ };
8663
+ } // namespace
8664
+
8665
+ void ClangImporter::Implementation::importBoundsAttributes (
8666
+ FuncDecl *MappedDecl) {
8667
+ assert (SwiftContext.LangOpts .hasFeature (Feature::SafeInteropWrappers));
8668
+ auto ClangDecl =
8669
+ dyn_cast_or_null<clang::FunctionDecl>(MappedDecl->getClangDecl ());
8670
+ // any function with safe pointer imports should have a clang decl
8671
+ assert (ClangDecl);
8672
+ if (!ClangDecl)
8673
+ return ;
8674
+
8675
+ llvm::SmallString<128 > MacroString;
8676
+ {
8677
+ llvm::raw_svector_ostream out (MacroString);
8678
+
8679
+ PointerParamInfoPrinter printer (getClangASTContext (), out);
8680
+ for (auto [index , param] : llvm::enumerate (ClangDecl->parameters ())) {
8681
+ if (auto CAT = param->getType ()->getAs <clang::CountAttributedType>()) {
8682
+ printer.printCountedBy (CAT, index );
8683
+ }
8684
+ }
8685
+ }
8686
+
8687
+ importNontrivialAttribute (MappedDecl, MacroString);
8688
+ }
8689
+
8616
8690
static bool isUsingMacroName (clang::SourceManager &SM,
8617
8691
clang::SourceLocation loc,
8618
8692
StringRef MacroName) {
0 commit comments