[PATCH] D101788: [AST] AnyCall: Implement arguments().

Artem Dergachev via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Mon May 3 15:10:10 PDT 2021


NoQ created this revision.
NoQ added reviewers: vsavchenko, george.karpenkov, rjmccall.
Herald added a subscriber: martong.
NoQ requested review of this revision.

AnyCall is an interface provided by libAnalysis to polymorphically handle various call-like entities (function calls, Obj-C message expressions, block calls, constructor/destructor invocations, new/delete invocations, etc.) which aren't necessarily related in the AST class hierarchy.

This patch updates it to allow obtaining arguments of any call-like expression.

It also adds a couple of accessor functions in the AST in order to make this possible. The `CXXDeleteExpr`'s `getArgumentAddress()` looks a bit weird out of context but we do seem to have a precedent (`VarDecl::getInitAddress()`).


Repository:
  rC Clang

https://reviews.llvm.org/D101788

Files:
  clang/include/clang/AST/ExprCXX.h
  clang/include/clang/Analysis/AnyCall.h


Index: clang/include/clang/Analysis/AnyCall.h
===================================================================
--- clang/include/clang/Analysis/AnyCall.h
+++ clang/include/clang/Analysis/AnyCall.h
@@ -109,7 +109,7 @@
 
   /// If @c E is a generic call (to ObjC method /function/block/etc),
   /// return a constructed @c AnyCall object. Return None otherwise.
-  static Optional<AnyCall> forExpr(const Expr *E) {
+  static Optional<AnyCall> forExpr(const Stmt *E) {
     if (const auto *ME = dyn_cast<ObjCMessageExpr>(E)) {
       return AnyCall(ME);
     } else if (const auto *CE = dyn_cast<CallExpr>(E)) {
@@ -161,6 +161,35 @@
   size_t param_size() const { return parameters().size(); }
   bool param_empty() const { return parameters().empty(); }
 
+  ArrayRef<const Expr *> arguments() const {
+    if (!E)
+      return None;
+
+    if (const auto *ME = dyn_cast<ObjCMessageExpr>(E)) {
+      return {ME->getArgs(), ME->getNumArgs()};
+    } else if (const auto *CE = dyn_cast<CallExpr>(E)) {
+      return {CE->getArgs(), CE->getNumArgs()};
+    } else if (const auto *CXNE = dyn_cast<CXXNewExpr>(E)) {
+      return {CXNE->getPlacementArgs(), CXNE->getNumPlacementArgs()};
+    } else if (const auto *CXDE = dyn_cast<CXXDeleteExpr>(E)) {
+      // The only argument is the object being deleted.
+      return {reinterpret_cast<Expr *const *>(CXDE->getArgumentAddress()), 1U};
+    } else if (const auto *CXCE = dyn_cast<CXXConstructExpr>(E)) {
+      return {CXCE->getArgs(), CXCE->getNumArgs()};
+    } else if (const auto *CXCIE = dyn_cast<CXXInheritedCtorInitExpr>(E)) {
+      // No argument expressions are synthesized in this case.
+      return None;
+    } else {
+      return None;
+    }
+  }
+
+  using arg_const_iterator = ArrayRef<const Expr *>::const_iterator;
+  arg_const_iterator arg_begin() const { return arguments().begin(); }
+  arg_const_iterator arg_end() const { return arguments().end(); }
+  size_t arg_size() const { return arguments().size(); }
+  bool arg_empty() const { return arguments().empty(); }
+
   QualType getReturnType(ASTContext &Ctx) const {
     switch (K) {
     case Function:
Index: clang/include/clang/AST/ExprCXX.h
===================================================================
--- clang/include/clang/AST/ExprCXX.h
+++ clang/include/clang/AST/ExprCXX.h
@@ -2281,6 +2281,11 @@
                                      placementNewArgsOffset());
   }
 
+  Expr *const *getPlacementArgs() const {
+    return reinterpret_cast<Expr *const *>(getTrailingObjects<Stmt *>() +
+                                           placementNewArgsOffset());
+  }
+
   Expr *getPlacementArg(unsigned I) {
     assert((I < getNumPlacementArgs()) && "Index out of range!");
     return getPlacementArgs()[I];
@@ -2439,6 +2444,9 @@
   Expr *getArgument() { return cast<Expr>(Argument); }
   const Expr *getArgument() const { return cast<Expr>(Argument); }
 
+  /// Retrieve the address of the argument expression.
+  Stmt *const *getArgumentAddress() const { return &Argument; }
+
   /// Retrieve the type being destroyed.
   ///
   /// If the type being destroyed is a dependent type which may or may not


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D101788.342556.patch
Type: text/x-patch
Size: 3148 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20210503/e8c426cb/attachment.bin>


More information about the cfe-commits mailing list