Index: clang/include/clang/AST/Expr.h =================================================================== --- clang/include/clang/AST/Expr.h +++ clang/include/clang/AST/Expr.h @@ -2274,13 +2274,26 @@ } }; +/// Abstract interface for CallExpr, ObjCMessageExpr and CXXConstructExpr. +class AbstractCallExpr : public Expr { +public: + using Expr::Expr; + + ArrayRef arguments() const; + + static bool classof(const Stmt *T) { + return T->getStmtClass() >= firstAbstractCallExprConstant + && T->getStmtClass() <= lastAbstractCallExprConstant; + } +}; + /// CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]). /// CallExpr itself represents a normal function call, e.g., "f(x, 2)", /// while its subclasses may represent alternative syntax that (semantically) /// results in a function call. For example, CXXOperatorCallExpr is /// a subclass for overloaded operator calls that use operator syntax, e.g., /// "str1 + str2" to resolve to a function call. -class CallExpr : public Expr { +class CallExpr : public AbstractCallExpr { enum { FN=0, PREARGS_START=1 }; Stmt **SubExprs; unsigned NumArgs; @@ -2369,25 +2382,10 @@ /// to null. void setNumArgs(const ASTContext& C, unsigned NumArgs); - typedef ExprIterator arg_iterator; - typedef ConstExprIterator const_arg_iterator; - typedef llvm::iterator_range arg_range; - typedef llvm::iterator_range arg_const_range; - - arg_range arguments() { return arg_range(arg_begin(), arg_end()); } - arg_const_range arguments() const { - return arg_const_range(arg_begin(), arg_end()); - } - - arg_iterator arg_begin() { return SubExprs+PREARGS_START+getNumPreArgs(); } - arg_iterator arg_end() { - return SubExprs+PREARGS_START+getNumPreArgs()+getNumArgs(); - } - const_arg_iterator arg_begin() const { - return SubExprs+PREARGS_START+getNumPreArgs(); - } - const_arg_iterator arg_end() const { - return SubExprs+PREARGS_START+getNumPreArgs()+getNumArgs(); + ArrayRef getArgsRef() const { + return ArrayRef( + reinterpret_cast(&(SubExprs[PREARGS_START + getNumPreArgs()])), + NumArgs); } /// This method provides fast access to all the subexpressions of Index: clang/include/clang/AST/ExprCXX.h =================================================================== --- clang/include/clang/AST/ExprCXX.h +++ clang/include/clang/AST/ExprCXX.h @@ -1236,7 +1236,7 @@ }; /// Represents a call to a C++ constructor. -class CXXConstructExpr : public Expr { +class CXXConstructExpr : public AbstractCallExpr { public: enum ConstructionKind { CK_Complete, @@ -1275,7 +1275,7 @@ /// Construct an empty C++ construction expression. CXXConstructExpr(StmtClass SC, EmptyShell Empty) - : Expr(SC, Empty), NumArgs(0), Elidable(false), + : AbstractCallExpr(SC, Empty), NumArgs(0), Elidable(false), HadMultipleCandidates(false), ListInitialization(false), ZeroInitialization(false), ConstructKind(0) {} @@ -1371,6 +1371,10 @@ return cast(Args[Arg]); } + ArrayRef getArgsRef() const { + return ArrayRef(reinterpret_cast(Args), NumArgs); + } + /// Set the specified argument. void setArg(unsigned Arg, Expr *ArgExpr) { assert(Arg < NumArgs && "Arg access out of range!"); @@ -2023,6 +2027,12 @@ return llvm::make_range(placement_arg_begin(), placement_arg_end()); } + ArrayRef placement_arguments_ref() const { + return ArrayRef( + reinterpret_cast(SubExprs + Array + hasInitializer()), + getNumPlacementArgs()); + } + arg_iterator placement_arg_begin() { return SubExprs + Array + hasInitializer(); } Index: clang/include/clang/AST/ExprObjC.h =================================================================== --- clang/include/clang/AST/ExprObjC.h +++ clang/include/clang/AST/ExprObjC.h @@ -901,7 +901,7 @@ /// receiver pointer), and NumArgs Expr *. But due to the /// implementation of children(), these must be together contiguously. class ObjCMessageExpr final - : public Expr, + : public AbstractCallExpr, private llvm::TrailingObjects { /// Stores either the selector that this message is sending /// to (when \c HasMethod is zero) or an \c ObjCMethodDecl pointer @@ -948,7 +948,7 @@ SourceLocation LBracLoc, RBracLoc; ObjCMessageExpr(EmptyShell Empty, unsigned NumArgs) - : Expr(ObjCMessageExprClass, Empty), Kind(0), HasMethod(false), + : AbstractCallExpr(ObjCMessageExprClass, Empty), Kind(0), HasMethod(false), IsDelegateInitCall(false), IsImplicit(false), SelLocsKind(0) { setNumArgs(NumArgs); } @@ -1426,6 +1426,13 @@ return reinterpret_cast(getArgs() + NumArgs); } + /// Return a reference to the arguments of this message expression not + /// including the receiver. + ArrayRef getArgsRef() const { + return ArrayRef( + const_cast(this)->getArgs(), NumArgs); + } + static bool classof(const Stmt *T) { return T->getStmtClass() == ObjCMessageExprClass; } Index: clang/include/clang/Basic/StmtNodes.td =================================================================== --- clang/include/clang/Basic/StmtNodes.td +++ clang/include/clang/Basic/StmtNodes.td @@ -54,6 +54,7 @@ // Expressions def Expr : Stmt<1>; +def AbstractCallExpr : DStmt; def PredefinedExpr : DStmt; def DeclRefExpr : DStmt; def IntegerLiteral : DStmt; @@ -68,7 +69,7 @@ def UnaryExprOrTypeTraitExpr : DStmt; def ArraySubscriptExpr : DStmt; def OMPArraySectionExpr : DStmt; -def CallExpr : DStmt; +def CallExpr : DStmt; def MemberExpr : DStmt; def CastExpr : DStmt; def BinaryOperator : DStmt; @@ -128,7 +129,7 @@ def ArrayTypeTraitExpr : DStmt; def ExpressionTraitExpr : DStmt; def DependentScopeDeclRefExpr : DStmt; -def CXXConstructExpr : DStmt; +def CXXConstructExpr : DStmt; def CXXInheritedCtorInitExpr : DStmt; def CXXBindTemporaryExpr : DStmt; def ExprWithCleanups : DStmt; @@ -160,7 +161,7 @@ def ObjCArrayLiteral : DStmt; def ObjCDictionaryLiteral : DStmt; def ObjCEncodeExpr : DStmt; -def ObjCMessageExpr : DStmt; +def ObjCMessageExpr : DStmt; def ObjCSelectorExpr : DStmt; def ObjCProtocolExpr : DStmt; def ObjCIvarRefExpr : DStmt; Index: clang/lib/AST/Expr.cpp =================================================================== --- clang/lib/AST/Expr.cpp +++ clang/lib/AST/Expr.cpp @@ -1183,6 +1183,15 @@ } } +ArrayRef AbstractCallExpr::arguments() const { + if (auto CE = dyn_cast(this)) + return CE->getArgsRef(); + if (auto ME = dyn_cast(this)) + return ME->getArgsRef(); + if (auto CXXCE = dyn_cast(this)) + return CXXCE->getArgsRef(); + llvm_unreachable("Unexpected child class"); +} //===----------------------------------------------------------------------===// // Postfix Operators. @@ -1191,7 +1200,7 @@ CallExpr::CallExpr(const ASTContext &C, StmtClass SC, Expr *fn, ArrayRef preargs, ArrayRef args, QualType t, ExprValueKind VK, SourceLocation rparenloc) - : Expr(SC, t, VK, OK_Ordinary, fn->isTypeDependent(), + : AbstractCallExpr(SC, t, VK, OK_Ordinary, fn->isTypeDependent(), fn->isValueDependent(), fn->isInstantiationDependent(), fn->containsUnexpandedParameterPack()), NumArgs(args.size()) { @@ -1227,7 +1236,7 @@ CallExpr::CallExpr(const ASTContext &C, StmtClass SC, unsigned NumPreArgs, EmptyShell Empty) - : Expr(SC, Empty), SubExprs(nullptr), NumArgs(0) { + : AbstractCallExpr(SC, Empty), SubExprs(nullptr), NumArgs(0) { // FIXME: Why do we allocate this? SubExprs = new (C) Stmt*[PREARGS_START+NumPreArgs](); CallExprBits.NumPreArgs = NumPreArgs; Index: clang/lib/AST/ExprCXX.cpp =================================================================== --- clang/lib/AST/ExprCXX.cpp +++ clang/lib/AST/ExprCXX.cpp @@ -806,21 +806,15 @@ ParenOrBraceRange); } -CXXConstructExpr::CXXConstructExpr(const ASTContext &C, StmtClass SC, - QualType T, SourceLocation Loc, - CXXConstructorDecl *Ctor, - bool Elidable, - ArrayRef Args, - bool HadMultipleCandidates, - bool ListInitialization, - bool StdInitListInitialization, - bool ZeroInitialization, - ConstructionKind ConstructKind, - SourceRange ParenOrBraceRange) - : Expr(SC, T, VK_RValue, OK_Ordinary, - T->isDependentType(), T->isDependentType(), - T->isInstantiationDependentType(), - T->containsUnexpandedParameterPack()), +CXXConstructExpr::CXXConstructExpr( + const ASTContext &C, StmtClass SC, QualType T, SourceLocation Loc, + CXXConstructorDecl *Ctor, bool Elidable, ArrayRef Args, + bool HadMultipleCandidates, bool ListInitialization, + bool StdInitListInitialization, bool ZeroInitialization, + ConstructionKind ConstructKind, SourceRange ParenOrBraceRange) + : AbstractCallExpr(SC, T, VK_RValue, OK_Ordinary, T->isDependentType(), + T->isDependentType(), T->isInstantiationDependentType(), + T->containsUnexpandedParameterPack()), Constructor(Ctor), Loc(Loc), ParenOrBraceRange(ParenOrBraceRange), NumArgs(Args.size()), Elidable(Elidable), HadMultipleCandidates(HadMultipleCandidates), Index: clang/lib/AST/ExprObjC.cpp =================================================================== --- clang/lib/AST/ExprObjC.cpp +++ clang/lib/AST/ExprObjC.cpp @@ -128,10 +128,10 @@ SelectorLocationsKind SelLocsK, ObjCMethodDecl *Method, ArrayRef Args, SourceLocation RBracLoc, bool isImplicit) - : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, - /*TypeDependent=*/false, /*ValueDependent=*/false, - /*InstantiationDependent=*/false, - /*ContainsUnexpandedParameterPack=*/false), + : AbstractCallExpr(ObjCMessageExprClass, T, VK, OK_Ordinary, + /*TypeDependent=*/false, /*ValueDependent=*/false, + /*InstantiationDependent=*/false, + /*ContainsUnexpandedParameterPack=*/false), SelectorOrMethod( reinterpret_cast(Method ? Method : Sel.getAsOpaquePtr())), Kind(IsInstanceSuper ? SuperInstance : SuperClass), @@ -149,9 +149,10 @@ SelectorLocationsKind SelLocsK, ObjCMethodDecl *Method, ArrayRef Args, SourceLocation RBracLoc, bool isImplicit) - : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, T->isDependentType(), - T->isDependentType(), T->isInstantiationDependentType(), - T->containsUnexpandedParameterPack()), + : AbstractCallExpr(ObjCMessageExprClass, T, VK, OK_Ordinary, + T->isDependentType(), T->isDependentType(), + T->isInstantiationDependentType(), + T->containsUnexpandedParameterPack()), SelectorOrMethod( reinterpret_cast(Method ? Method : Sel.getAsOpaquePtr())), Kind(Class), HasMethod(Method != nullptr), IsDelegateInitCall(false), @@ -166,10 +167,10 @@ SelectorLocationsKind SelLocsK, ObjCMethodDecl *Method, ArrayRef Args, SourceLocation RBracLoc, bool isImplicit) - : Expr(ObjCMessageExprClass, T, VK, OK_Ordinary, - Receiver->isTypeDependent(), Receiver->isTypeDependent(), - Receiver->isInstantiationDependent(), - Receiver->containsUnexpandedParameterPack()), + : AbstractCallExpr(ObjCMessageExprClass, T, VK, OK_Ordinary, + Receiver->isTypeDependent(), Receiver->isTypeDependent(), + Receiver->isInstantiationDependent(), + Receiver->containsUnexpandedParameterPack()), SelectorOrMethod( reinterpret_cast(Method ? Method : Sel.getAsOpaquePtr())), Kind(Instance), HasMethod(Method != nullptr), IsDelegateInitCall(false),