clang 22.0.0git
LifetimeSafety.h
Go to the documentation of this file.
1//===- LifetimeSafety.h - C++ Lifetime Safety Analysis -*----------- C++-*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the entry point for a dataflow-based static analysis
10// that checks for C++ lifetime violations.
11//
12// The analysis is based on the concepts of "origins" and "loans" to track
13// pointer lifetimes and detect issues like use-after-free and dangling
14// pointers. See the RFC for more details:
15// https://discourse.llvm.org/t/rfc-intra-procedural-lifetime-analysis-in-clang/86291
16//
17//===----------------------------------------------------------------------===//
18#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H
19#define LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H
21#include "clang/Analysis/CFG.h"
23#include "llvm/ADT/DenseMapInfo.h"
24#include "llvm/ADT/ImmutableMap.h"
25#include "llvm/ADT/ImmutableSet.h"
26#include "llvm/ADT/StringMap.h"
27#include <memory>
28
30
31/// Enum to track the confidence level of a potential error.
32enum class Confidence {
33 None,
34 Maybe, // Reported as a potential error (-Wlifetime-safety-strict)
35 Definite // Reported as a definite error (-Wlifetime-safety-permissive)
36};
37
39public:
41 virtual ~LifetimeSafetyReporter() = default;
42
43 virtual void reportUseAfterFree(const Expr *IssueExpr, const Expr *UseExpr,
44 SourceLocation FreeLoc,
46};
47
48/// The main entry point for the analysis.
50 LifetimeSafetyReporter *Reporter);
51
52namespace internal {
53// Forward declarations of internal types.
54class Fact;
55class FactManager;
58struct LifetimeFactory;
59
60/// A generic, type-safe wrapper for an ID, distinguished by its `Tag` type.
61/// Used for giving ID to loans and origins.
62template <typename Tag> struct ID {
63 uint32_t Value = 0;
64
65 bool operator==(const ID<Tag> &Other) const { return Value == Other.Value; }
66 bool operator!=(const ID<Tag> &Other) const { return !(*this == Other); }
67 bool operator<(const ID<Tag> &Other) const { return Value < Other.Value; }
69 ID<Tag> Tmp = *this;
70 ++Value;
71 return Tmp;
72 }
73 void Profile(llvm::FoldingSetNodeID &IDBuilder) const {
74 IDBuilder.AddInteger(Value);
75 }
76};
77
78template <typename Tag>
79inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ID<Tag> ID) {
80 return OS << ID.Value;
81}
82
85
86// Using LLVM's immutable collections is efficient for dataflow analysis
87// as it avoids deep copies during state transitions.
88// TODO(opt): Consider using a bitset to represent the set of loans.
89using LoanSet = llvm::ImmutableSet<LoanID>;
90using OriginSet = llvm::ImmutableSet<OriginID>;
91
92/// A `ProgramPoint` identifies a location in the CFG by pointing to a specific
93/// `Fact`. identified by a lifetime-related event (`Fact`).
94///
95/// A `ProgramPoint` has "after" semantics: it represents the location
96/// immediately after its corresponding `Fact`.
97using ProgramPoint = const Fact *;
98
99/// Running the lifetime safety analysis and querying its results. It
100/// encapsulates the various dataflow analyses.
102public:
104 LifetimeSafetyReporter *Reporter);
106
107 void run();
108
109 /// Returns the set of loans an origin holds at a specific program point.
111
112 /// Returns the set of loans that have expired at a specific program point.
113 std::vector<LoanID> getExpiredLoansAtPoint(ProgramPoint PP) const;
114
115 /// Finds the OriginID for a given declaration.
116 /// Returns a null optional if not found.
117 std::optional<OriginID> getOriginIDForDecl(const ValueDecl *D) const;
118
119 /// Finds the LoanID's for the loan created with the specific variable as
120 /// their Path.
121 std::vector<LoanID> getLoanIDForVar(const VarDecl *VD) const;
122
123 /// Retrieves program points that were specially marked in the source code
124 /// for testing.
125 ///
126 /// The analysis recognizes special function calls of the form
127 /// `void("__lifetime_test_point_<name>")` as test points. This method returns
128 /// a map from the annotation string (<name>) to the corresponding
129 /// `ProgramPoint`. This allows test harnesses to query the analysis state at
130 /// user-defined locations in the code.
131 /// \note This is intended for testing only.
132 llvm::StringMap<ProgramPoint> getTestPoints() const;
133
134private:
136 LifetimeSafetyReporter *Reporter;
137 std::unique_ptr<LifetimeFactory> Factory;
138 std::unique_ptr<FactManager> FactMgr;
139 std::unique_ptr<LoanPropagationAnalysis> LoanPropagation;
140 std::unique_ptr<ExpiredLoansAnalysis> ExpiredLoans;
141};
142} // namespace internal
143} // namespace clang::lifetimes
144
145namespace llvm {
146template <typename Tag>
147struct DenseMapInfo<clang::lifetimes::internal::ID<Tag>> {
149
150 static inline ID getEmptyKey() {
151 return {DenseMapInfo<uint32_t>::getEmptyKey()};
152 }
153
154 static inline ID getTombstoneKey() {
155 return {DenseMapInfo<uint32_t>::getTombstoneKey()};
156 }
157
158 static unsigned getHashValue(const ID &Val) {
159 return DenseMapInfo<uint32_t>::getHashValue(Val.Value);
160 }
161
162 static bool isEqual(const ID &LHS, const ID &RHS) { return LHS == RHS; }
163};
164} // namespace llvm
165
166#endif // LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
const Decl * D
Defines the clang::SourceLocation class and associated facilities.
AnalysisDeclContext contains the context data for the function, method or block under analysis.
This represents one expression.
Definition: Expr.h:112
Encodes a location in the source.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:711
Represents a variable declaration or definition.
Definition: Decl.h:925
virtual void reportUseAfterFree(const Expr *IssueExpr, const Expr *UseExpr, SourceLocation FreeLoc, Confidence Confidence)
The analysis that tracks which loans have expired.
An abstract base class for a single, atomic lifetime-relevant event.
Running the lifetime safety analysis and querying its results.
LoanSet getLoansAtPoint(OriginID OID, ProgramPoint PP) const
Returns the set of loans an origin holds at a specific program point.
std::optional< OriginID > getOriginIDForDecl(const ValueDecl *D) const
Finds the OriginID for a given declaration.
std::vector< LoanID > getExpiredLoansAtPoint(ProgramPoint PP) const
Returns the set of loans that have expired at a specific program point.
std::vector< LoanID > getLoanIDForVar(const VarDecl *VD) const
Finds the LoanID's for the loan created with the specific variable as their Path.
llvm::StringMap< ProgramPoint > getTestPoints() const
Retrieves program points that were specially marked in the source code for testing.
The analysis that tracks which loans belong to which origins.
llvm::ImmutableSet< LoanID > LoanSet
llvm::ImmutableSet< OriginID > OriginSet
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, ID< Tag > ID)
void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC, LifetimeSafetyReporter *Reporter)
The main entry point for the analysis.
Confidence
Enum to track the confidence level of a potential error.
The JSON file list parser is used to communicate input to InstallAPI.
@ Other
Other implicit parameter.
Diagnostic wrappers for TextAPI types for error reporting.
Definition: Dominators.h:30
A generic, type-safe wrapper for an ID, distinguished by its Tag type.
bool operator==(const ID< Tag > &Other) const
bool operator!=(const ID< Tag > &Other) const
bool operator<(const ID< Tag > &Other) const
void Profile(llvm::FoldingSetNodeID &IDBuilder) const
An object to hold the factories for immutable collections, ensuring that all created states share the...
static bool isEqual(const ID &LHS, const ID &RHS)