[llvm-branch-commits] [clang] 556e4eb - [AST][RecoveryAST] Preserve type for member call expr if argments are not matched.
Haojian Wu via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Dec 11 01:42:23 PST 2020
Author: Haojian Wu
Date: 2020-12-11T10:38:03+01:00
New Revision: 556e4eba4404acdc003ce344a62de846c0661be2
URL: https://github.com/llvm/llvm-project/commit/556e4eba4404acdc003ce344a62de846c0661be2
DIFF: https://github.com/llvm/llvm-project/commit/556e4eba4404acdc003ce344a62de846c0661be2.diff
LOG: [AST][RecoveryAST] Preserve type for member call expr if argments are not matched.
Differential Revision: https://reviews.llvm.org/D92298
Added:
Modified:
clang/include/clang/Sema/Sema.h
clang/lib/Sema/SemaExpr.cpp
clang/lib/Sema/SemaOverload.cpp
clang/test/AST/ast-dump-recovery.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 9c838e574283..04e2b9553f4c 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -3723,11 +3723,11 @@ class Sema final {
SourceLocation RLoc,
Expr *Base,Expr *Idx);
- ExprResult
- BuildCallToMemberFunction(Scope *S, Expr *MemExpr,
- SourceLocation LParenLoc,
- MultiExprArg Args,
- SourceLocation RParenLoc);
+ ExprResult BuildCallToMemberFunction(Scope *S, Expr *MemExpr,
+ SourceLocation LParenLoc,
+ MultiExprArg Args,
+ SourceLocation RParenLoc,
+ bool AllowRecovery = false);
ExprResult
BuildCallToObjectOfClassType(Scope *S, Expr *Object, SourceLocation LParenLoc,
MultiExprArg Args,
@@ -5238,7 +5238,8 @@ class Sema final {
ExprResult BuildCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc,
MultiExprArg ArgExprs, SourceLocation RParenLoc,
Expr *ExecConfig = nullptr,
- bool IsExecConfig = false);
+ bool IsExecConfig = false,
+ bool AllowRecovery = false);
enum class AtomicArgumentOrder { API, AST };
ExprResult
BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange,
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 859960d13007..0e829230d6a8 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -6309,7 +6309,8 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
MultiExprArg ArgExprs, SourceLocation RParenLoc,
Expr *ExecConfig) {
ExprResult Call =
- BuildCallExpr(Scope, Fn, LParenLoc, ArgExprs, RParenLoc, ExecConfig);
+ BuildCallExpr(Scope, Fn, LParenLoc, ArgExprs, RParenLoc, ExecConfig,
+ /*IsExecConfig=*/false, /*AllowRecovery=*/true);
if (Call.isInvalid())
return Call;
@@ -6337,7 +6338,8 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
/// locations.
ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
MultiExprArg ArgExprs, SourceLocation RParenLoc,
- Expr *ExecConfig, bool IsExecConfig) {
+ Expr *ExecConfig, bool IsExecConfig,
+ bool AllowRecovery) {
// Since this might be a postfix expression, get rid of ParenListExprs.
ExprResult Result = MaybeConvertParenListExprToParenExpr(Scope, Fn);
if (Result.isInvalid()) return ExprError();
@@ -6397,7 +6399,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
if (Fn->getType() == Context.BoundMemberTy) {
return BuildCallToMemberFunction(Scope, Fn, LParenLoc, ArgExprs,
- RParenLoc);
+ RParenLoc, AllowRecovery);
}
}
@@ -6416,7 +6418,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
Scope, Fn, ULE, LParenLoc, ArgExprs, RParenLoc, ExecConfig,
/*AllowTypoCorrection=*/true, find.IsAddressOfOperand);
return BuildCallToMemberFunction(Scope, Fn, LParenLoc, ArgExprs,
- RParenLoc);
+ RParenLoc, AllowRecovery);
}
}
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index ff010fd6e4df..5689efe578fa 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -14154,11 +14154,11 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
/// parameter). The caller needs to validate that the member
/// expression refers to a non-static member function or an overloaded
/// member function.
-ExprResult
-Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
- SourceLocation LParenLoc,
- MultiExprArg Args,
- SourceLocation RParenLoc) {
+ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
+ SourceLocation LParenLoc,
+ MultiExprArg Args,
+ SourceLocation RParenLoc,
+ bool AllowRecovery) {
assert(MemExprE->getType() == Context.BoundMemberTy ||
MemExprE->getType() == Context.OverloadTy);
@@ -14215,6 +14215,17 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
return MaybeBindToTemporary(call);
}
+ // We only try to build a recovery expr at this level if we can preserve
+ // the return type, otherwise we return ExprError() and let the caller
+ // recover.
+ auto BuildRecoveryExpr = [&](QualType Type) {
+ if (!AllowRecovery)
+ return ExprError();
+ std::vector<Expr *> SubExprs = {MemExprE};
+ llvm::for_each(Args, [&SubExprs](Expr *E) { SubExprs.push_back(E); });
+ return CreateRecoveryExpr(MemExprE->getBeginLoc(), RParenLoc, SubExprs,
+ Type);
+ };
if (isa<CXXPseudoDestructorExpr>(NakedMemExpr))
return CallExpr::Create(Context, MemExprE, Args, Context.VoidTy, VK_RValue,
RParenLoc, CurFPFeatureOverrides());
@@ -14362,7 +14373,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
// Check for a valid return type.
if (CheckCallReturnType(Method->getReturnType(), MemExpr->getMemberLoc(),
TheCall, Method))
- return ExprError();
+ return BuildRecoveryExpr(ResultType);
// Convert the object argument (for a non-static member function call).
// We only need to do this if there was actually an overload; otherwise
@@ -14379,7 +14390,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
// Convert the rest of the arguments
if (ConvertArgumentsForCall(TheCall, MemExpr, Method, Proto, Args,
RParenLoc))
- return ExprError();
+ return BuildRecoveryExpr(ResultType);
DiagnoseSentinelCalls(Method, LParenLoc, Args);
diff --git a/clang/test/AST/ast-dump-recovery.cpp b/clang/test/AST/ast-dump-recovery.cpp
index 366b3bfd9e07..2a8346eb0d15 100644
--- a/clang/test/AST/ast-dump-recovery.cpp
+++ b/clang/test/AST/ast-dump-recovery.cpp
@@ -121,6 +121,23 @@ void test(int x) {
foo->func(x);
}
+struct Foo2 {
+ double func();
+ class ForwardClass;
+ ForwardClass createFwd();
+};
+void test2(Foo2 f) {
+ // CHECK: RecoveryExpr {{.*}} 'double'
+ // CHECK-NEXT: |-MemberExpr {{.*}} '<bound member function type>'
+ // CHECK-NEXT: | `-DeclRefExpr {{.*}} 'f'
+ // CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
+ f.func(1);
+ // CHECK: RecoveryExpr {{.*}} 'Foo2::ForwardClass'
+ // CHECK-NEXT: `-MemberExpr {{.*}} '<bound member function type>' .createFwd
+ // CHECK-NEXT: `-DeclRefExpr {{.*}} 'f'
+ f.createFwd();
+}
+
// CHECK: |-AlignedAttr {{.*}} alignas
// CHECK-NEXT:| `-RecoveryExpr {{.*}} contains-errors
// CHECK-NEXT:| `-UnresolvedLookupExpr {{.*}} 'invalid'
More information about the llvm-branch-commits
mailing list