diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 0cb600fb46d14f..dda0d3486e0e69 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -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(); diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 19f8248db6bfd1..877020ed4dcf98 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -4655,6 +4655,8 @@ Sema::DeduceAutoResult 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 index 00000000000000..b77d5335c66192 --- /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 index b63483fba4168a..9b13f4d3e06b13 100644 --- a/clang/test/AST/ast-dump-recovery.cpp +++ b/clang/test/AST/ast-dump-recovery.cpp @@ -178,10 +178,6 @@ void InitializerForAuto() { 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 index fe93cac683ae8d..63aced1a3bf4dd 100644 --- 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 @@ @interface Ivar 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);