[AST][RecoveryExpr] Build dependent callexpr in C for error-recovery.

See whole context: https://reviews.llvm.org/D85025

Reviewed By: sammccall

Differential Revision: https://reviews.llvm.org/D84304
This commit is contained in:
Haojian Wu 2020-10-12 11:12:58 +02:00
parent 25e437ec1e
commit bb406f36dc
3 changed files with 35 additions and 2 deletions

View File

@ -6375,6 +6375,21 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
checkDirectCallValidity(*this, Fn, FD, ArgExprs);
}
if (Context.isDependenceAllowed() &&
(Fn->isTypeDependent() || Expr::hasAnyTypeDependentArguments(ArgExprs))) {
assert(!getLangOpts().CPlusPlus);
assert(Fn->containsErrors() ||
llvm::any_of(ArgExprs,
[](clang::Expr *E) { return E->containsErrors(); }) &&
"should only occur in error-recovery path.");
QualType ReturnType =
llvm::isa_and_nonnull<FunctionDecl>(NDecl)
? dyn_cast<FunctionDecl>(NDecl)->getCallResultType()
: Context.DependentTy;
return CallExpr::Create(Context, Fn, ArgExprs, ReturnType,
Expr::getValueKindForType(ReturnType), RParenLoc,
CurFPFeatureOverrides());
}
return BuildResolvedCallExpr(Fn, NDecl, LParenLoc, ArgExprs, RParenLoc,
ExecConfig, IsExecConfig);
}
@ -6515,7 +6530,7 @@ ExprResult Sema::BuildResolvedCallExpr(Expr *Fn, NamedDecl *NDecl,
CurFPFeatureOverrides(), NumParams, UsesADL);
}
if (!getLangOpts().CPlusPlus) {
if (!Context.isDependenceAllowed()) {
// Forget about the nulled arguments since typo correction
// do not handle them well.
TheCall->shrinkNumArgs(Args.size());
@ -19052,7 +19067,7 @@ static ExprResult diagnoseUnknownAnyExpr(Sema &S, Expr *E) {
/// Check for operands with placeholder types and complain if found.
/// Returns ExprError() if there was an error and no recovery was possible.
ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
if (!getLangOpts().CPlusPlus) {
if (!Context.isDependenceAllowed()) {
// C cannot handle TypoExpr nodes on either side of a binop because it
// doesn't handle dependent types properly, so make sure any TypoExprs have
// been dealt with before checking the operands.

View File

@ -87,3 +87,18 @@ void test2() {
// CHECK-NEXT: `-DeclRefExpr {{.*}} 'some_func'
(float)some_func();
}
void test3() {
// CHECK: CallExpr {{.*}} '<dependent type>' contains-errors
// CHECK-NEXT: |-ParenExpr {{.*}} contains-errors lvalue
// CHECK-NEXT: | `-RecoveryExpr {{.*}} contains-errors
// CHECK-NEXT: | `-DeclRefExpr {{.*}} '__builtin_classify_type'
// CHECK-NEXT: `-IntegerLiteral {{.*}} 'int' 1
(*__builtin_classify_type)(1);
extern void ext();
// CHECK: CallExpr {{.*}} 'void' contains-errors
// CHECK-NEXT: |-DeclRefExpr {{.*}} 'ext'
// CHECK-NEXT: `-RecoveryExpr {{.*}} '<dependent type>'
ext(undef_var);
}

View File

@ -10,6 +10,9 @@ void test1(int s) {
// verify diagnostic "operand of type '<dependent type>' where arithmetic or
// pointer type is required" is not emitted.
(float)call(); // expected-error {{too few arguments to function call}}
// verify disgnostic "called object type '<dependent type>' is not a function
// or function pointer" is not emitted.
(*__builtin_classify_type)(1); // expected-error {{builtin functions must be directly called}}
}
void test2(int* ptr, float f) {