diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -3896,6 +3896,8 @@ void DiagnoseAmbiguousLookup(LookupResult &Result); //@} + /// Rebuild the given Expr with the TypoExpr degraded to RecoveryExpr. + ExprResult rebuildTypoExprs(Expr *TypoExpr); /// Attempts to produce a RecoveryExpr after some AST node cannot be created. ExprResult CreateRecoveryExpr(SourceLocation Begin, SourceLocation End, ArrayRef SubExprs, diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -12015,6 +12015,9 @@ InitializationSequence Init(*this, Entity, Kind, MultiExprArg(E)); return Init.Failed() ? ExprError() : E; }); + if (Res.isInvalid()) + Res = rebuildTypoExprs(Args[Idx]); + if (Res.isInvalid()) { VDecl->setInvalidDecl(); } else if (Res.get() != Args[Idx]) { diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -19175,6 +19175,17 @@ ObjCAvailabilityCheckExpr(Version, AtLoc, RParen, Context.BoolTy); } +ExprResult Sema::rebuildTypoExprs(Expr *TypoExpr) { + struct TyposReplace : TreeTransform { + TyposReplace(Sema &SemaRef) : TreeTransform(SemaRef) {} + ExprResult TransformTypoExpr(clang::TypoExpr *E) { + return this->SemaRef.CreateRecoveryExpr(E->getBeginLoc(), E->getEndLoc(), + {}); + } + } TT(*this); + return TT.TransformExpr(TypoExpr); +} + ExprResult Sema::CreateRecoveryExpr(SourceLocation Begin, SourceLocation End, ArrayRef SubExprs, QualType T) { // FIXME: enable it for C++, RecoveryExpr is type-dependent to suppress diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -8305,17 +8305,7 @@ FullExpr = CorrectDelayedTyposInExpr(FullExpr.get()); if (FullExpr.isInvalid()) { - // Typo-correction fails, we rebuild the broken AST with the typos degraded - // to RecoveryExpr. - struct TyposReplace : TreeTransform { - TyposReplace(Sema &SemaRef) : TreeTransform(SemaRef) {} - ExprResult TransformTypoExpr(TypoExpr *E) { - return this->SemaRef.CreateRecoveryExpr(E->getBeginLoc(), - E->getEndLoc(), {}); - } - } TT(*this); - - return TT.TransformExpr(FE); + return rebuildTypoExprs(FE); } CheckCompletedExpr(FullExpr.get(), CC, IsConstexpr); diff --git a/clang/test/AST/ast-dump-recovery.cpp b/clang/test/AST/ast-dump-recovery.cpp --- a/clang/test/AST/ast-dump-recovery.cpp +++ b/clang/test/AST/ast-dump-recovery.cpp @@ -25,8 +25,11 @@ // CHECK-NEXT: |-UnresolvedLookupExpr {{.*}} 'some_func' // CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors s = some_func(undef1); - // CHECK: `-VarDecl {{.*}} invalid var 'int' - // FIXME: preserve the broken call. + + // CHECK: VarDecl {{.*}} var 'int' + // CHECK-NEXT: `-CallExpr {{.*}} '' contains-errors + // CHECK-NEXT: |-UnresolvedLookupExpr {{.*}} 'some_func' + // CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors int var = some_func(undef1); } @@ -176,6 +179,12 @@ // CHECK-NEXT: `-RecoveryExpr {{.*}} contains-errors // CHECK-NEXT: `-UnresolvedLookupExpr {{.*}} 'invalid' Bar b6 = Bar{invalid()}; + + // CHECK: `-VarDecl {{.*}} var1 + // CHECK-NEXT: `-BinaryOperator {{.*}} '' contains-errors + // CHECK-NEXT: |-RecoveryExpr {{.*}} '' contains-errors + // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1 + int var1 = undef + 1; } void InitializerForAuto() { // CHECK: `-VarDecl {{.*}} invalid a 'auto'