llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: babadany2999

<details>
<summary>Changes</summary>

As proposed by other reviewers in #<!-- -->214160, I believe that we should 
restrict the code which delays diagnostics about unexpanded packs if it is 
within a lambda, if that unexpanded pack is a structured binding pack, and 
instead diagnose it directly.

Fixes #<!-- -->214160

My understanding of this area(and other areas) of Sema is fairly limited, so, 
if this breaks any contract and the proper fix is somewhere else or perhaps 
something else entirely, please do point me in the right direction.

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


3 Files Affected:

- (modified) clang/docs/ReleaseNotes.md (+3) 
- (modified) clang/lib/Sema/SemaTemplateVariadic.cpp (+14-1) 
- (added) clang/test/SemaCXX/GH214160.cpp (+31) 


``````````diff
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index a00b725143d49..42de9d57d5e80 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -366,6 +366,9 @@ features cannot lower the translation-unit ABI level;
 - Fixed USR generation for declarations whose signature mentions a class-type
   non-type template parameter. (#GH212351)
 - Clang now defines the GCC-compatible predefined macro `__SIG_ATOMIC_TYPE__`. 
(#GH213895)
+- Fixed an ICE where structured binding packs within a lambda were
+  considered for delayed diagnostics, when they should be diagnosed
+  immediately. (#GH214160)
 
 #### Bug Fixes to Compiler Builtins
 
diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp 
b/clang/lib/Sema/SemaTemplateVariadic.cpp
index c26a96eae9f66..3e228b7de4d72 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -428,6 +428,13 @@ bool Sema::isUnexpandedParameterPackPermitted() {
   return false;
 }
 
+static bool isStructuredBindingPack(const UnexpandedParameterPack &Pack) {
+  if (auto *ND = Pack.first.dyn_cast<NamedDecl *>()) {
+    return isa<BindingDecl>(ND);
+  }
+  return false;
+}
+
 /// Diagnose all of the unexpanded parameter packs in the given
 /// vector.
 bool
@@ -442,6 +449,7 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
   // parameter pack, and we are done. Analogously for blocks.
   // FIXME: Store 'Unexpanded' on the lambda so we don't need to recompute it
   // later.
+  bool HasNonDelayablePack = false;
   SmallVector<UnexpandedParameterPack, 4> ParamPackReferences;
   if (sema::CapturingScopeInfo *CSI = getEnclosingLambdaOrBlock()) {
     for (auto &Pack : Unexpanded) {
@@ -454,6 +462,11 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
       };
       if (llvm::any_of(CSI->LocalPacks, DeclaresThisPack))
         ParamPackReferences.push_back(Pack);
+
+      // Structured binding packs should not participate in delayed lambda
+      // diagnostics, and should instead be diagnosed immediately
+      if (isStructuredBindingPack(Pack))
+        HasNonDelayablePack = true;
     }
 
     if (ParamPackReferences.empty()) {
@@ -483,7 +496,7 @@ Sema::DiagnoseUnexpandedParameterPacks(SourceLocation Loc,
           break;
       }
 
-      if (!EnclosingStmtExpr) {
+      if (!EnclosingStmtExpr && !HasNonDelayablePack) {
         CSI->ContainsUnexpandedParameterPack = true;
         return false;
       }
diff --git a/clang/test/SemaCXX/GH214160.cpp b/clang/test/SemaCXX/GH214160.cpp
new file mode 100644
index 0000000000000..11d1c284409d7
--- /dev/null
+++ b/clang/test/SemaCXX/GH214160.cpp
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -std=c++2c -fsyntax-only -verify %s
+
+namespace GH214160 {
+// Test case: non-constexpr
+struct A {
+  int x, y;
+};
+
+template <typename = void>
+void f() {
+  ([&]{ auto [...tmp] = A{}; tmp; }() + ... + 0);
+  // expected-error@-1 {{expression contains unexpanded parameter pack 'tmp'}}
+  // expected-error@-2 {{pack expansion does not contain any unexpanded 
parameter packs}}
+}
+
+template void f<void>();
+
+// Test case: constexpr
+struct B {
+    int x, y;
+};
+
+template <typename = void>
+constexpr void g() {
+    ([&]{ auto [...tmp] = B{}; tmp; }() + ... + 0);
+    // expected-error@-1 {{expression contains unexpanded parameter pack 
'tmp'}}
+    // expected-error@-2 {{pack expansion does not contain any unexpanded 
parameter packs}}
+}
+
+template void g<void>();
+}

``````````

</details>


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

Reply via email to