llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Kartik Ohlan (Ko496-glitch)

<details>
<summary>Changes</summary>

This fixes a crash where the compiler would blow up if you tried to return an 
initializer list from a void lambda. It also cleans up the error message so it 
actually says "lambda" instead of "block" when that's what you're actually 
using.

Added the check for isa&lt;InitListExpr&gt;(RetValExp) checker


---
Full diff: https://github.com/llvm/llvm-project/pull/188904.diff


3 Files Affected:

- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+2-1) 
- (modified) clang/lib/Sema/SemaStmt.cpp (+10-7) 
- (added) clang/test/SemaCXX/void-lambda-return-init.cpp (+25) 


``````````diff
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 0c25eb2443d5e..05efa47210384 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7426,7 +7426,8 @@ def err_illegal_decl_mempointer_in_nonclass
 def err_reference_to_void : Error<"cannot form a reference to 'void'">;
 def err_nonfunction_block_type : Error<
   "block pointer to non-function type is invalid">;
-def err_return_block_has_expr : Error<"void block should not return a value">;
+def err_return_block_has_expr : Error<
+  "void %select{block|lambda}0 should not return a value">;
 def err_block_return_missing_expr : Error<
   "non-void block should return a value">;
 def err_func_def_incomplete_result : Error<
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index b74af55d1bea1..87414564c82d0 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -3715,15 +3715,18 @@ StmtResult Sema::ActOnCapScopeReturnStmt(SourceLocation 
ReturnLoc,
     // Delay processing for now.  TODO: there are lots of dependent
     // types we can conclusively prove aren't void.
   } else if (FnRetType->isVoidType()) {
-    if (RetValExp && !isa<InitListExpr>(RetValExp) &&
-        !(getLangOpts().CPlusPlus &&
-          (RetValExp->isTypeDependent() ||
-           RetValExp->getType()->isVoidType()))) {
-      if (!getLangOpts().CPlusPlus &&
-          RetValExp->getType()->isVoidType())
+    if (RetValExp && isa<InitListExpr>(RetValExp)) {
+      Diag(ReturnLoc, diag::err_return_block_has_expr)
+          << (getCurLambda() != nullptr);
+      RetValExp = nullptr;
+    } else if (RetValExp && !(getLangOpts().CPlusPlus &&
+                              (RetValExp->isTypeDependent() ||
+                               RetValExp->getType()->isVoidType()))) {
+      if (!getLangOpts().CPlusPlus && RetValExp->getType()->isVoidType())
         Diag(ReturnLoc, diag::ext_return_has_void_expr) << "literal" << 2;
       else {
-        Diag(ReturnLoc, diag::err_return_block_has_expr);
+        Diag(ReturnLoc, diag::err_return_block_has_expr)
+            << (getCurLambda() != nullptr);
         RetValExp = nullptr;
       }
     }
diff --git a/clang/test/SemaCXX/void-lambda-return-init.cpp 
b/clang/test/SemaCXX/void-lambda-return-init.cpp
new file mode 100644
index 0000000000000..d38ee1617691c
--- /dev/null
+++ b/clang/test/SemaCXX/void-lambda-return-init.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -std=c++20 -fblocks -fsyntax-only -verify %s
+
+void test_lambdas() {
+  (void) [] () -> void { return {}; }; // expected-error {{void lambda should 
not return a value}}
+  (void) [] () -> void { return {1}; }; // expected-error {{void lambda should 
not return a value}}
+  (void) [] () -> void { return {1, 2}; }; // expected-error {{void lambda 
should not return a value}}
+  (void) [] () -> void { return 42; }; // expected-error {{void lambda should 
not return a value}}
+  (void) [] () -> void { return double(32); }; // expected-error {{void lambda 
should not return a value}}
+  
+  // Qualtype  on void  Lambda return
+  (void) [] () -> const void { return {1}; }; // expected-error {{void lambda 
should not return a value}}
+  (void) [] () -> volatile void { // expected-warning {{volatile-qualified 
return type 'volatile void' is deprecated}}
+    return {1, 2}; // expected-error {{void lambda should not return a value}}
+  };
+}
+
+void test_blocks() {
+  (void) ^ void { return {}; }; // expected-error {{void block should not 
return a value}}
+  (void) ^ void { return {1}; }; // expected-error {{void block should not 
return a value}}
+  (void) ^ void { return {1, 2}; }; // expected-error {{void block should not 
return a value}}
+  (void) ^ void { return 42; }; // expected-error {{void block should not 
return a value}}
+  
+  // Qualtype on void Block return
+  (void) ^ const void { return {1}; }; // expected-error {{void block should 
not return a value}}
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/188904
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to