Author: Oleksandr T. Date: 2024-11-22T08:46:46+01:00 New Revision: 925e1956cd5039fa2489b802d25555e247c34175
URL: https://github.com/llvm/llvm-project/commit/925e1956cd5039fa2489b802d25555e247c34175 DIFF: https://github.com/llvm/llvm-project/commit/925e1956cd5039fa2489b802d25555e247c34175.diff LOG: [Clang] enhance error recovery with RecoveryExpr for trailing commas in call arguments (#114684) Fixes #100921 Added: Modified: clang/docs/ReleaseNotes.rst clang/include/clang/Parse/Parser.h clang/lib/Parse/ParseExpr.cpp clang/test/AST/ast-dump-recovery.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 8c81de341937ca..4847437ef1f8bd 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -578,6 +578,8 @@ Improvements to Clang's diagnostics - Clang now omits shadowing warnings for parameter names in explicit object member functions (#GH95707). +- Improved error recovery for function call arguments with trailing commas (#GH100921). + Improvements to Clang's time-trace ---------------------------------- diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 045ee754a242b3..d3838a4cc8418c 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -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. diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 4570a18bc0d5e5..736484ded8383c 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -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 @@ -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) @@ -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 diff --git a/clang/test/AST/ast-dump-recovery.cpp b/clang/test/AST/ast-dump-recovery.cpp index a88dff471d9f04..43884622240269 100644 --- a/clang/test/AST/ast-dump-recovery.cpp +++ b/clang/test/AST/ast-dump-recovery.cpp @@ -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> @@ -32,6 +32,26 @@ 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,); + + // FIXME: Handle invalid argument with recovery + // CHECK-NOT: `-RecoveryExpr + some_func2(,1); +} + int ambig_func(double); int ambig_func(float); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits