@@ -959,10 +959,8 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D,
959959 return New;
960960}
961961
962- // CheckBindingsCount
963- // - Checks the arity of the structured bindings
964- // - Creates the resolved pack expr if there is
965- // one
962+ // Check the arity of the structured bindings.
963+ // Create the resolved pack expr if needed.
966964static bool CheckBindingsCount(Sema &S, DecompositionDecl *DD,
967965 QualType DecompType,
968966 ArrayRef<BindingDecl *> Bindings,
@@ -975,19 +973,31 @@ static bool CheckBindingsCount(Sema &S, DecompositionDecl *DD,
975973 if (!HasPack) {
976974 IsValid = Bindings.size() == MemberCount;
977975 } else {
978- // there may not be more members than non-pack bindings
976+ // There may not be more members than non-pack bindings.
979977 IsValid = MemberCount >= Bindings.size() - 1;
980978 }
981979
982980 if (IsValid && HasPack) {
983- // create the pack expr and assign it to the binding
981+ // Create the pack expr and assign it to the binding.
984982 unsigned PackSize = MemberCount - Bindings.size() + 1;
985983 QualType PackType = S.Context.getPackExpansionType(
986984 S.Context.DependentTy, std::nullopt, /*ExpectsPackInType=*/false);
987985 BindingDecl *BD = (*BindingWithPackItr);
988- BD->setBinding(PackType,
989- ResolvedUnexpandedPackExpr::Create(
990- S.Context, DD->getBeginLoc(), DecompType, PackSize));
986+ auto *RP = ResolvedUnexpandedPackExpr::Create(S.Context, DD->getBeginLoc(),
987+ DecompType, PackSize);
988+ BD->setDecomposedDecl(DD);
989+ BD->setBinding(PackType, RP);
990+
991+ BindingDecl *BPack = *BindingWithPackItr;
992+ // Create the nested BindingDecls.
993+ for (Expr *&E : RP->getExprs()) {
994+ auto *NestedBD = BindingDecl::Create(S.Context, BPack->getDeclContext(),
995+ BPack->getLocation(),
996+ BPack->getIdentifier(), QualType());
997+ NestedBD->setDecomposedDecl(DD);
998+ E = S.BuildDeclRefExpr(NestedBD, S.Context.DependentTy, VK_LValue,
999+ BPack->getLocation());
1000+ }
9911001 }
9921002
9931003 if (IsValid)
@@ -999,84 +1009,26 @@ static bool CheckBindingsCount(Sema &S, DecompositionDecl *DD,
9991009 return true;
10001010}
10011011
1002- // BindingInitWalker
1003- // - This implements a forward iterating flattened view
1004- // of structured bindings that may have a nested pack.
1005- // It allows the user to set the init expr for either the
1006- // BindingDecl or its ResolvedUnexpandedPackExpr
1007- struct BindingInitWalker {
1008- using BindingItrTy = typename ArrayRef<BindingDecl *>::iterator;
1009- using PackExprItrTy = typename MutableArrayRef<Expr *>::iterator;
1010- Sema &SemaRef;
1011- DecompositionDecl *DecompDecl;
1012- ArrayRef<BindingDecl *> Bindings;
1013- ResolvedUnexpandedPackExpr *PackExpr = nullptr;
1014- MutableArrayRef<Expr *> PackExprNodes;
1015- BindingItrTy BindingItr;
1016- PackExprItrTy PackExprItr;
1017-
1018- BindingInitWalker(Sema &S, DecompositionDecl *DD, ArrayRef<BindingDecl *> Bs)
1019- : SemaRef(S), DecompDecl(DD), Bindings(Bs), BindingItr(Bindings.begin()) {
1020- }
1021-
1022- BindingDecl *get() { return *BindingItr; }
1023-
1024- void commitAndAdvance(QualType T, Expr *E) {
1025- BindingDecl *B = *BindingItr;
1026- bool IsPackExpr =
1027- isa_and_nonnull<ResolvedUnexpandedPackExpr>(B->getBinding());
1028- if (IsPackExpr && !PackExpr) {
1029- PackExpr = cast<ResolvedUnexpandedPackExpr>(B->getBinding());
1030- PackExprNodes = PackExpr->getExprs();
1031- PackExprItr = PackExprNodes.begin();
1032- }
1033-
1034- if (IsPackExpr) {
1035- // Build a nested BindingDecl with a DeclRefExpr
1036- auto *NestedBD =
1037- BindingDecl::Create(SemaRef.Context, B->getDeclContext(),
1038- B->getLocation(), B->getIdentifier(), T);
1039-
1040- NestedBD->setBinding(T, E);
1041- NestedBD->setDecomposedDecl(DecompDecl);
1042- auto *DE = SemaRef.BuildDeclRefExpr(NestedBD, T.getNonReferenceType(),
1043- VK_LValue, B->getLocation());
1044- *PackExprItr = DE;
1045- if (++PackExprItr != PackExprNodes.end())
1046- return;
1047- // If we hit the end of the pack exprs then
1048- // continue to advance BindingItr
1049- } else {
1050- (*BindingItr)->setBinding(T, E);
1051- }
1052-
1053- ++BindingItr;
1054- }
1055- };
1056-
10571012static bool checkSimpleDecomposition(
10581013 Sema &S, ArrayRef<BindingDecl *> Bindings, ValueDecl *Src,
10591014 QualType DecompType, const llvm::APSInt &NumElemsAPS, QualType ElemType,
10601015 llvm::function_ref<ExprResult(SourceLocation, Expr *, unsigned)> GetInit) {
10611016 unsigned NumElems = (unsigned)NumElemsAPS.getLimitedValue(UINT_MAX);
1017+ auto *DD = cast<DecompositionDecl>(Src);
10621018
1063- if (CheckBindingsCount(S, cast<DecompositionDecl>(Src), DecompType, Bindings,
1064- NumElems)) {
1065-
1019+ if (CheckBindingsCount(S, DD, DecompType, Bindings, NumElems))
10661020 return true;
1067- }
10681021
1069- auto Walker = BindingInitWalker(S, cast<DecompositionDecl>(Src), Bindings);
1070- for (unsigned I = 0; I < NumElems; I++) {
1071- BindingDecl *B = Walker.get();
1022+ unsigned I = 0;
1023+ for (auto *B : DD->flat_bindings()) {
10721024 SourceLocation Loc = B->getLocation();
10731025 ExprResult E = S.BuildDeclRefExpr(Src, DecompType, VK_LValue, Loc);
10741026 if (E.isInvalid())
10751027 return true;
1076- E = GetInit(Loc, E.get(), I);
1028+ E = GetInit(Loc, E.get(), I++ );
10771029 if (E.isInvalid())
10781030 return true;
1079- Walker.commitAndAdvance (ElemType, E.get());
1031+ B->setBinding (ElemType, E.get());
10801032 }
10811033
10821034 return false;
@@ -1314,11 +1266,10 @@ static bool checkTupleLikeDecomposition(Sema &S,
13141266 ArrayRef<BindingDecl *> Bindings,
13151267 VarDecl *Src, QualType DecompType,
13161268 const llvm::APSInt &TupleSize) {
1269+ auto *DD = cast<DecompositionDecl>(Src);
13171270 unsigned NumElems = (unsigned)TupleSize.getLimitedValue(UINT_MAX);
1318- if (CheckBindingsCount(S, cast<DecompositionDecl>(Src), DecompType, Bindings,
1319- NumElems)) {
1271+ if (CheckBindingsCount(S, DD, DecompType, Bindings, NumElems))
13201272 return true;
1321- }
13221273
13231274 if (Bindings.empty())
13241275 return false;
@@ -1351,9 +1302,8 @@ static bool checkTupleLikeDecomposition(Sema &S,
13511302 }
13521303 }
13531304
1354- auto Walker = BindingInitWalker(S, cast<DecompositionDecl>(Src), Bindings);
1355- for (unsigned I = 0; I < NumElems; I++) {
1356- BindingDecl *B = Walker.get();
1305+ unsigned I = 0;
1306+ for (auto *B : DD->flat_bindings()) {
13571307 InitializingBinding InitContext(S, B);
13581308 SourceLocation Loc = B->getLocation();
13591309
@@ -1439,7 +1389,8 @@ static bool checkTupleLikeDecomposition(Sema &S,
14391389 if (E.isInvalid())
14401390 return true;
14411391
1442- Walker.commitAndAdvance(T, E.get());
1392+ B->setBinding(T, E.get());
1393+ I++;
14431394 }
14441395
14451396 return false;
@@ -1535,18 +1486,18 @@ static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings,
15351486 QualType BaseType = S.Context.getQualifiedType(S.Context.getRecordType(RD),
15361487 DecompType.getQualifiers());
15371488
1489+ auto *DD = cast<DecompositionDecl>(Src);
15381490 unsigned NumFields = llvm::count_if(
15391491 RD->fields(), [](FieldDecl *FD) { return !FD->isUnnamedBitField(); });
1540- if (CheckBindingsCount(S, cast<DecompositionDecl>(Src), DecompType, Bindings,
1541- NumFields)) {
1492+ if (CheckBindingsCount(S, DD, DecompType, Bindings, NumFields))
15421493 return true;
1543- }
1544-
1545- auto Walker = BindingInitWalker(S, cast<DecompositionDecl>(Src), Bindings);
15461494
15471495 // all of E's non-static data members shall be [...] well-formed
15481496 // when named as e.name in the context of the structured binding,
15491497 // E shall not have an anonymous union member, ...
1498+ auto FlatBindings = DD->flat_bindings();
1499+ assert(llvm::range_size(FlatBindings) == NumFields);
1500+ auto FlatBindingsItr = FlatBindings.begin();
15501501 for (auto *FD : RD->fields()) {
15511502 if (FD->isUnnamedBitField())
15521503 continue;
@@ -1571,7 +1522,8 @@ static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings,
15711522 }
15721523
15731524 // We have a real field to bind.
1574- BindingDecl *B = Walker.get();
1525+ assert(FlatBindingsItr != FlatBindings.end());
1526+ BindingDecl *B = *(FlatBindingsItr++);
15751527 SourceLocation Loc = B->getLocation();
15761528
15771529 // The field must be accessible in the context of the structured binding.
@@ -1606,8 +1558,7 @@ static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings,
16061558 Qualifiers Q = DecompType.getQualifiers();
16071559 if (FD->isMutable())
16081560 Q.removeConst();
1609- Walker.commitAndAdvance(S.BuildQualifiedType(FD->getType(), Loc, Q),
1610- E.get());
1561+ B->setBinding(S.BuildQualifiedType(FD->getType(), Loc, Q), E.get());
16111562 }
16121563
16131564 return false;
@@ -1625,6 +1576,19 @@ void Sema::CheckCompleteDecompositionDeclaration(DecompositionDecl *DD) {
16251576 B->setType(Context.DependentTy);
16261577 }
16271578 return;
1579+ } else {
1580+ // Set the types of the DeclRefExprs that point to nested pack bindings.
1581+ for (BindingDecl *B : DD->bindings()) {
1582+ if (B->isParameterPack()) {
1583+ for (Expr *E : B->getBindingPackExprs()) {
1584+ auto *DRE = cast<DeclRefExpr>(E);
1585+ auto *NestedB = cast<BindingDecl>(DRE->getDecl());
1586+ QualType T = NestedB->getType();
1587+ DRE->setTypeFromBinding(T, Context);
1588+ }
1589+ break;
1590+ }
1591+ }
16281592 }
16291593
16301594 DecompType = DecompType.getNonReferenceType();
0 commit comments