forked from OSchip/llvm-project
[AST][RecoveryExpr] Fix the value category for recovery expr.
RecoveryExpr was always lvalue, but it is wrong if we use it to model broken function calls, function call expression has more compliated rules: - a call to a function whose return type is an lvalue reference yields an lvalue; - a call to a function whose return type is an rvalue reference yields an xvalue; - a call to a function whose return type is nonreference type yields a prvalue; This patch makes the recovery-expr align with the function call if it is modeled a broken call. Differential revision: https://reviews.llvm.org/D83201
This commit is contained in:
parent
695b33a569
commit
96a5cfff20
|
@ -4779,8 +4779,10 @@ QualType OMPArraySectionExpr::getBaseOriginalType(const Expr *Base) {
|
|||
|
||||
RecoveryExpr::RecoveryExpr(ASTContext &Ctx, QualType T, SourceLocation BeginLoc,
|
||||
SourceLocation EndLoc, ArrayRef<Expr *> 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; }));
|
||||
|
||||
|
|
|
@ -130,7 +130,6 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
|
|||
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 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
|
|||
return Cl::CL_PRValue;
|
||||
}
|
||||
|
||||
case Expr::RecoveryExprClass:
|
||||
case Expr::OpaqueValueExprClass:
|
||||
return ClassifyExprValueKind(Lang, E, E->getValueKind());
|
||||
|
||||
|
|
|
@ -12818,7 +12818,7 @@ static QualType chooseRecoveryType(OverloadCandidateSet &CS,
|
|||
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)
|
||||
|
|
|
@ -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(double);
|
|||
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 @@ struct {
|
|||
} 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.
|
||||
}
|
||||
|
|
|
@ -62,3 +62,9 @@ constexpr auto x2 = AA<int>::foo2(); // expected-error {{be initialized by a con
|
|||
// 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}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue