@@ -125,6 +125,7 @@ createFuncOrAccessor(ClangImporter::Implementation &impl, SourceLoc funcLoc,
125
125
genericParams, dc, clangNode);
126
126
}
127
127
impl.importSwiftAttrAttributes(decl);
128
+ impl.importBoundsAttributes(decl);
128
129
return decl;
129
130
}
130
131
@@ -8532,6 +8533,107 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
8532
8533
}
8533
8534
}
8534
8535
8536
+ namespace {
8537
+ class PointerParamInfo {
8538
+ public:
8539
+ virtual void print(clang::ASTContext &ctx, llvm::raw_ostream &out) const = 0;
8540
+ virtual ~PointerParamInfo() {}
8541
+ };
8542
+
8543
+ class CountedByParam : public PointerParamInfo {
8544
+ public:
8545
+ size_t pointerIndex;
8546
+ clang::Expr *countExpr;
8547
+ bool isSizedBy;
8548
+ CountedByParam(size_t idx, clang::Expr *E, bool sizedBy)
8549
+ : pointerIndex(idx), countExpr(E), isSizedBy(sizedBy) {}
8550
+
8551
+ virtual void print(clang::ASTContext &ctx,
8552
+ llvm::raw_ostream &out) const override {
8553
+ out << ".";
8554
+ if (isSizedBy)
8555
+ out << "sizedBy";
8556
+ else
8557
+ out << "countedBy";
8558
+ out << "(pointer: " << pointerIndex << ", ";
8559
+ if (isSizedBy)
8560
+ out << "size";
8561
+ else
8562
+ out << "count";
8563
+ out << ": \"";
8564
+ countExpr->printPretty(
8565
+ out, {}, {ctx.getLangOpts()}); // TODO: map clang::Expr to Swift Expr
8566
+ out << "\")";
8567
+ }
8568
+ virtual ~CountedByParam() {}
8569
+ };
8570
+ } // namespace
8571
+
8572
+ void ClangImporter::Implementation::importBoundsAttributes(
8573
+ FuncDecl *MappedDecl) {
8574
+ auto ClangDecl =
8575
+ dyn_cast_or_null<clang::FunctionDecl>(MappedDecl->getClangDecl());
8576
+ if (!ClangDecl)
8577
+ return;
8578
+
8579
+ SmallVector<PointerParamInfo *, 4> BoundsInfo;
8580
+ size_t parameterIndex = 1;
8581
+ for (auto param : ClangDecl->parameters()) {
8582
+ if (auto CAT = param->getType()->getAs<clang::CountAttributedType>()) {
8583
+ BoundsInfo.push_back(new CountedByParam(
8584
+ parameterIndex, CAT->getCountExpr(), CAT->isCountInBytes()));
8585
+ }
8586
+ parameterIndex++;
8587
+ }
8588
+ if (BoundsInfo.empty())
8589
+ return;
8590
+
8591
+ llvm::SmallString<128> MacroString;
8592
+ {
8593
+ llvm::raw_svector_ostream out(MacroString);
8594
+
8595
+ out << "@PointerBounds(";
8596
+ for (size_t i = 0; i < BoundsInfo.size(); i++) {
8597
+ BoundsInfo[i]->print(getClangASTContext(), out);
8598
+ if (i + 1 < BoundsInfo.size()) {
8599
+ out << ", ";
8600
+ }
8601
+ }
8602
+ out << ")";
8603
+ }
8604
+
8605
+ // Dig out a buffer with the attribute text.
8606
+ unsigned bufferID = getClangSwiftAttrSourceBuffer(MacroString);
8607
+
8608
+ // Dig out a source file we can use for parsing.
8609
+ auto &sourceFile = getClangSwiftAttrSourceFile(
8610
+ *MappedDecl->getDeclContext()->getParentModule(), bufferID);
8611
+
8612
+ // Spin up a parser.
8613
+ swift::Parser parser(bufferID, sourceFile, &SwiftContext.Diags, nullptr,
8614
+ nullptr);
8615
+ // Prime the lexer.
8616
+ parser.consumeTokenWithoutFeedingReceiver();
8617
+
8618
+ bool hadError = false;
8619
+ assert(parser.Tok.is(tok::at_sign));
8620
+ SourceLoc atEndLoc = parser.Tok.getRange().getEnd();
8621
+ SourceLoc atLoc = parser.consumeToken(tok::at_sign);
8622
+ DeclContext *DC = MappedDecl->getParent();
8623
+ auto initContext = PatternBindingInitializer::create(DC);
8624
+ hadError = parser
8625
+ .parseDeclAttribute(MappedDecl->getAttrs(), atLoc, atEndLoc,
8626
+ initContext,
8627
+ /*isFromClangAttribute=*/true)
8628
+ .isError();
8629
+ if (hadError) {
8630
+ HeaderLoc attrLoc(ClangDecl->getLocation());
8631
+ diagnose(attrLoc, diag::clang_pointer_bounds_unhandled,
8632
+ MappedDecl->getName(), MacroString);
8633
+ return;
8634
+ }
8635
+ }
8636
+
8535
8637
static bool isUsingMacroName(clang::SourceManager &SM,
8536
8638
clang::SourceLocation loc,
8537
8639
StringRef MacroName) {
0 commit comments