Skip to content

Commit a7da36b

Browse files
committed
Merging r354035:
------------------------------------------------------------------------ r354035 | brunoricci | 2019-02-14 16:43:17 +0100 (Thu, 14 Feb 2019) | 23 lines [Sema] Fix a regression introduced in "[AST][Sema] Remove CallExpr::setNumArgs" D54902 removed CallExpr::setNumArgs in preparation of tail-allocating the arguments of CallExpr. It did this by allocating storage for max(number of arguments, number of parameters in the prototype). The temporarily nulled arguments however causes issues in BuildResolvedCallExpr when typo correction is done just after the creation of the call expression. This was unfortunately missed by the tests /: To fix this, delay setting the number of arguments to max(number of arguments, number of parameters in the prototype) until we are ready for it. It would be nice to have this encapsulated in CallExpr but this is the best I can come up with under the constraint that we cannot add anything the CallExpr. Fixes PR40286. Differential Revision: https://reviews.llvm.org/D57948 Reviewed By: aaron.ballman ------------------------------------------------------------------------ llvm-svn: 354247
1 parent 8015928 commit a7da36b

File tree

3 files changed

+42
-4
lines changed

3 files changed

+42
-4
lines changed

clang/include/clang/AST/Expr.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2577,6 +2577,11 @@ class CallExpr : public Expr {
25772577
NumArgs = NewNumArgs;
25782578
}
25792579

2580+
/// Bluntly set a new number of arguments without doing any checks whatsoever.
2581+
/// Only used during construction of a CallExpr in a few places in Sema.
2582+
/// FIXME: Find a way to remove it.
2583+
void setNumArgsUnsafe(unsigned NewNumArgs) { NumArgs = NewNumArgs; }
2584+
25802585
typedef ExprIterator arg_iterator;
25812586
typedef ConstExprIterator const_arg_iterator;
25822587
typedef llvm::iterator_range<arg_iterator> arg_range;

clang/lib/Sema/SemaExpr.cpp

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5676,18 +5676,36 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
56765676
}
56775677

56785678
if (!getLangOpts().CPlusPlus) {
5679+
// Forget about the nulled arguments since typo correction
5680+
// do not handle them well.
5681+
TheCall->shrinkNumArgs(Args.size());
56795682
// C cannot always handle TypoExpr nodes in builtin calls and direct
56805683
// function calls as their argument checking don't necessarily handle
56815684
// dependent types properly, so make sure any TypoExprs have been
56825685
// dealt with.
56835686
ExprResult Result = CorrectDelayedTyposInExpr(TheCall);
56845687
if (!Result.isUsable()) return ExprError();
5688+
CallExpr *TheOldCall = TheCall;
56855689
TheCall = dyn_cast<CallExpr>(Result.get());
5690+
bool CorrectedTypos = TheCall != TheOldCall;
56865691
if (!TheCall) return Result;
5687-
// TheCall at this point has max(Args.size(), NumParams) arguments,
5688-
// with extra arguments nulled. We don't want to introduce nulled
5689-
// arguments in Args and so we only take the first Args.size() arguments.
5690-
Args = llvm::makeArrayRef(TheCall->getArgs(), Args.size());
5692+
Args = llvm::makeArrayRef(TheCall->getArgs(), TheCall->getNumArgs());
5693+
5694+
// A new call expression node was created if some typos were corrected.
5695+
// However it may not have been constructed with enough storage. In this
5696+
// case, rebuild the node with enough storage. The waste of space is
5697+
// immaterial since this only happens when some typos were corrected.
5698+
if (CorrectedTypos && Args.size() < NumParams) {
5699+
if (Config)
5700+
TheCall = CUDAKernelCallExpr::Create(
5701+
Context, Fn, cast<CallExpr>(Config), Args, ResultTy, VK_RValue,
5702+
RParenLoc, NumParams);
5703+
else
5704+
TheCall = CallExpr::Create(Context, Fn, Args, ResultTy, VK_RValue,
5705+
RParenLoc, NumParams, UsesADL);
5706+
}
5707+
// We can now handle the nulled arguments for the default arguments.
5708+
TheCall->setNumArgsUnsafe(std::max<unsigned>(Args.size(), NumParams));
56915709
}
56925710

56935711
// Bail out early if calling a builtin with custom type checking.

clang/test/Sema/typo-correction.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,18 @@ void rdar38642201_caller() {
100100
structVar1.fieldName1.member1, //expected-error{{use of undeclared identifier 'structVar1'}}
101101
structVar2.fieldName2.member2); //expected-error{{use of undeclared identifier 'structVar2'}}
102102
}
103+
104+
void PR40286_g(int x, int y);
105+
void PR40286_h(int x, int y, int z);
106+
void PR40286_1(int the_value) {
107+
PR40286_g(the_walue); // expected-error {{use of undeclared identifier 'the_walue'}}
108+
}
109+
void PR40286_2(int the_value) {
110+
PR40286_h(the_value, the_walue); // expected-error {{use of undeclared identifier 'the_walue'}}
111+
}
112+
void PR40286_3(int the_value) {
113+
PR40286_h(the_walue); // expected-error {{use of undeclared identifier 'the_walue'}}
114+
}
115+
void PR40286_4(int the_value) { // expected-note {{'the_value' declared here}}
116+
PR40286_h(the_value, the_value, the_walue); // expected-error {{use of undeclared identifier 'the_walue'; did you mean 'the_value'?}}
117+
}

0 commit comments

Comments
 (0)