Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,8 @@ Improvements to Clang's diagnostics
- Clang now correctly recognises code after a call to a ``[[noreturn]]`` constructor
as unreachable (#GH63009).

- Improved error recovery for function call arguments with trailing commas (#GH100921).

Improvements to Clang's time-trace
----------------------------------

Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -1934,7 +1934,8 @@ class Parser : public CodeCompletionHandler {
llvm::function_ref<void()> ExpressionStarts =
llvm::function_ref<void()>(),
bool FailImmediatelyOnInvalidExpr = false,
bool EarlyTypoCorrection = false);
bool EarlyTypoCorrection = false,
bool *HasTrailingComma = nullptr);

/// ParseSimpleExpressionList - A simple comma-separated list of expressions,
/// used for misc language extensions.
Expand Down
20 changes: 17 additions & 3 deletions clang/lib/Parse/ParseExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2199,10 +2199,17 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
};
if (OpKind == tok::l_paren || !LHS.isInvalid()) {
if (Tok.isNot(tok::r_paren)) {
if (ParseExpressionList(ArgExprs, [&] {
bool HasTrailingComma = false;
bool HasError = ParseExpressionList(
ArgExprs,
[&] {
PreferredType.enterFunctionArgument(Tok.getLocation(),
RunSignatureHelp);
})) {
},
/*FailImmediatelyOnInvalidExpr*/ false,
/*EarlyTypoCorrection*/ false, &HasTrailingComma);

if (HasError && !HasTrailingComma) {
(void)Actions.CorrectDelayedTyposInExpr(LHS);
// If we got an error when parsing expression list, we don't call
// the CodeCompleteCall handler inside the parser. So call it here
Expand Down Expand Up @@ -3662,7 +3669,8 @@ void Parser::injectEmbedTokens() {
bool Parser::ParseExpressionList(SmallVectorImpl<Expr *> &Exprs,
llvm::function_ref<void()> ExpressionStarts,
bool FailImmediatelyOnInvalidExpr,
bool EarlyTypoCorrection) {
bool EarlyTypoCorrection,
bool *HasTrailingComma) {
bool SawError = false;
while (true) {
if (ExpressionStarts)
Expand Down Expand Up @@ -3705,6 +3713,12 @@ bool Parser::ParseExpressionList(SmallVectorImpl<Expr *> &Exprs,
Token Comma = Tok;
ConsumeToken();
checkPotentialAngleBracketDelimiter(Comma);

if (Tok.is(tok::r_paren)) {
if (HasTrailingComma)
*HasTrailingComma = true;
break;
}
}
if (SawError) {
// Ensure typos get diagnosed when errors were encountered while parsing the
Expand Down
21 changes: 20 additions & 1 deletion clang/test/AST/ast-dump-recovery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ int some_func(int *);
// CHECK-NEXT: `-IntegerLiteral {{.*}} 123
// DISABLED-NOT: -RecoveryExpr {{.*}} contains-errors
int invalid_call = some_func(123);
void test_invalid_call(int s) {
void test_invalid_call_1(int s) {
// CHECK: CallExpr {{.*}} '<dependent type>' contains-errors
// CHECK-NEXT: |-UnresolvedLookupExpr {{.*}} 'some_func'
// CHECK-NEXT: |-RecoveryExpr {{.*}} <col:13>
Expand All @@ -32,6 +32,25 @@ void test_invalid_call(int s) {
int var = some_func(undef1);
}

int some_func2(int a, int b);
void test_invalid_call_2() {
// CHECK: -RecoveryExpr {{.*}} 'int' contains-errors
// CHECK-NEXT: `-UnresolvedLookupExpr {{.*}} '<overloaded function type>' lvalue (ADL) = 'some_func2'
some_func2(,);

// CHECK: -RecoveryExpr {{.*}} 'int' contains-errors
// CHECK-NEXT: `-UnresolvedLookupExpr {{.*}} '<overloaded function type>' lvalue (ADL) = 'some_func2'
some_func2(,,);

// CHECK: `-RecoveryExpr {{.*}} 'int' contains-errors
// CHECK-NEXT: |-UnresolvedLookupExpr {{.*}} '<overloaded function type>' lvalue (ADL) = 'some_func2'
// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
some_func2(1,);

// CHECK-NOT: `-RecoveryExpr
some_func2(,1);
}

int ambig_func(double);
int ambig_func(float);

Expand Down