@@ -108,7 +108,8 @@ createFuncOrAccessor(ClangImporter::Implementation &impl, SourceLoc funcLoc,
108108 std::optional<AccessorInfo> accessorInfo, DeclName name,
109109 SourceLoc nameLoc, GenericParamList *genericParams,
110110 ParameterList *bodyParams, Type resultTy, bool async,
111- bool throws, DeclContext *dc, ClangNode clangNode) {
111+ bool throws, DeclContext *dc, ClangNode clangNode,
112+ bool hasBoundsAnnotation) {
112113 FuncDecl *decl;
113114 if (accessorInfo) {
114115 decl = AccessorDecl::create (
@@ -124,6 +125,9 @@ createFuncOrAccessor(ClangImporter::Implementation &impl, SourceLoc funcLoc,
124125 genericParams, dc, clangNode);
125126 }
126127 impl.importSwiftAttrAttributes (decl);
128+ if (hasBoundsAnnotation)
129+ impl.importBoundsAttributes (decl);
130+
127131 return decl;
128132}
129133
@@ -3272,7 +3276,8 @@ namespace {
32723276 }
32733277 return Impl.importFunctionParameterList (
32743278 dc, decl, nonSelfParams, decl->isVariadic (), allowNSUIntegerAsInt,
3275- argNames, genericParams, /* resultType=*/ nullptr );
3279+ argNames, genericParams, /* resultType=*/ nullptr ,
3280+ /* hasBoundsAnnotatedParam=*/ nullptr );
32763281 }
32773282
32783283 Decl *
@@ -3690,6 +3695,7 @@ namespace {
36903695
36913696 bool importFuncWithoutSignature =
36923697 isa<clang::CXXMethodDecl>(decl) && Impl.importSymbolicCXXDecls ;
3698+ bool hasBoundsAnnotation = false ;
36933699 if (!dc->isModuleScopeContext () && !isa<clang::CXXMethodDecl>(decl)) {
36943700 // Handle initializers.
36953701 if (name.getBaseName ().isConstructor ()) {
@@ -3786,7 +3792,7 @@ namespace {
37863792 importedType = Impl.importFunctionParamsAndReturnType (
37873793 dc, decl, {decl->param_begin (), decl->param_size ()},
37883794 decl->isVariadic (), isInSystemModule (dc), name, bodyParams,
3789- templateParams);
3795+ templateParams, &hasBoundsAnnotation );
37903796 }
37913797
37923798 if (auto *mdecl = dyn_cast<clang::CXXMethodDecl>(decl)) {
@@ -3853,10 +3859,10 @@ namespace {
38533859 auto resultTy = importedType.getType ();
38543860
38553861 FuncDecl *func =
3856- createFuncOrAccessor (Impl, loc, accessorInfo, name,
3857- nameLoc, genericParams, bodyParams, resultTy,
3862+ createFuncOrAccessor (Impl, loc, accessorInfo, name, nameLoc,
3863+ genericParams, bodyParams, resultTy,
38583864 /* async=*/ false , /* throws=*/ false , dc,
3859- clangNode);
3865+ clangNode, hasBoundsAnnotation );
38603866 result = func;
38613867
38623868 if (!dc->isModuleScopeContext ()) {
@@ -4899,12 +4905,14 @@ namespace {
48994905 }
49004906 }
49014907
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);
49084916
49094917 result->setAccess (decl->isDirectMethod () ? AccessLevel::Public
49104918 : getOverridableAccessLevel (dc));
@@ -6544,7 +6552,8 @@ Decl *SwiftDeclConverter::importGlobalAsInitializer(
65446552 } else {
65456553 parameterList = Impl.importFunctionParameterList (
65466554 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 );
65486557 }
65496558 if (!parameterList)
65506559 return nullptr ;
@@ -8344,6 +8353,53 @@ static bool importAsUnsafe(ClangImporter::Implementation &impl,
83448353 return false ;
83458354}
83468355
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+
83478403void
83488404ClangImporter::Implementation::importSwiftAttrAttributes (Decl *MappedDecl) {
83498405 auto ClangDecl =
@@ -8481,53 +8537,7 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
84818537 continue ;
84828538 }
84838539
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 ());
85318541 }
85328542
85338543 if (seenUnsafe || importAsUnsafe (*this , ClangDecl, MappedDecl)) {
@@ -8613,6 +8623,70 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
86138623 }
86148624}
86158625
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+
86168690static bool isUsingMacroName (clang::SourceManager &SM,
86178691 clang::SourceLocation loc,
86188692 StringRef MacroName) {
0 commit comments