//===- FactsGenerator.h - Lifetime Facts Generation -------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file defines the FactsGenerator, which traverses the AST to generate // lifetime-relevant facts (such as loan issuance, expiration, origin flow, // and use) from CFG statements. These facts are used by the dataflow analyses // to track pointer lifetimes and detect use-after-free errors. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_FACTSGENERATOR_H #define LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_FACTSGENERATOR_H #include "clang/AST/StmtVisitor.h" #include "clang/Analysis/Analyses/LifetimeSafety/Facts.h" #include "clang/Analysis/Analyses/LifetimeSafety/Origins.h" #include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Analysis/CFG.h" #include "llvm/ADT/SmallVector.h" namespace clang::lifetimes::internal { class FactsGenerator : public ConstStmtVisitor { using Base = ConstStmtVisitor; public: FactsGenerator(FactManager &FactMgr, AnalysisDeclContext &AC) : FactMgr(FactMgr), AC(AC) {} void run(); void VisitDeclStmt(const DeclStmt *DS); void VisitDeclRefExpr(const DeclRefExpr *DRE); void VisitCXXConstructExpr(const CXXConstructExpr *CCE); void VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE); void VisitCallExpr(const CallExpr *CE); void VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *N); void VisitImplicitCastExpr(const ImplicitCastExpr *ICE); void VisitUnaryOperator(const UnaryOperator *UO); void VisitReturnStmt(const ReturnStmt *RS); void VisitBinaryOperator(const BinaryOperator *BO); void VisitConditionalOperator(const ConditionalOperator *CO); void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *OCE); void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *FCE); void VisitInitListExpr(const InitListExpr *ILE); void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *MTE); private: OriginList *getOriginsList(const ValueDecl &D); OriginList *getOriginsList(const Expr &E); void flow(OriginList *Dst, OriginList *Src, bool Kill); void handleAssignment(const Expr *LHSExpr, const Expr *RHSExpr); void handleLifetimeEnds(const CFGLifetimeEnds &LifetimeEnds); void handleGSLPointerConstruction(const CXXConstructExpr *CCE); /// Checks if a call-like expression creates a borrow by passing a value to a /// reference parameter, creating an IssueFact if it does. /// \param IsGslConstruction True if this is a GSL construction where all /// argument origins should flow to the returned origin. void handleFunctionCall(const Expr *Call, const FunctionDecl *FD, ArrayRef Args, bool IsGslConstruction = false); template void flowOrigin(const Destination &D, const Source &S) { flow(getOriginsList(D), getOriginsList(S), /*Kill=*/false); } template void killAndFlowOrigin(const Destination &D, const Source &S) { flow(getOriginsList(D), getOriginsList(S), /*Kill=*/true); } /// Checks if the expression is a `void("__lifetime_test_point_...")` cast. /// If so, creates a `TestPointFact` and returns true. bool handleTestPoint(const CXXFunctionalCastExpr *FCE); // A DeclRefExpr will be treated as a use of the referenced decl. It will be // checked for use-after-free unless it is later marked as being written to // (e.g. on the left-hand side of an assignment). void handleUse(const DeclRefExpr *DRE); void markUseAsWrite(const DeclRefExpr *DRE); llvm::SmallVector issuePlaceholderLoans(); FactManager &FactMgr; AnalysisDeclContext ∾ llvm::SmallVector CurrentBlockFacts; // Collect origins that escape the function in this block (OriginEscapesFact), // appended at the end of CurrentBlockFacts to ensure they appear after // ExpireFact entries. llvm::SmallVector EscapesInCurrentBlock; // To distinguish between reads and writes for use-after-free checks, this map // stores the `UseFact` for each `DeclRefExpr`. We initially identify all // `DeclRefExpr`s as "read" uses. When an assignment is processed, the use // corresponding to the left-hand side is updated to be a "write", thereby // exempting it from the check. llvm::DenseMap UseFacts; }; } // namespace clang::lifetimes::internal #endif // LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_FACTSGENERATOR_H