23#include "llvm/ADT/DenseMap.h"
24#include "llvm/Support/ErrorHandling.h"
25#include "llvm/Support/TimeProfiler.h"
38 llvm_unreachable(
"unknown liveness kind");
44struct PendingWarning {
46 llvm::PointerUnion<const UseFact *, const OriginEscapesFact *> CausingFact;
50class LifetimeChecker {
52 llvm::DenseMap<LoanID, PendingWarning> FinalWarningsMap;
53 llvm::DenseMap<const ParmVarDecl *, const Expr *> AnnotationWarningsMap;
54 const LoanPropagationAnalysis &LoanPropagation;
55 const LiveOriginsAnalysis &LiveOrigins;
56 const FactManager &FactMgr;
57 LifetimeSafetyReporter *Reporter;
61 LifetimeChecker(
const LoanPropagationAnalysis &LoanPropagation,
62 const LiveOriginsAnalysis &LiveOrigins,
const FactManager &FM,
64 : LoanPropagation(LoanPropagation), LiveOrigins(LiveOrigins), FactMgr(FM),
65 Reporter(Reporter), AST(ADC.getASTContext()) {
67 for (
const Fact *F : FactMgr.getFacts(B))
68 if (
const auto *EF = F->getAs<ExpireFact>())
70 else if (
const auto *OEF = F->getAs<OriginEscapesFact>())
71 checkAnnotations(OEF);
72 issuePendingWarnings();
77 if (AST.
getLangOpts().EnableLifetimeSafetyInference)
83 void checkAnnotations(
const OriginEscapesFact *OEF) {
84 OriginID EscapedOID = OEF->getEscapedOriginID();
85 LoanSet EscapedLoans = LoanPropagation.getLoans(EscapedOID, OEF);
86 for (
LoanID LID : EscapedLoans) {
87 const Loan *L = FactMgr.getLoanMgr().getLoan(LID);
88 if (
const auto *PL = dyn_cast<PlaceholderLoan>(L)) {
89 const ParmVarDecl *PVD = PL->getParmVarDecl();
90 if (PVD->hasAttr<LifetimeBoundAttr>())
92 AnnotationWarningsMap.try_emplace(PVD, OEF->getEscapeExpr());
108 void checkExpiry(
const ExpireFact *EF) {
109 LoanID ExpiredLoan = EF->getLoanID();
110 LivenessMap Origins = LiveOrigins.getLiveOriginsAt(EF);
114 llvm::PointerUnion<const UseFact *, const OriginEscapesFact *>
115 BestCausingFact =
nullptr;
117 for (
auto &[OID, LiveInfo] : Origins) {
118 LoanSet HeldLoans = LoanPropagation.getLoans(OID, EF);
119 if (!HeldLoans.contains(ExpiredLoan))
123 if (CurConfidence < NewConfidence) {
124 CurConfidence = NewConfidence;
125 BestCausingFact = LiveInfo.CausingFact;
128 if (!BestCausingFact)
131 Confidence LastConf = FinalWarningsMap.lookup(ExpiredLoan).ConfidenceLevel;
132 if (LastConf >= CurConfidence)
134 FinalWarningsMap[ExpiredLoan] = {EF->getExpiryLoc(),
139 void issuePendingWarnings() {
142 for (
const auto &[LID,
Warning] : FinalWarningsMap) {
143 const Loan *L = FactMgr.getLoanMgr().getLoan(LID);
145 const Expr *IssueExpr = BL->getIssueExpr();
146 llvm::PointerUnion<const UseFact *, const OriginEscapesFact *>
147 CausingFact =
Warning.CausingFact;
149 SourceLocation ExpiryLoc =
Warning.ExpiryLoc;
151 if (
const auto *UF = CausingFact.dyn_cast<
const UseFact *>())
152 Reporter->reportUseAfterFree(IssueExpr, UF->getUseExpr(), ExpiryLoc,
154 else if (
const auto *OEF =
155 CausingFact.dyn_cast<
const OriginEscapesFact *>())
156 Reporter->reportUseAfterReturn(IssueExpr, OEF->getEscapeExpr(),
159 llvm_unreachable(
"Unhandled CausingFact type");
163 void suggestAnnotations() {
166 for (
const auto &[PVD, EscapeExpr] : AnnotationWarningsMap)
167 Reporter->suggestAnnotation(PVD, EscapeExpr);
170 void inferAnnotations() {
176 for (
const auto &[ConstPVD, EscapeExpr] : AnnotationWarningsMap) {
177 ParmVarDecl *PVD =
const_cast<ParmVarDecl *
>(ConstPVD);
178 if (!PVD->hasAttr<LifetimeBoundAttr>())
180 LifetimeBoundAttr::CreateImplicit(AST, PVD->getLocation()));
190 llvm::TimeTraceScope TimeProfile(
"LifetimeChecker");
191 LifetimeChecker Checker(LP, LO, FactMgr, ADC, Reporter);
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
Defines the clang::SourceLocation class and associated facilities.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const LangOptions & getLangOpts() const
AnalysisDeclContext contains the context data for the function, method or block under analysis.
Represents a single basic block in a source-level CFG.
Encodes a location in the source.
llvm::ImmutableSet< LoanID > LoanSet
utils::ID< struct LoanTag > LoanID
utils::ID< struct OriginTag > OriginID
llvm::ImmutableMap< OriginID, LivenessInfo > LivenessMap
void runLifetimeChecker(const LoanPropagationAnalysis &LoanPropagation, const LiveOriginsAnalysis &LiveOrigins, const FactManager &FactMgr, AnalysisDeclContext &ADC, LifetimeSafetyReporter *Reporter)
Runs the lifetime checker, which detects use-after-free errors by examining loan expiration points an...
static Confidence livenessKindToConfidence(LivenessKind K)
Confidence
Enum to track the confidence level of a potential error.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
for(const auto &A :T->param_types())
U cast(CodeGen::Address addr)