12#include "llvm/Support/TimeProfiler.h"
19 if (
auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
20 return CTSD->getSpecializedTemplate()
22 ->hasAttr<PointerAttr>();
23 return RD->hasAttr<PointerAttr>();
45 if (
const auto *VD = dyn_cast<ValueDecl>(DRE->
getDecl())) {
54 llvm::TimeTraceScope TimeProfile(
"FactGenerator");
58 CurrentBlockFacts.clear();
59 for (
unsigned I = 0; I <
Block->size(); ++I) {
61 if (std::optional<CFGStmt> CS = Element.
getAs<
CFGStmt>())
63 else if (std::optional<CFGAutomaticObjDtor> DtorOpt =
65 handleDestructor(*DtorOpt);
67 FactMgr.addBlockFacts(
Block, CurrentBlockFacts);
73 if (
const auto *VD = dyn_cast<VarDecl>(D))
75 if (
const Expr *InitExpr = VD->getInit())
76 killAndFlowOrigin(*VD, *InitExpr);
93 OriginID ExprOID = FactMgr.getOriginMgr().getOrCreate(*DRE);
94 CurrentBlockFacts.push_back(
95 FactMgr.createFact<
IssueFact>(L->ID, ExprOID));
102 handleGSLPointerConstruction(CCE);
114 {MCE->getImplicitObjectArgument()},
124 handleFunctionCall(MCE,
Method, Args,
false);
130 {CE->getArgs(), CE->getNumArgs()});
137 FactMgr.getOriginMgr().getOrCreate(*N);
159 killAndFlowOrigin(*UO, *SubExpr);
166 OriginID OID = FactMgr.getOriginMgr().getOrCreate(*RetExpr);
185 {OCE->getArgs(), OCE->getNumArgs()},
193 if (handleTestPoint(FCE))
205 killAndFlowOrigin(*ILE, *ILE->
getInit(0));
233 if (LoanPath.
D == DestructedVD)
239void FactsGenerator::handleGSLPointerConstruction(
const CXXConstructExpr *CCE) {
244 killAndFlowOrigin(*CCE, *CCE->
getArg(0));
248 {CCE->getArgs(), CCE->getNumArgs()},
256void FactsGenerator::handleFunctionCall(
const Expr *
Call,
257 const FunctionDecl *FD,
259 bool IsGslConstruction) {
263 auto IsArgLifetimeBound = [FD](
unsigned I) ->
bool {
264 const ParmVarDecl *PVD =
nullptr;
265 if (
const auto *Method = dyn_cast<CXXMethodDecl>(FD);
266 Method && Method->isInstance()) {
270 if ((I - 1) < Method->getNumParams())
273 PVD = Method->getParamDecl(I - 1);
274 }
else if (I < FD->getNumParams())
276 PVD = FD->getParamDecl(I);
277 return PVD ? PVD->hasAttr<clang::LifetimeBoundAttr>() :
false;
281 bool killedSrc =
false;
282 for (
unsigned I = 0; I < Args.size(); ++I)
283 if (IsGslConstruction || IsArgLifetimeBound(I)) {
286 killAndFlowOrigin(*
Call, *Args[I]);
288 flowOrigin(*
Call, *Args[I]);
294bool FactsGenerator::handleTestPoint(
const CXXFunctionalCastExpr *FCE) {
295 if (!FCE->getType()->isVoidType())
298 const auto *SubExpr = FCE->getSubExpr()->IgnoreParenImpCasts();
299 if (
const auto *SL = dyn_cast<StringLiteral>(SubExpr)) {
300 llvm::StringRef LiteralValue = SL->getString();
301 const std::string Prefix =
"__lifetime_test_point_";
303 if (LiteralValue.starts_with(Prefix)) {
304 StringRef Annotation = LiteralValue.drop_front(Prefix.length());
305 CurrentBlockFacts.push_back(
306 FactMgr.createFact<TestPointFact>(Annotation));
313void FactsGenerator::handleAssignment(
const Expr *LHSExpr,
314 const Expr *RHSExpr) {
318 if (
const auto *DRE_LHS =
319 dyn_cast<DeclRefExpr>(LHSExpr->IgnoreParenImpCasts())) {
320 markUseAsWrite(DRE_LHS);
321 if (
const auto *VD_LHS = dyn_cast<ValueDecl>(DRE_LHS->getDecl())) {
324 killAndFlowOrigin(*VD_LHS, *RHSExpr);
332void FactsGenerator::handleUse(
const DeclRefExpr *DRE) {
334 UseFact *UF = FactMgr.createFact<UseFact>(DRE);
335 CurrentBlockFacts.push_back(UF);
336 assert(!UseFacts.contains(DRE));
341void FactsGenerator::markUseAsWrite(
const DeclRefExpr *DRE) {
344 assert(UseFacts.contains(DRE));
345 UseFacts[DRE]->markAsWritten();
A builtin binary operation expression such as "x + y" or "x <= y".
static bool isAssignmentOp(Opcode Opc)
Represents C++ object destructor implicitly generated for automatic object or temporary bound to cons...
const VarDecl * getVarDecl() const
const Stmt * getTriggerStmt() const
Represents a single basic block in a source-level CFG.
Represents a top-level expression in a basic block.
std::optional< T > getAs() const
Convert to the specified CFGElement type, returning std::nullopt if this CFGElement is not of the des...
Represents a call to a C++ constructor.
Expr * getArg(unsigned Arg)
Return the specified argument.
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
unsigned getNumArgs() const
Return the number of arguments to the constructor call.
Represents an explicit C++ type conversion that uses "functional" notation (C++ [expr....
Represents a call to a member function that may be written either with member call syntax (e....
CXXMethodDecl * getMethodDecl() const
Retrieve the declaration of the called method.
Expr * getImplicitObjectArgument() const
Retrieve the implicit object argument for the member call.
Represents a static or instance method of a struct/union/class.
The null pointer literal (C++11 [lex.nullptr])
A call to an overloaded operator written using operator syntax.
static bool isAssignmentOp(OverloadedOperatorKind Opc)
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Expr ** getArgs()
Retrieve the call arguments.
A reference to a declared variable, function, enum, etc.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Decl - This represents one declaration (or definition), e.g.
This represents one expression.
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
Describes an C or C++ initializer list.
unsigned getNumInits() const
const Expr * getInit(unsigned Init) const
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
Expr * getSubExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.
A (possibly-)qualified type.
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
RetTy Visit(PTR(Stmt) S, ParamTys... P)
SourceLocation getEndLoc() const LLVM_READONLY
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isPointerOrReferenceType() const
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Expr * getSubExpr() const
Represents a variable declaration or definition.
FactType * createFact(Args &&...args)
LoanManager & getLoanMgr()
void VisitDeclRefExpr(const DeclRefExpr *DRE)
void VisitBinaryOperator(const BinaryOperator *BO)
void VisitCallExpr(const CallExpr *CE)
void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *MTE)
void VisitReturnStmt(const ReturnStmt *RS)
void VisitCXXConstructExpr(const CXXConstructExpr *CCE)
void VisitImplicitCastExpr(const ImplicitCastExpr *ICE)
void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *FCE)
void VisitInitListExpr(const InitListExpr *ILE)
void VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *N)
void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *OCE)
void VisitUnaryOperator(const UnaryOperator *UO)
void VisitDeclStmt(const DeclStmt *DS)
void VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE)
Loan & addLoan(AccessPath Path, const Expr *IssueExpr)
llvm::ArrayRef< Loan > getLoans() const
static bool hasOrigin(const Expr *E)
utils::ID< struct OriginTag > OriginID
static bool isPointerType(QualType QT)
static bool isGslPointerType(QualType QT)
static const Loan * createLoan(FactManager &FactMgr, const DeclRefExpr *DRE)
Creates a loan for the storage path of a given declaration reference.
bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD)
bool isa(CodeGen::Address addr)
Represents the storage location being borrowed, e.g., a specific stack variable.
const clang::ValueDecl * D
Information about a single borrow, or "Loan".