================
@@ -105,6 +107,103 @@ bool implicitObjectParamIsLifetimeBound(const 
FunctionDecl *FD) {
   return isNormalAssignmentOperator(FD);
 }
 
+std::optional<LifetimeBoundParamInfo>
+getLifetimeBoundParamInfo(const FunctionDecl *FD, unsigned I) {
+  FD = getDeclWithMergedLifetimeBoundAttrs(FD);
+  if (!FD)
+    return std::nullopt;
+
+  const ParmVarDecl *PVD = nullptr;
+  if (const auto *Method = dyn_cast<CXXMethodDecl>(FD);
+      Method && Method->isInstance() && !isa<CXXConstructorDecl>(FD)) {
+    if (I == 0)
+      return implicitObjectParamIsLifetimeBound(Method)
+                 ? std::optional<LifetimeBoundParamInfo>(
+                       LifetimeBoundParamInfo(Method))
+                 : std::nullopt;
+    if ((I - 1) < Method->getNumParams())
+      PVD = Method->getParamDecl(I - 1);
+  } else if (I < FD->getNumParams()) {
+    PVD = FD->getParamDecl(I);
+  }
+
+  if (PVD && PVD->hasAttr<clang::LifetimeBoundAttr>())
+    return LifetimeBoundParamInfo(PVD);
+  return std::nullopt;
+}
+
+static bool isExprInCallArg(const Expr *Arg, const Expr *Source) {
+  if (!Arg || !Source)
+    return false;
+
+  Arg = Arg->IgnoreParenImpCasts();
+  Source = Source->IgnoreParenImpCasts();
+  if (Arg == Source || Arg->getSourceRange() == Source->getSourceRange())
+    return true;
+
+  for (const Stmt *Child : Arg->children())
+    if (const auto *ChildExpr = dyn_cast_or_null<Expr>(Child))
+      if (isExprInCallArg(ChildExpr, Source))
+        return true;
+
+  return false;
+}
+
+llvm::SmallVector<const Expr *, 4> getLifetimeSafetyCallArgs(const Expr *Call) 
{
+  llvm::SmallVector<const Expr *, 4> Args;
+  if (!Call)
+    return Args;
+
+  Call = Call->IgnoreParenImpCasts();
+  if (const auto *CCE = dyn_cast<CXXConstructExpr>(Call)) {
+    Args.append(CCE->getArgs(), CCE->getArgs() + CCE->getNumArgs());
+  } else if (const auto *MCE = dyn_cast<CXXMemberCallExpr>(Call)) {
+    Args.push_back(MCE->getImplicitObjectArgument());
+    Args.append(MCE->getArgs(), MCE->getArgs() + MCE->getNumArgs());
+  } else if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(Call)) {
+    Args.append(OCE->getArgs(), OCE->getArgs() + OCE->getNumArgs());
+    if (const FunctionDecl *FD = OCE->getDirectCallee();
+        FD && OCE->getOperator() == OO_Call && FD->isStatic())
+      Args.erase(Args.begin());
+  } else if (const auto *CE = dyn_cast<CallExpr>(Call)) {
+    Args.append(CE->getArgs(), CE->getArgs() + CE->getNumArgs());
+  }
+
+  return Args;
----------------
NeKon69 wrote:

Can we return callee here along with the arguments to avoid having to extract 
callee again later in `getLifetimeBoundParamInfoForCallArg`?

https://github.com/llvm/llvm-project/pull/206337
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to