12#include "llvm/Support/Casting.h"
13#include "llvm/Support/TimeProfiler.h"
16using llvm::isa_and_present;
21 if (
auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
22 return CTSD->getSpecializedTemplate()
24 ->hasAttr<PointerAttr>();
25 return RD->hasAttr<PointerAttr>();
47 if (
const auto *VD = dyn_cast<ValueDecl>(DRE->
getDecl())) {
56 llvm::TimeTraceScope TimeProfile(
"FactGenerator");
60 CurrentBlockFacts.clear();
61 for (
unsigned I = 0; I <
Block->size(); ++I) {
63 if (std::optional<CFGStmt> CS = Element.
getAs<
CFGStmt>())
65 else if (std::optional<CFGAutomaticObjDtor> DtorOpt =
67 handleDestructor(*DtorOpt);
69 FactMgr.addBlockFacts(
Block, CurrentBlockFacts);
75 if (
const auto *VD = dyn_cast<VarDecl>(D))
77 if (
const Expr *InitExpr = VD->getInit())
78 killAndFlowOrigin(*VD, *InitExpr);
95 OriginID ExprOID = FactMgr.getOriginMgr().getOrCreate(*DRE);
96 CurrentBlockFacts.push_back(
97 FactMgr.createFact<
IssueFact>(L->ID, ExprOID));
104 handleGSLPointerConstruction(CCE);
116 {MCE->getImplicitObjectArgument()},
126 handleFunctionCall(MCE,
Method, Args,
false);
132 {CE->getArgs(), CE->getNumArgs()});
139 FactMgr.getOriginMgr().getOrCreate(*N);
161 killAndFlowOrigin(*UO, *SubExpr);
168 OriginID OID = FactMgr.getOriginMgr().getOrCreate(*RetExpr);
187 {OCE->getArgs(), OCE->getNumArgs()},
195 if (handleTestPoint(FCE))
207 killAndFlowOrigin(*ILE, *ILE->
getInit(0));
235 if (LoanPath.
D == DestructedVD)
241void FactsGenerator::handleGSLPointerConstruction(
const CXXConstructExpr *CCE) {
246 killAndFlowOrigin(*CCE, *CCE->
getArg(0));
250 {CCE->getArgs(), CCE->getNumArgs()},
258void FactsGenerator::handleFunctionCall(
const Expr *
Call,
259 const FunctionDecl *FD,
261 bool IsGslConstruction) {
265 auto IsArgLifetimeBound = [FD](
unsigned I) ->
bool {
266 const ParmVarDecl *PVD =
nullptr;
267 if (
const auto *Method = dyn_cast<CXXMethodDecl>(FD);
268 Method && Method->isInstance()) {
272 if ((I - 1) < Method->getNumParams())
275 PVD = Method->getParamDecl(I - 1);
276 }
else if (I < FD->getNumParams())
278 PVD = FD->getParamDecl(I);
279 return PVD ? PVD->hasAttr<clang::LifetimeBoundAttr>() :
false;
283 bool killedSrc =
false;
284 for (
unsigned I = 0; I < Args.size(); ++I)
285 if (IsGslConstruction || IsArgLifetimeBound(I)) {
288 killAndFlowOrigin(*
Call, *Args[I]);
290 flowOrigin(*
Call, *Args[I]);
296bool FactsGenerator::handleTestPoint(
const CXXFunctionalCastExpr *FCE) {
297 if (!FCE->getType()->isVoidType())
300 const auto *SubExpr = FCE->getSubExpr()->IgnoreParenImpCasts();
301 if (
const auto *SL = dyn_cast<StringLiteral>(SubExpr)) {
302 llvm::StringRef LiteralValue = SL->getString();
303 const std::string Prefix =
"__lifetime_test_point_";
305 if (LiteralValue.starts_with(Prefix)) {
306 StringRef Annotation = LiteralValue.drop_front(Prefix.length());
307 CurrentBlockFacts.push_back(
308 FactMgr.createFact<TestPointFact>(Annotation));
315void FactsGenerator::handleAssignment(
const Expr *LHSExpr,
316 const Expr *RHSExpr) {
320 if (
const auto *DRE_LHS =
321 dyn_cast<DeclRefExpr>(LHSExpr->IgnoreParenImpCasts())) {
322 markUseAsWrite(DRE_LHS);
323 if (
const auto *VD_LHS = dyn_cast<ValueDecl>(DRE_LHS->getDecl())) {
326 killAndFlowOrigin(*VD_LHS, *RHSExpr);
334void FactsGenerator::handleUse(
const DeclRefExpr *DRE) {
336 UseFact *UF = FactMgr.createFact<UseFact>(DRE);
337 CurrentBlockFacts.push_back(UF);
338 assert(!UseFacts.contains(DRE));
343void FactsGenerator::markUseAsWrite(
const DeclRefExpr *DRE) {
346 assert(UseFacts.contains(DRE));
347 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)
Represents the storage location being borrowed, e.g., a specific stack variable.
const clang::ValueDecl * D
Information about a single borrow, or "Loan".