Skip to content

Commit 6ef089d

Browse files
committed
[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
1 parent 7800dbe commit 6ef089d

File tree

1 file changed

+23
-25
lines changed

1 file changed

+23
-25
lines changed

clang/lib/Sema/SemaOverload.cpp

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13257,29 +13257,14 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
1325713257
if (NewFn.isInvalid())
1325813258
return true;
1325913259

13260+
// The number of argument slots to allocate in the call. If we have default
13261+
// arguments we need to allocate space for them as well. We additionally
13262+
// need one more slot for the object parameter.
13263+
unsigned NumArgsSlots = 1 + std::max<unsigned>(Args.size(), NumParams);
13264+
1326013265
// Build the full argument list for the method call (the implicit object
1326113266
// parameter is placed at the beginning of the list).
13262-
SmallVector<Expr *, 8> MethodArgs(Args.size() + 1);
13263-
MethodArgs[0] = Object.get();
13264-
std::copy(Args.begin(), Args.end(), MethodArgs.begin() + 1);
13265-
13266-
// Once we've built TheCall, all of the expressions are properly
13267-
// owned.
13268-
QualType ResultTy = Method->getReturnType();
13269-
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
13270-
ResultTy = ResultTy.getNonLValueExprType(Context);
13271-
13272-
CXXOperatorCallExpr *TheCall = new (Context)
13273-
CXXOperatorCallExpr(Context, OO_Call, NewFn.get(), MethodArgs, ResultTy,
13274-
VK, RParenLoc, FPOptions());
13275-
13276-
if (CheckCallReturnType(Method->getReturnType(), LParenLoc, TheCall, Method))
13277-
return true;
13278-
13279-
// We may have default arguments. If so, we need to allocate more
13280-
// slots in the call for them.
13281-
if (Args.size() < NumParams)
13282-
TheCall->setNumArgs(Context, NumParams + 1);
13267+
SmallVector<Expr *, 8> MethodArgs(NumArgsSlots);
1328313268

1328413269
bool IsError = false;
1328513270

@@ -13291,7 +13276,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
1329113276
IsError = true;
1329213277
else
1329313278
Object = ObjRes;
13294-
TheCall->setArg(0, Object.get());
13279+
MethodArgs[0] = Object.get();
1329513280

1329613281
// Check the argument types.
1329713282
for (unsigned i = 0; i != NumParams; i++) {
@@ -13320,7 +13305,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
1332013305
Arg = DefArg.getAs<Expr>();
1332113306
}
1332213307

13323-
TheCall->setArg(i + 1, Arg);
13308+
MethodArgs[i + 1] = Arg;
1332413309
}
1332513310

1332613311
// If this is a variadic call, handle args passed through "...".
@@ -13330,14 +13315,27 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Obj,
1333013315
ExprResult Arg = DefaultVariadicArgumentPromotion(Args[i], VariadicMethod,
1333113316
nullptr);
1333213317
IsError |= Arg.isInvalid();
13333-
TheCall->setArg(i + 1, Arg.get());
13318+
MethodArgs[i + 1] = Arg.get();
1333413319
}
1333513320
}
1333613321

13337-
if (IsError) return true;
13322+
if (IsError)
13323+
return true;
1333813324

1333913325
DiagnoseSentinelCalls(Method, LParenLoc, Args);
1334013326

13327+
// Once we've built TheCall, all of the expressions are properly owned.
13328+
QualType ResultTy = Method->getReturnType();
13329+
ExprValueKind VK = Expr::getValueKindForType(ResultTy);
13330+
ResultTy = ResultTy.getNonLValueExprType(Context);
13331+
13332+
CXXOperatorCallExpr *TheCall = new (Context)
13333+
CXXOperatorCallExpr(Context, OO_Call, NewFn.get(), MethodArgs, ResultTy,
13334+
VK, RParenLoc, FPOptions());
13335+
13336+
if (CheckCallReturnType(Method->getReturnType(), LParenLoc, TheCall, Method))
13337+
return true;
13338+
1334113339
if (CheckFunctionCall(Method, TheCall, Proto))
1334213340
return true;
1334313341

0 commit comments

Comments
 (0)