diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -4779,8 +4779,10 @@ RecoveryExpr::RecoveryExpr(ASTContext &Ctx, QualType T, SourceLocation BeginLoc, SourceLocation EndLoc, ArrayRef SubExprs) - : Expr(RecoveryExprClass, T, VK_LValue, OK_Ordinary), BeginLoc(BeginLoc), - EndLoc(EndLoc), NumExprs(SubExprs.size()) { + : Expr(RecoveryExprClass, T.getNonReferenceType(), + T->isDependentType() ? VK_LValue : getValueKindForType(T), + OK_Ordinary), + BeginLoc(BeginLoc), EndLoc(EndLoc), NumExprs(SubExprs.size()) { assert(!T.isNull()); assert(llvm::all_of(SubExprs, [](Expr* E) { return E != nullptr; })); diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp --- a/clang/lib/AST/ExprClassification.cpp +++ b/clang/lib/AST/ExprClassification.cpp @@ -130,7 +130,6 @@ case Expr::UnresolvedLookupExprClass: case Expr::UnresolvedMemberExprClass: case Expr::TypoExprClass: - case Expr::RecoveryExprClass: case Expr::DependentCoawaitExprClass: case Expr::CXXDependentScopeMemberExprClass: case Expr::DependentScopeDeclRefExprClass: @@ -276,6 +275,7 @@ return Cl::CL_PRValue; } + case Expr::RecoveryExprClass: case Expr::OpaqueValueExprClass: return ClassifyExprValueKind(Lang, E, E->getValueKind()); diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -12818,7 +12818,7 @@ auto ConsiderCandidate = [&](const OverloadCandidate &Candidate) { if (!Candidate.Function) return; - QualType T = Candidate.Function->getCallResultType(); + QualType T = Candidate.Function->getReturnType(); if (T.isNull()) return; if (!Result) 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 @@ -4,7 +4,6 @@ int some_func(int *); // CHECK: VarDecl {{.*}} invalid_call -// CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'int' contains-errors // CHECK-NEXT: `-RecoveryExpr {{.*}} 'int' contains-errors // CHECK-NEXT: |-UnresolvedLookupExpr {{.*}} 'some_func' // CHECK-NEXT: `-IntegerLiteral {{.*}} 123 @@ -34,7 +33,6 @@ int ambig_func(float); // CHECK: VarDecl {{.*}} ambig_call -// CHECK-NEXT: `-ImplicitCastExpr {{.*}} 'int' contains-errors // CHECK-NEXT: `-RecoveryExpr {{.*}} 'int' contains-errors // CHECK-NEXT: |-UnresolvedLookupExpr {{.*}} 'ambig_func' // CHECK-NEXT: `-IntegerLiteral {{.*}} 123 @@ -211,3 +209,16 @@ } NoCrashOnInvalidInitList = { .abc = nullptr, }; + +// Verify the value category of recovery expression. +int prvalue(int); +int &lvalue(int); +int &&xvalue(int); +void ValueCategory() { + // CHECK: RecoveryExpr {{.*}} 'int' contains-errors + prvalue(); // call to a function (nonreference return type) yields a prvalue (not print by default) + // CHECK: RecoveryExpr {{.*}} 'int' contains-errors lvalue + lvalue(); // call to a function (lvalue reference return type) yields an lvalue. + // CHECK: RecoveryExpr {{.*}} 'int' contains-errors xvalue + xvalue(); // call to a function (rvalue reference return type) yields an xvalue. +} diff --git a/clang/test/SemaCXX/recovery-expr-type.cpp b/clang/test/SemaCXX/recovery-expr-type.cpp --- a/clang/test/SemaCXX/recovery-expr-type.cpp +++ b/clang/test/SemaCXX/recovery-expr-type.cpp @@ -62,3 +62,9 @@ // expected-note {{in instantiation of member function}} \ // expected-note {{in call to}} } + +// verify no assertion failure on violating value category. +namespace test4 { +int &&f(int); // expected-note {{candidate function not viable}} +int &&k = f(); // expected-error {{no matching function for call}} +}