Retain an expression pack expansion when the parameter pack expansion code asks
authorRichard Smith <richard-llvm@metafoo.co.uk>
Fri, 6 Jun 2014 17:33:35 +0000 (17:33 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Fri, 6 Jun 2014 17:33:35 +0000 (17:33 +0000)
us to.

llvm-svn: 210355

clang/lib/Sema/TreeTransform.h
clang/test/SemaTemplate/pack-deduction.cpp

index 94b2e95..eba23a5 100644 (file)
@@ -2912,9 +2912,11 @@ bool TreeTransform<Derived>::TransformExprs(Expr **Inputs,
         if (Out.isInvalid())
           return true;
 
+        // FIXME: Can this happen? We should not try to expand the pack
+        // in this case.
         if (Out.get()->containsUnexpandedParameterPack()) {
-          Out = RebuildPackExpansion(Out.get(), Expansion->getEllipsisLoc(),
-                                     OrigNumExpansions);
+          Out = getDerived().RebuildPackExpansion(
+              Out.get(), Expansion->getEllipsisLoc(), OrigNumExpansions);
           if (Out.isInvalid())
             return true;
         }
@@ -2922,6 +2924,23 @@ bool TreeTransform<Derived>::TransformExprs(Expr **Inputs,
         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;
     }
 
@@ -8618,6 +8637,9 @@ TreeTransform<Derived>::TransformLambdaScope(LambdaExpr *E,
           // Capture the transformed variable.
           getSema().tryCaptureVariable(CapturedVar, C->getLocation(), Kind);
         }
+
+        // FIXME: Retain a pack expansion if RetainExpansion is true.
+
         continue;
       }
 
@@ -9122,6 +9144,7 @@ TreeTransform<Derived>::TransformObjCDictionaryLiteral(
 
         // If any unexpanded parameter packs remain, we still have a
         // pack expansion.
+        // FIXME: Can this really happen?
         if (Key.get()->containsUnexpandedParameterPack() ||
             Value.get()->containsUnexpandedParameterPack())
           Element.EllipsisLoc = OrigElement.EllipsisLoc;
@@ -9129,6 +9152,8 @@ TreeTransform<Derived>::TransformObjCDictionaryLiteral(
         Elements.push_back(Element);
       }
 
+      // FIXME: Retain a pack expansion if RetainExpansion is true.
+
       // We've finished with this pack expansion.
       continue;
     }
index abb76de..f3f969e 100644 (file)
@@ -30,3 +30,10 @@ namespace PR14841 {
     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);
+}