diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3309,6 +3309,7 @@ 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(); diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -4655,6 +4655,8 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result, Optional DependentDeductionDepth, bool IgnoreConstraints) { + if (Init->containsErrors()) + return DAR_FailedAlreadyDiagnosed; if (Init->getType()->isNonOverloadPlaceholderType()) { ExprResult NonPlaceholder = CheckPlaceholderExpr(Init); if (NonPlaceholder.isInvalid()) diff --git a/clang/test/AST/ast-dump-invalid-auto-return-funcs.cpp b/clang/test/AST/ast-dump-invalid-auto-return-funcs.cpp new file mode 100644 --- /dev/null +++ b/clang/test/AST/ast-dump-invalid-auto-return-funcs.cpp @@ -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. +}; diff --git a/clang/test/AST/ast-dump-recovery.cpp b/clang/test/AST/ast-dump-recovery.cpp --- a/clang/test/AST/ast-dump-recovery.cpp +++ b/clang/test/AST/ast-dump-recovery.cpp @@ -178,10 +178,6 @@ auto unresolved_typo = gned.*[] {}; } -// CHECK: `-TypeAliasDecl {{.*}} Escape 'decltype([] { -// CHECK-NEXT: return (undef); -// CHECK-NEXT: }())' -// CHECK-NEXT: `-DecltypeType {{.*}} 'decltype([] { -// CHECK-NEXT: return (undef); -// CHECK-NEXT: }())' dependent +// Verified that the generated call operator is invalid. +// CHECK: |-CXXMethodDecl {{.*}} invalid operator() 'auto () const -> auto' using Escape = decltype([] { return undef(); }()); diff --git a/clang/test/Sema/invalid-bitwidth-expr.mm b/clang/test/Sema/invalid-bitwidth-expr.mm --- a/clang/test/Sema/invalid-bitwidth-expr.mm +++ b/clang/test/Sema/invalid-bitwidth-expr.mm @@ -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 @@ 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);