Author: Haojian Wu Date: 2020-05-29T09:54:28+02:00 New Revision: 82bb57c11d8ccb4e1b0f420f4388dd6553bbc57a
URL: https://github.com/llvm/llvm-project/commit/82bb57c11d8ccb4e1b0f420f4388dd6553bbc57a DIFF: https://github.com/llvm/llvm-project/commit/82bb57c11d8ccb4e1b0f420f4388dd6553bbc57a.diff LOG: [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 Added: clang/test/AST/ast-dump-invalid-auto-return-funcs.cpp Modified: clang/lib/Sema/SemaStmt.cpp clang/lib/Sema/SemaTemplateDeduction.cpp clang/test/AST/ast-dump-recovery.cpp clang/test/Sema/invalid-bitwidth-expr.mm Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 0cb600fb46d1..dda0d3486e0e 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 19f8248db6bf..877020ed4dcf 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<unsigned> 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 000000000000..b77d5335c661 --- /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 b63483fba416..9b13f4d3e06b 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 <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(); }()); diff --git a/clang/test/Sema/invalid-bitwidth-expr.mm b/clang/test/Sema/invalid-bitwidth-expr.mm index fe93cac683ae..63aced1a3bf4 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); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits