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 @@ -6375,6 +6375,21 @@ 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(NDecl) + ? dyn_cast(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 @@ 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 @@ /// 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. diff --git a/clang/test/AST/ast-dump-recovery.c b/clang/test/AST/ast-dump-recovery.c --- a/clang/test/AST/ast-dump-recovery.c +++ b/clang/test/AST/ast-dump-recovery.c @@ -87,3 +87,18 @@ // CHECK-NEXT: `-DeclRefExpr {{.*}} 'some_func' (float)some_func(); } + +void test3() { + // CHECK: CallExpr {{.*}} '' 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 {{.*}} '' + ext(undef_var); +} diff --git a/clang/test/Sema/error-dependence.c b/clang/test/Sema/error-dependence.c --- a/clang/test/Sema/error-dependence.c +++ b/clang/test/Sema/error-dependence.c @@ -10,6 +10,9 @@ // verify diagnostic "operand of 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 '' 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) {