[AST][RecoveryExpr] Make DeduceAutoType fail if the auto is deduced from recovery exprs.

Summary:
With recovery-ast, we will get an undeduced `auto` return type for
"auto foo()->undef()" function declaration, the function decl still keeps
valid, it is dangerous, and breaks assumptions in clang, and leads crashes.

This patch invalidates these functions, if we deduce autos from the
return rexpression, which is similar to auto VarDecl.

Subscribers: cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D80221
This commit is contained in:
Haojian Wu 2020-05-19 18:05:15 +02:00
parent 7fb8a40e52
commit 82bb57c11d
5 changed files with 41 additions and 7 deletions

View File

@ -3309,6 +3309,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) {
assert(AT && "lost auto type from lambda return type");
if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) {
FD->setInvalidDecl();
// FIXME: preserve the ill-formed return expression.
return StmtError();
}
CurCap->ReturnType = FnRetType = FD->getReturnType();

View File

@ -4655,6 +4655,8 @@ Sema::DeduceAutoResult
Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result,
Optional<unsigned> DependentDeductionDepth,
bool IgnoreConstraints) {
if (Init->containsErrors())
return DAR_FailedAlreadyDiagnosed;
if (Init->getType()->isNonOverloadPlaceholderType()) {
ExprResult NonPlaceholder = CheckPlaceholderExpr(Init);
if (NonPlaceholder.isInvalid())

View File

@ -0,0 +1,28 @@
// RUN: not %clang_cc1 -triple x86_64-unknown-unknown -Wno-unused-value -fcxx-exceptions -frecovery-ast -std=gnu++17 -ast-dump %s | FileCheck -strict-whitespace %s
// CHECK: FunctionDecl {{.*}} s1 'auto ()'
auto s1(); // valid
// FIXME: why we're finding int as the return type. int is used as a fallback type?
// CHECK: FunctionDecl {{.*}} invalid s2 'auto () -> int'
auto s2() -> undef();
// CHECK: FunctionDecl {{.*}} invalid s3 'auto () -> int'
auto s3() -> decltype(undef());
// CHECK: FunctionDecl {{.*}} invalid s4 'auto ()'
auto s4() {
return undef();
}
// CHECK: FunctionDecl {{.*}} s5 'void ()'
auto s5() {} // valid, no return stmt, fallback to void
class Foo {
// CHECK: CXXMethodDecl {{.*}} foo1 'auto ()'
auto foo1(); // valid
// CHECK: CXXMethodDecl {{.*}} invalid foo2 'auto () -> int'
auto foo2() -> undef();
// CHECK: CXXMethodDecl {{.*}} invalid foo3 'auto () -> int'
auto foo3() -> decltype(undef());
// CHECK: CXXMethodDecl {{.*}} invalid foo4 'auto ()'
auto foo4() { return undef(); }
// CHECK: CXXMethodDecl {{.*}} foo5 'void ()'
auto foo5() {} // valid, no return stmt, fallback to void.
};

View File

@ -178,10 +178,6 @@ void InitializerForAuto() {
auto unresolved_typo = gned.*[] {};
}
// CHECK: `-TypeAliasDecl {{.*}} Escape 'decltype([] {
// CHECK-NEXT: return <recovery-expr>(undef);
// CHECK-NEXT: }())'
// CHECK-NEXT: `-DecltypeType {{.*}} 'decltype([] {
// CHECK-NEXT: return <recovery-expr>(undef);
// CHECK-NEXT: }())' dependent
// Verified that the generated call operator is invalid.
// CHECK: |-CXXMethodDecl {{.*}} invalid operator() 'auto () const -> auto'
using Escape = decltype([] { return undef(); }());

View File

@ -1,5 +1,4 @@
// RUN: %clang_cc1 -fobjc-runtime=gcc -frecovery-ast -verify %s
// RUN: %clang_cc1 -fobjc-runtime=gcc -fno-recovery-ast -verify %s
@interface Ivar
{
@ -11,3 +10,11 @@ struct X { int Y: foo(); }; // expected-error {{use of undeclared identifier}}
constexpr int s = sizeof(Ivar);
constexpr int ss = sizeof(X);
auto func() {
return undef(); // expected-error {{use of undeclared identifier}}
}
struct Y {
int X : func();
};
constexpr int sss = sizeof(Y);