[AST][RecoveryExpr] Make DeduceAutoType fail if the auto is deduced from recovery...
authorHaojian Wu <hokein.wu@gmail.com>
Tue, 19 May 2020 16:05:15 +0000 (18:05 +0200)
committerHaojian Wu <hokein.wu@gmail.com>
Fri, 29 May 2020 07:54:28 +0000 (09:54 +0200)
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

clang/lib/Sema/SemaStmt.cpp
clang/lib/Sema/SemaTemplateDeduction.cpp
clang/test/AST/ast-dump-invalid-auto-return-funcs.cpp [new file with mode: 0644]
clang/test/AST/ast-dump-recovery.cpp
clang/test/Sema/invalid-bitwidth-expr.mm

index 0cb600fb46d14f64b93027be0a732edbeec9f805..dda0d3486e0e69f1160760cdb280579d831326aa 100644 (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();
index 19f8248db6bfd1da48d8b8fc9b1490bb84f76c95..877020ed4dcf987850d1d902d86338643cb30bd1 100644 (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())
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 (file)
index 0000000..b77d533
--- /dev/null
@@ -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.
+};
index b63483fba4168a3f05dcea9ef1badeea89815343..9b13f4d3e06b13f22c377066d86edd8dd08eaf12 100644 (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(); }());
index fe93cac683ae8dca77ba9f5423e2991e606fac22..63aced1a3bf4ddcd511d7e58c1fd044a1ee3f218 100644 (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);