================
@@ -951,28 +959,130 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator 
&D,
   return New;
 }
 
+namespace {
+// CheckBindingsCount
+//  - Checks the arity of the structured bindings
+//  - Creates the resolved pack expr if there is
+//    one
+bool CheckBindingsCount(Sema &S, DecompositionDecl *DD, QualType DecompType,
+                        ArrayRef<BindingDecl *> Bindings,
+                        unsigned MemberCount) {
+  auto BindingWithPackItr =
+      std::find_if(Bindings.begin(), Bindings.end(),
+                   [](BindingDecl *D) -> bool { return D->isParameterPack(); 
});
+  bool HasPack = BindingWithPackItr != Bindings.end();
+  bool IsValid;
+  if (!HasPack) {
+    IsValid = Bindings.size() == MemberCount;
+  } else {
+    // there may not be more members than non-pack bindings
+    IsValid = MemberCount >= Bindings.size() - 1;
+  }
+
+  if (IsValid && HasPack) {
+    TemplateTypeParmDecl *DummyTemplateParam = TemplateTypeParmDecl::Create(
+        S.Context, S.Context.getTranslationUnitDecl(),
+        /*KeyLoc*/ SourceLocation(), /*NameLoc*/ SourceLocation(),
+        /*TemplateDepth*/ 0, /*AutoParameterPosition*/ 0,
+        /*Identifier*/ nullptr, false, /*IsParameterPack*/ true);
+
+    // create the pack expr and assign it to the binding
+    unsigned PackSize = MemberCount - Bindings.size() + 1;
+    QualType PackType = S.Context.getPackExpansionType(
+        QualType(DummyTemplateParam->getTypeForDecl(), 0), PackSize);
+    (*BindingWithPackItr)
+        ->setBinding(PackType,
+                     ResolvedUnexpandedPackExpr::Create(
+                         S.Context, DD->getBeginLoc(), DecompType, PackSize));
+  }
+
+  if (IsValid)
+    return false;
+
+  S.Diag(DD->getLocation(), diag::err_decomp_decl_wrong_number_bindings)
+      << DecompType << (unsigned)Bindings.size() << MemberCount << MemberCount
+      << (MemberCount < Bindings.size());
+  return true;
+}
+
+// BindingInitWalker
+//  - This implements a forward iterating flattened view
+//    of structured bindings that may have a nested pack.
+//    It allows the user to set the init expr for either the
+//    BindingDecl or its ResolvedUnexpandedPackExpr
----------------
ricejasonf wrote:

By contiguous, I mean that we would not nest the BindingDecls. The trade off is 
the extra references needed would bloat the size of DecompositionDecl. Perhaps 
that is a concern if there are a ton of them in a program which is why I 
abandoned the idea. The problem here is that the bindings are created before 
the init expression so we do not know how many bindings there will be up front 
in the case of packs. Hence the weird BindingInitWalker stuff as well as the 
DecompositionDecl::Visit* functions that I added. If you want me to remove 
those, it will require deferring the allocation of the BindingDecls.

https://github.com/llvm/llvm-project/pull/121417
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to