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(getTrailingObjects() + + placementNewArgsOffset()); + } + Expr *getPlacementArg(unsigned I) { assert((I < getNumPlacementArgs()) && "Index out of range!"); return getPlacementArgs()[I]; @@ -2439,6 +2444,9 @@ Expr *getArgument() { return cast(Argument); } const Expr *getArgument() const { return cast(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 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 forExpr(const Expr *E) { + static Optional forExpr(const Stmt *E) { if (const auto *ME = dyn_cast(E)) { return AnyCall(ME); } else if (const auto *CE = dyn_cast(E)) { @@ -161,6 +161,35 @@ size_t param_size() const { return parameters().size(); } bool param_empty() const { return parameters().empty(); } + ArrayRef arguments() const { + if (!E) + return None; + + if (const auto *ME = dyn_cast(E)) { + return {ME->getArgs(), ME->getNumArgs()}; + } else if (const auto *CE = dyn_cast(E)) { + return {CE->getArgs(), CE->getNumArgs()}; + } else if (const auto *CXNE = dyn_cast(E)) { + return {CXNE->getPlacementArgs(), CXNE->getNumPlacementArgs()}; + } else if (const auto *CXDE = dyn_cast(E)) { + // The only argument is the object being deleted. + return {reinterpret_cast(CXDE->getArgumentAddress()), 1U}; + } else if (const auto *CXCE = dyn_cast(E)) { + return {CXCE->getArgs(), CXCE->getNumArgs()}; + } else if (const auto *CXCIE = dyn_cast(E)) { + // No argument expressions are synthesized in this case. + return None; + } else { + return None; + } + } + + using arg_const_iterator = ArrayRef::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: