From: Bruno Ricci Date: Mon, 3 Dec 2018 13:23:56 +0000 (+0000) Subject: [Sema] Avoid CallExpr::setNumArgs in Sema::BuildCallToObjectOfClassType X-Git-Tag: llvmorg-8.0.0-rc1~3066 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=6ef089d21c8853d4623980617f18490ab64c8548;p=platform%2Fupstream%2Fllvm.git [Sema] Avoid CallExpr::setNumArgs in Sema::BuildCallToObjectOfClassType CallExpr::setNumArgs is the only thing that prevents storing the arguments of a call expression in a trailing array since it might resize the argument array. setNumArgs is only called in 3 places in Sema, and for all of them it is possible to avoid it. This deals with the call to setNumArgs in BuildCallToObjectOfClassType. Instead of constructing the CXXOperatorCallExpr first and later calling setNumArgs if we have default arguments, we first construct a large enough SmallVector, do the promotion/check of the arguments, and then construct the CXXOperatorCallExpr. Incidentally this also avoid reallocating the arguments when the call operator has default arguments but this is not the primary goal. Differential Revision: https://reviews.llvm.org/D54900 Reviewed By: aaron.ballman llvm-svn: 348134 --- diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index f36668f..b53c0ad 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -13257,29 +13257,14 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, if (NewFn.isInvalid()) return true; + // The number of argument slots to allocate in the call. If we have default + // arguments we need to allocate space for them as well. We additionally + // need one more slot for the object parameter. + unsigned NumArgsSlots = 1 + std::max(Args.size(), NumParams); + // Build the full argument list for the method call (the implicit object // parameter is placed at the beginning of the list). - SmallVector MethodArgs(Args.size() + 1); - MethodArgs[0] = Object.get(); - std::copy(Args.begin(), Args.end(), MethodArgs.begin() + 1); - - // Once we've built TheCall, all of the expressions are properly - // owned. - QualType ResultTy = Method->getReturnType(); - ExprValueKind VK = Expr::getValueKindForType(ResultTy); - ResultTy = ResultTy.getNonLValueExprType(Context); - - CXXOperatorCallExpr *TheCall = new (Context) - CXXOperatorCallExpr(Context, OO_Call, NewFn.get(), MethodArgs, ResultTy, - VK, RParenLoc, FPOptions()); - - if (CheckCallReturnType(Method->getReturnType(), LParenLoc, TheCall, Method)) - return true; - - // We may have default arguments. If so, we need to allocate more - // slots in the call for them. - if (Args.size() < NumParams) - TheCall->setNumArgs(Context, NumParams + 1); + SmallVector MethodArgs(NumArgsSlots); bool IsError = false; @@ -13291,7 +13276,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, IsError = true; else Object = ObjRes; - TheCall->setArg(0, Object.get()); + MethodArgs[0] = Object.get(); // Check the argument types. for (unsigned i = 0; i != NumParams; i++) { @@ -13320,7 +13305,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, Arg = DefArg.getAs(); } - TheCall->setArg(i + 1, Arg); + MethodArgs[i + 1] = Arg; } // If this is a variadic call, handle args passed through "...". @@ -13330,14 +13315,27 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj, ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod, nullptr); IsError |= Arg.isInvalid(); - TheCall->setArg(i + 1, Arg.get()); + MethodArgs[i + 1] = Arg.get(); } } - if (IsError) return true; + if (IsError) + return true; DiagnoseSentinelCalls(Method, LParenLoc, Args); + // Once we've built TheCall, all of the expressions are properly owned. + QualType ResultTy = Method->getReturnType(); + ExprValueKind VK = Expr::getValueKindForType(ResultTy); + ResultTy = ResultTy.getNonLValueExprType(Context); + + CXXOperatorCallExpr *TheCall = new (Context) + CXXOperatorCallExpr(Context, OO_Call, NewFn.get(), MethodArgs, ResultTy, + VK, RParenLoc, FPOptions()); + + if (CheckCallReturnType(Method->getReturnType(), LParenLoc, TheCall, Method)) + return true; + if (CheckFunctionCall(Method, TheCall, Proto)) return true;