[llvm-branch-commits] [clang] [LifetimeSafety] Add support for GSL Pointer types (PR #154009)
Utkarsh Saxena via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Sep 3 04:12:05 PDT 2025
================
@@ -521,8 +563,75 @@ class FactGeneratorVisitor : public ConstStmtVisitor<FactGeneratorVisitor> {
}
private:
+ static bool isGslPointerType(QualType QT) {
+ if (const auto *RD = QT->getAsCXXRecordDecl()) {
+ // We need to check the template definition for specializations.
+ if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
+ return CTSD->getSpecializedTemplate()
+ ->getTemplatedDecl()
+ ->hasAttr<PointerAttr>();
+ return RD->hasAttr<PointerAttr>();
+ }
+ return false;
+ }
+
// Check if a type has an origin.
- bool hasOrigin(QualType QT) { return QT->isPointerOrReferenceType(); }
+ static bool hasOrigin(QualType QT) {
+ if (QT->isFunctionPointerType())
+ return false;
+ return QT->isPointerOrReferenceType() || isGslPointerType(QT);
+ }
+
+ /// Checks if a call-like expression creates a borrow by passing a local
+ /// value to a reference parameter, creating an IssueFact if it does.
+ void checkForBorrows(const Expr *Call, const FunctionDecl *FD,
+ ArrayRef<const Expr *> Args) {
+ if (!FD)
+ return;
+
+ for (unsigned I = 0; I < Args.size(); ++I) {
+ if (I >= FD->getNumParams())
+ break;
+
+ const ParmVarDecl *Param = FD->getParamDecl(I);
+ const Expr *Arg = Args[I];
+
+ // This is the core condition for a new borrow: a value type (no origin)
+ // is passed to a reference parameter.
+ if (Param->getType()->isReferenceType() && !hasOrigin(Arg->getType())) {
+ if (const Loan *L = createLoanFrom(Arg, Call)) {
+ OriginID OID = FactMgr.getOriginMgr().getOrCreate(*Call);
+ CurrentBlockFacts.push_back(
+ FactMgr.createFact<IssueFact>(L->ID, OID));
+ // For view creation, we assume the first borrow is the significant
+ // one.
+ return;
+ }
+ }
+ }
+ }
+
+ /// Attempts to create a loan by analyzing the source expression of a borrow.
+ /// This method is the single point for creating loans, allowing for future
+ /// expansion to handle temporaries, field members, etc.
+ /// \param SourceExpr The expression representing the object being borrowed
+ /// from.
+ /// \param IssueExpr The expression that triggers the borrow (e.g., a
+ /// constructor call).
+ /// \return The new Loan on success, nullptr on failure.
+ const Loan *createLoanFrom(const Expr *SourceExpr, const Expr *IssueExpr) {
+ // For now, we only handle direct borrows from local variables.
+ // In the future, this can be extended to handle MaterializeTemporaryExpr,
----------------
usx95 wrote:
Did some renaming of the params.
A loan to a path is issued to some origin. This path would always be some expression (example a DRE `a`, field `a.field`, array subscript `a[0]`). This loan is issued to a an origin of the expression triggering the loan (`IssuedTo` expr). We could have directly used the origin of this expression but loan needs to be aware of the underlying issueTo expression for diagnostic purposes as this is the expression at which the diagnostic is shown.
https://github.com/llvm/llvm-project/pull/154009
More information about the llvm-branch-commits
mailing list