diff options
author | Bruno Ricci <riccibrun@gmail.com> | 2018-12-03 13:23:56 +0000 |
---|---|---|
committer | Bruno Ricci <riccibrun@gmail.com> | 2018-12-03 13:23:56 +0000 |
commit | 6ef089d21c8853d4623980617f18490ab64c8548 (patch) | |
tree | 099ec18533bdf179e1c8b02994b843b9cbd05ba8 /clang/lib/Sema | |
parent | 7800dbe157eae0b5380afff848e5a930b30ab6ac (diff) | |
download | bcm5719-llvm-6ef089d21c8853d4623980617f18490ab64c8548.tar.gz bcm5719-llvm-6ef089d21c8853d4623980617f18490ab64c8548.zip |
[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
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 48 |
1 files changed, 23 insertions, 25 deletions
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index f36668f7614..b53c0adda94 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<unsigned>(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<Expr *, 8> 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<Expr *, 8> 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<Expr>(); } - 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; |