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

Haojian Wu via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue May 19 09:49:18 PDT 2020


hokein created this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
hokein updated this revision to Diff 264951.
hokein added a comment.
hokein marked an inline comment as done.
hokein added a reviewer: sammccall.
hokein added a subscriber: rsmith.

small update



================
Comment at: clang/test/AST/ast-dump-recovery.cpp:182
+// Verified that the generated call operator is invalid.
+// CHECK: |-CXXMethodDecl {{.*}} invalid operator() 'auto () const -> auto'
 using Escape = decltype([] { return undef(); }());
----------------
with this patch, we don't preserve the return stmt, so we only have the CXXRecordDecl for the lambda, and no `TypeAliasDecl ` node.


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.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D80221

Files:
  clang/lib/Sema/SemaStmt.cpp
  clang/lib/Sema/SemaTemplateDeduction.cpp
  clang/test/AST/ast-dump-invalid-auto-return-funcs.cpp
  clang/test/AST/ast-dump-recovery.cpp
  clang/test/Sema/invalid-bitwidth-expr.mm


Index: clang/test/Sema/invalid-bitwidth-expr.mm
===================================================================
--- clang/test/Sema/invalid-bitwidth-expr.mm
+++ 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);
Index: clang/test/AST/ast-dump-recovery.cpp
===================================================================
--- clang/test/AST/ast-dump-recovery.cpp
+++ clang/test/AST/ast-dump-recovery.cpp
@@ -178,10 +178,6 @@
   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: clang/test/AST/ast-dump-invalid-auto-return-funcs.cpp
===================================================================
--- /dev/null
+++ clang/test/AST/ast-dump-invalid-auto-return-funcs.cpp
@@ -0,0 +1,27 @@
+// 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
+// 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: clang/lib/Sema/SemaTemplateDeduction.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateDeduction.cpp
+++ clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -4655,6 +4655,9 @@
 Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result,
                      Optional<unsigned> DependentDeductionDepth,
                      bool IgnoreConstraints) {
+  // FIXME: continue the following steps if the type is known.
+  if (Init->containsErrors())
+    return DAR_FailedAlreadyDiagnosed;
   if (Init->getType()->isNonOverloadPlaceholderType()) {
     ExprResult NonPlaceholder = CheckPlaceholderExpr(Init);
     if (NonPlaceholder.isInvalid())
Index: clang/lib/Sema/SemaStmt.cpp
===================================================================
--- clang/lib/Sema/SemaStmt.cpp
+++ 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();


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D80221.264951.patch
Type: text/x-patch
Size: 3844 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20200519/c1dfd143/attachment.bin>


More information about the cfe-commits mailing list