Răsfoiți Sursa

Retain an expression pack expansion when the parameter pack expansion code asks
us to.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@210355 91177308-0d34-0410-b5e6-96231b3b80d8

Richard Smith 11 ani în urmă
părinte
comite
150a4989ec
2 a modificat fișierele cu 34 adăugiri și 2 ștergeri
  1. 27 2
      lib/Sema/TreeTransform.h
  2. 7 0
      test/SemaTemplate/pack-deduction.cpp

+ 27 - 2
lib/Sema/TreeTransform.h

@@ -2912,9 +2912,11 @@ bool TreeTransform<Derived>::TransformExprs(Expr **Inputs,
         if (Out.isInvalid())
         if (Out.isInvalid())
           return true;
           return true;
 
 
+        // FIXME: Can this happen? We should not try to expand the pack
+        // in this case.
         if (Out.get()->containsUnexpandedParameterPack()) {
         if (Out.get()->containsUnexpandedParameterPack()) {
-          Out = RebuildPackExpansion(Out.get(), Expansion->getEllipsisLoc(),
-                                     OrigNumExpansions);
+          Out = getDerived().RebuildPackExpansion(
+              Out.get(), Expansion->getEllipsisLoc(), OrigNumExpansions);
           if (Out.isInvalid())
           if (Out.isInvalid())
             return true;
             return true;
         }
         }
@@ -2922,6 +2924,23 @@ bool TreeTransform<Derived>::TransformExprs(Expr **Inputs,
         Outputs.push_back(Out.get());
         Outputs.push_back(Out.get());
       }
       }
 
 
+      // If we're supposed to retain a pack expansion, do so by temporarily
+      // forgetting the partially-substituted parameter pack.
+      if (RetainExpansion) {
+        ForgetPartiallySubstitutedPackRAII Forget(getDerived());
+
+        ExprResult Out = getDerived().TransformExpr(Pattern);
+        if (Out.isInvalid())
+          return true;
+
+        Out = getDerived().RebuildPackExpansion(
+            Out.get(), Expansion->getEllipsisLoc(), OrigNumExpansions);
+        if (Out.isInvalid())
+          return true;
+
+        Outputs.push_back(Out.get());
+      }
+
       continue;
       continue;
     }
     }
 
 
@@ -8618,6 +8637,9 @@ TreeTransform<Derived>::TransformLambdaScope(LambdaExpr *E,
           // Capture the transformed variable.
           // Capture the transformed variable.
           getSema().tryCaptureVariable(CapturedVar, C->getLocation(), Kind);
           getSema().tryCaptureVariable(CapturedVar, C->getLocation(), Kind);
         }
         }
+
+        // FIXME: Retain a pack expansion if RetainExpansion is true.
+
         continue;
         continue;
       }
       }
 
 
@@ -9122,6 +9144,7 @@ TreeTransform<Derived>::TransformObjCDictionaryLiteral(
 
 
         // If any unexpanded parameter packs remain, we still have a
         // If any unexpanded parameter packs remain, we still have a
         // pack expansion.
         // pack expansion.
+        // FIXME: Can this really happen?
         if (Key.get()->containsUnexpandedParameterPack() ||
         if (Key.get()->containsUnexpandedParameterPack() ||
             Value.get()->containsUnexpandedParameterPack())
             Value.get()->containsUnexpandedParameterPack())
           Element.EllipsisLoc = OrigElement.EllipsisLoc;
           Element.EllipsisLoc = OrigElement.EllipsisLoc;
@@ -9129,6 +9152,8 @@ TreeTransform<Derived>::TransformObjCDictionaryLiteral(
         Elements.push_back(Element);
         Elements.push_back(Element);
       }
       }
 
 
+      // FIXME: Retain a pack expansion if RetainExpansion is true.
+
       // We've finished with this pack expansion.
       // We've finished with this pack expansion.
       continue;
       continue;
     }
     }

+ 7 - 0
test/SemaTemplate/pack-deduction.cpp

@@ -30,3 +30,10 @@ namespace PR14841 {
     f<char, short, int>(a); // expected-error {{no matching function}}
     f<char, short, int>(a); // expected-error {{no matching function}}
   }
   }
 }
 }
+
+namespace RetainExprPacks {
+  int f(int a, int b, int c);
+  template<typename ...Ts> struct X {};
+  template<typename ...Ts> int g(X<Ts...>, decltype(f(Ts()...)));
+  int n = g<int, int>(X<int, int, int>(), 0);
+}