[cfe-commits] r122439 - in /cfe/trunk: include/clang/AST/DeclTemplate.h include/clang/AST/TemplateBase.h include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/Sema.h lib/AST/TemplateBase.cpp lib/Sema/SemaTemplateDeduction.cpp lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp lib/Sema/SemaTemplateVariadic.cpp test/CXX/temp/temp.decls/temp.variadic/count.cpp

Douglas Gregor dgregor at apple.com
Wed Dec 22 13:19:48 PST 2010


Author: dgregor
Date: Wed Dec 22 15:19:48 2010
New Revision: 122439

URL: http://llvm.org/viewvc/llvm-project?rev=122439&view=rev
Log:
Implement template argument deduction for pack expansions whose
pattern is a template argument, which involves repeatedly deducing
template arguments using the pattern of the pack expansion, then
bundling the resulting deductions into an argument pack.

We can now handle a variety of simple list-handling metaprograms using
variadic templates. See, e.g., the new "count" metaprogram.

Modified:
    cfe/trunk/include/clang/AST/DeclTemplate.h
    cfe/trunk/include/clang/AST/TemplateBase.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/TemplateBase.cpp
    cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
    cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/count.cpp

Modified: cfe/trunk/include/clang/AST/DeclTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=122439&r1=122438&r2=122439&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
+++ cfe/trunk/include/clang/AST/DeclTemplate.h Wed Dec 22 15:19:48 2010
@@ -417,11 +417,6 @@
     return reinterpret_cast<FunctionTemplateDecl*const*>(this+1);
   }
 
-  const TemplateArgumentLoc *getTemplateArgs() const {
-    return reinterpret_cast<const TemplateArgumentLoc*>(
-             &getTemplates()[getNumTemplates()]);
-  }
-
 public:
   DependentFunctionTemplateSpecializationInfo(
                                  const UnresolvedSetImpl &Templates,
@@ -439,6 +434,12 @@
     return getTemplates()[I];
   }
 
+  /// \brief Returns the explicit template arguments that were given.
+  const TemplateArgumentLoc *getTemplateArgs() const {
+    return reinterpret_cast<const TemplateArgumentLoc*>(
+                                                        &getTemplates()[getNumTemplates()]);
+  }
+
   /// \brief Returns the number of explicit template arguments that were given.
   unsigned getNumTemplateArgs() const {
     return d.NumArgs;

Modified: cfe/trunk/include/clang/AST/TemplateBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TemplateBase.h?rev=122439&r1=122438&r2=122439&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/TemplateBase.h (original)
+++ cfe/trunk/include/clang/AST/TemplateBase.h Wed Dec 22 15:19:48 2010
@@ -285,6 +285,12 @@
   /// same.
   bool structurallyEquals(const TemplateArgument &Other) const;
 
+  /// \brief When the template argument is a pack expansion, returns 
+  /// the pattern of the pack expansion.
+  ///
+  /// \param Ellipsis Will be set to the location of the ellipsis.
+  TemplateArgument getPackExpansionPattern() const;
+
   /// \brief Print this template argument to the given output stream.
   void print(const PrintingPolicy &Policy, llvm::raw_ostream &Out) const;
              

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=122439&r1=122438&r2=122439&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Dec 22 15:19:48 2010
@@ -1868,8 +1868,8 @@
   "clang cannot yet instantiate pack expansions">;
 def err_pack_expansion_mismatch_unsupported : Error<
   "clang cannot yet instantiate pack expansions with mismatched pack levels">;
-def err_pack_expansion_deduction : Error<
-  "clang cannot yet perform template argument deduction for a pack expansion">;
+def err_pack_expansion_deduction_compare : Error<
+  "clang cannot yet compare deduced template argument packs">;
 
 def err_unexpected_typedef : Error<
   "unexpected type name %0: expected expression">;

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=122439&r1=122438&r2=122439&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Dec 22 15:19:48 2010
@@ -3247,6 +3247,14 @@
   ///
   /// \param Arg The template argument that will be traversed to find
   /// unexpanded parameter packs.
+  void collectUnexpandedParameterPacks(TemplateArgument Arg,
+                   llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
+
+  /// \brief Collect the set of unexpanded parameter packs within the given
+  /// template argument.  
+  ///
+  /// \param Arg The template argument that will be traversed to find
+  /// unexpanded parameter packs.
   void collectUnexpandedParameterPacks(TemplateArgumentLoc Arg,
                     llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded);
 
@@ -3862,7 +3870,8 @@
   TemplateName
   SubstTemplateName(TemplateName Name, SourceLocation Loc,
                     const MultiLevelTemplateArgumentList &TemplateArgs);
-  bool Subst(const TemplateArgumentLoc &Arg, TemplateArgumentLoc &Result,
+  bool Subst(const TemplateArgumentLoc *Args, unsigned NumArgs,
+             TemplateArgumentListInfo &Result,
              const MultiLevelTemplateArgumentList &TemplateArgs);
 
   void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,

Modified: cfe/trunk/lib/AST/TemplateBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TemplateBase.cpp?rev=122439&r1=122438&r2=122439&view=diff
==============================================================================
--- cfe/trunk/lib/AST/TemplateBase.cpp (original)
+++ cfe/trunk/lib/AST/TemplateBase.cpp Wed Dec 22 15:19:48 2010
@@ -191,6 +191,28 @@
   return false;
 }
 
+TemplateArgument TemplateArgument::getPackExpansionPattern() const {
+  assert(isPackExpansion());
+  
+  switch (getKind()) {
+    case Type:
+      return getAsType()->getAs<PackExpansionType>()->getPattern();
+      
+    case Expression:
+    case Template:
+      // FIXME: Variadic templates.
+      llvm_unreachable("Expression and template pack expansions unsupported");
+      
+    case Declaration:
+    case Integral:
+    case Pack:
+    case Null:
+      return TemplateArgument();
+  }
+  
+  return TemplateArgument();
+}
+
 void TemplateArgument::print(const PrintingPolicy &Policy, 
                              llvm::raw_ostream &Out) const {
   switch (getKind()) {

Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=122439&r1=122438&r2=122439&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Wed Dec 22 15:19:48 2010
@@ -21,6 +21,7 @@
 #include "clang/AST/StmtVisitor.h"
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
+#include "llvm/ADT/BitVector.h"
 #include <algorithm>
 
 namespace clang {
@@ -947,6 +948,24 @@
   return ArgIdx < NumArgs;
 }
 
+/// \brief Retrieve the depth and index of an unexpanded parameter pack.
+static std::pair<unsigned, unsigned> 
+getDepthAndIndex(UnexpandedParameterPack UPP) {
+  if (const TemplateTypeParmType *TTP
+                          = UPP.first.dyn_cast<const TemplateTypeParmType *>())
+    return std::make_pair(TTP->getDepth(), TTP->getIndex());
+  
+  if (TemplateTypeParmDecl *TTP = UPP.first.dyn_cast<TemplateTypeParmDecl *>())
+    return std::make_pair(TTP->getDepth(), TTP->getIndex());
+  
+  if (NonTypeTemplateParmDecl *NTTP 
+                              = UPP.first.dyn_cast<NonTypeTemplateParmDecl *>())
+    return std::make_pair(NTTP->getDepth(), NTTP->getIndex());
+  
+  TemplateTemplateParmDecl *TTP = UPP.first.get<TemplateTemplateParmDecl *>();
+  return std::make_pair(TTP->getDepth(), TTP->getIndex());
+}
+
 static Sema::TemplateDeductionResult
 DeduceTemplateArguments(Sema &S,
                         TemplateParameterList *TemplateParams,
@@ -955,18 +974,32 @@
                         TemplateDeductionInfo &Info,
                     llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
                         bool NumberOfArgumentsMustMatch) {
+  // C++0x [temp.deduct.type]p9:
+  //   If the template argument list of P contains a pack expansion that is not 
+  //   the last template argument, the entire template argument list is a 
+  //   non-deduced context.
+  // FIXME: Implement this.
+
+
+  // C++0x [temp.deduct.type]p9:
+  //   If P has a form that contains <T> or <i>, then each argument Pi of the 
+  //   respective template argument list P is compared with the corresponding 
+  //   argument Ai of the corresponding template argument list of A.
   unsigned ArgIdx = 0, ParamIdx = 0;
   for (; hasTemplateArgumentForDeduction(Params, ParamIdx, NumParams); 
        ++ParamIdx) {
+    // FIXME: Variadic templates.
+    // What do we do if the argument is a pack expansion?
+    
     if (!Params[ParamIdx].isPackExpansion()) {
-      // The simple case: deduce template arguments by matching P and A.
+      // The simple case: deduce template arguments by matching Pi and Ai.
       
       // Check whether we have enough arguments.
       if (!hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs))
         return NumberOfArgumentsMustMatch? Sema::TDK_TooFewArguments 
                                          : Sema::TDK_Success;
       
-      // Perform deduction for this P/A pair.
+      // Perform deduction for this Pi/Ai pair.
       if (Sema::TemplateDeductionResult Result
           = DeduceTemplateArguments(S, TemplateParams,
                                     Params[ParamIdx], Args[ArgIdx],
@@ -978,12 +1011,107 @@
       continue;
     }
     
-    // FIXME: Variadic templates. 
-    // The parameter is a pack expansion, so we'll
-    // need to repeatedly unify arguments against the parameter, capturing
-    // the bindings for each expanded parameter pack.
-    S.Diag(Info.getLocation(), diag::err_pack_expansion_deduction);
-    return Sema::TDK_TooManyArguments;
+    // The parameter is a pack expansion.
+    
+    // C++0x [temp.deduct.type]p9:
+    //   If Pi is a pack expansion, then the pattern of Pi is compared with 
+    //   each remaining argument in the template argument list of A. Each 
+    //   comparison deduces template arguments for subsequent positions in the 
+    //   template parameter packs expanded by Pi.
+    TemplateArgument Pattern = Params[ParamIdx].getPackExpansionPattern();
+    
+    // Compute the set of template parameter indices that correspond to
+    // parameter packs expanded by the pack expansion.
+    llvm::SmallVector<unsigned, 2> PackIndices;
+    {
+      llvm::BitVector SawIndices(TemplateParams->size());
+      llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+      S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
+      for (unsigned I = 0, N = Unexpanded.size(); I != N; ++I) {
+        unsigned Depth, Index;
+        llvm::tie(Depth, Index) = getDepthAndIndex(Unexpanded[I]);
+        if (Depth == 0 && !SawIndices[Index]) {
+          SawIndices[Index] = true;
+          PackIndices.push_back(Index);
+        }
+      }
+    }
+    assert(!PackIndices.empty() && "Pack expansion without unexpanded packs?");
+        
+    // FIXME: If there are no remaining arguments, we can bail out early
+    // and set any deduced parameter packs to an empty argument pack.
+    // The latter part of this is a (minor) correctness issue.
+    
+    // Save the deduced template arguments for each parameter pack expanded
+    // by this pack expansion, then clear out the deduction.
+    llvm::SmallVector<DeducedTemplateArgument, 2> 
+      SavedPacks(PackIndices.size());
+    for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
+      SavedPacks[I] = Deduced[PackIndices[I]];
+      Deduced[PackIndices[I]] = DeducedTemplateArgument();
+    }
+
+    // Keep track of the deduced template arguments for each parameter pack
+    // expanded by this pack expansion (the outer index) and for each 
+    // template argument (the inner SmallVectors).
+    llvm::SmallVector<llvm::SmallVector<DeducedTemplateArgument, 4>, 2>
+      NewlyDeducedPacks(PackIndices.size());
+    bool HasAnyArguments = false;
+    while (hasTemplateArgumentForDeduction(Args, ArgIdx, NumArgs)) {
+      HasAnyArguments = true;
+      
+      // Deduce template arguments from the pattern.
+      if (Sema::TemplateDeductionResult Result 
+            = DeduceTemplateArguments(S, TemplateParams, Pattern, Args[ArgIdx],
+                                      Info, Deduced))
+        return Result;
+      
+      // Capture the deduced template arguments for each parameter pack expanded
+      // by this pack expansion, add them to the list of arguments we've deduced
+      // for that pack, then clear out the deduced argument.
+      for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
+        DeducedTemplateArgument &DeducedArg = Deduced[PackIndices[I]];
+        if (!DeducedArg.isNull()) {
+          NewlyDeducedPacks[I].push_back(DeducedArg);
+          DeducedArg = DeducedTemplateArgument();
+        }
+      }
+      
+      ++ArgIdx;
+    }
+    
+    // Build argument packs for each of the parameter packs expanded by this
+    // pack expansion.
+    for (unsigned I = 0, N = PackIndices.size(); I != N; ++I) {
+      if (HasAnyArguments && NewlyDeducedPacks[I].empty()) {
+        // We were not able to deduce anything for this parameter pack,
+        // so just restore the saved argument pack.
+        Deduced[PackIndices[I]] = SavedPacks[I];
+        continue;
+      }
+      
+      if (!SavedPacks[I].isNull()) {
+        // FIXME: Check against the existing argument pack.
+        S.Diag(Info.getLocation(), diag::err_pack_expansion_deduction_compare);
+        return Sema::TDK_TooFewArguments;
+      }
+      
+      if (NewlyDeducedPacks[I].empty()) {
+        // If we deduced an empty argument pack, create it now.
+        Deduced[PackIndices[I]]
+          = DeducedTemplateArgument(TemplateArgument(0, 0));
+        continue;
+      }
+                
+      TemplateArgument *ArgumentPack
+        = new (S.Context) TemplateArgument [NewlyDeducedPacks[I].size()];
+      std::copy(NewlyDeducedPacks[I].begin(), NewlyDeducedPacks[I].end(),
+                ArgumentPack);
+      Deduced[PackIndices[I]]
+        = DeducedTemplateArgument(TemplateArgument(ArgumentPack,
+                                                   NewlyDeducedPacks[I].size()),
+                            NewlyDeducedPacks[I][0].wasDeducedFromArrayBound());
+    }
   }
   
   // If there is an argument remaining, then we had too many arguments.
@@ -1087,12 +1215,16 @@
   // C++ [temp.deduct.type]p2:
   //   [...] or if any template argument remains neither deduced nor
   //   explicitly specified, template argument deduction fails.
+  // FIXME: Variadic templates Empty parameter packs?
   llvm::SmallVector<TemplateArgument, 4> Builder;
   for (unsigned I = 0, N = Deduced.size(); I != N; ++I) {
     if (Deduced[I].isNull()) {
+      unsigned ParamIdx = I;
+      if (ParamIdx >= Partial->getTemplateParameters()->size())
+        ParamIdx = Partial->getTemplateParameters()->size() - 1;
       Decl *Param
         = const_cast<NamedDecl *>(
-                                Partial->getTemplateParameters()->getParam(I));
+                          Partial->getTemplateParameters()->getParam(ParamIdx));
       Info.Param = makeTemplateParameter(Param);
       return Sema::TDK_Incomplete;
     }
@@ -1118,22 +1250,23 @@
   ClassTemplateDecl *ClassTemplate = Partial->getSpecializedTemplate();
   const TemplateArgumentLoc *PartialTemplateArgs
     = Partial->getTemplateArgsAsWritten();
-  unsigned N = Partial->getNumTemplateArgsAsWritten();
 
   // Note that we don't provide the langle and rangle locations.
   TemplateArgumentListInfo InstArgs;
 
-  for (unsigned I = 0; I != N; ++I) {
-    Decl *Param = const_cast<NamedDecl *>(
-                    ClassTemplate->getTemplateParameters()->getParam(I));
-    TemplateArgumentLoc InstArg;
-    if (S.Subst(PartialTemplateArgs[I], InstArg,
-                MultiLevelTemplateArgumentList(*DeducedArgumentList))) {
-      Info.Param = makeTemplateParameter(Param);
-      Info.FirstArg = PartialTemplateArgs[I].getArgument();
-      return Sema::TDK_SubstitutionFailure;
-    }
-    InstArgs.addArgument(InstArg);
+  if (S.Subst(PartialTemplateArgs,
+              Partial->getNumTemplateArgsAsWritten(),
+              InstArgs, MultiLevelTemplateArgumentList(*DeducedArgumentList))) {
+    unsigned ArgIdx = InstArgs.size(), ParamIdx = ArgIdx;
+    if (ParamIdx >= Partial->getTemplateParameters()->size())
+      ParamIdx = Partial->getTemplateParameters()->size() - 1;
+
+    Decl *Param
+      = const_cast<NamedDecl *>(
+                          Partial->getTemplateParameters()->getParam(ParamIdx));
+    Info.Param = makeTemplateParameter(Param);
+    Info.FirstArg = PartialTemplateArgs[ArgIdx].getArgument();
+    return Sema::TDK_SubstitutionFailure;
   }
 
   llvm::SmallVector<TemplateArgument, 4> ConvertedInstArgs;

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=122439&r1=122438&r2=122439&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Wed Dec 22 15:19:48 2010
@@ -1723,12 +1723,13 @@
   return Instantiator.TransformTemplateName(Name);
 }
 
-bool Sema::Subst(const TemplateArgumentLoc &Input, TemplateArgumentLoc &Output,
+bool Sema::Subst(const TemplateArgumentLoc *Args, unsigned NumArgs,
+                 TemplateArgumentListInfo &Result,
                  const MultiLevelTemplateArgumentList &TemplateArgs) {
   TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(),
                                     DeclarationName());
-
-  return Instantiator.TransformTemplateArgument(Input, Output);
+  
+  return Instantiator.TransformTemplateArguments(Args, NumArgs, Result);
 }
 
 Decl *LocalInstantiationScope::getInstantiationOf(const Decl *D) {

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=122439&r1=122438&r2=122439&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Wed Dec 22 15:19:48 2010
@@ -1095,13 +1095,9 @@
     // Instantiate the explicit template arguments.
     TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(),
                                           Info->getRAngleLoc());
-    for (unsigned I = 0, E = Info->getNumTemplateArgs(); I != E; ++I) {
-      TemplateArgumentLoc Loc;
-      if (SemaRef.Subst(Info->getTemplateArg(I), Loc, TemplateArgs))
-        return 0;
-
-      ExplicitArgs.addArgument(Loc);
-    }
+    if (SemaRef.Subst(Info->getTemplateArgs(), Info->getNumTemplateArgs(),
+                      ExplicitArgs, TemplateArgs))
+      return 0;
 
     // Map the candidate templates to their instantiations.
     for (unsigned I = 0, E = Info->getNumTemplates(); I != E; ++I) {
@@ -1791,19 +1787,12 @@
   
   // Substitute into the template arguments of the class template partial
   // specialization.
-  const TemplateArgumentLoc *PartialSpecTemplateArgs
-    = PartialSpec->getTemplateArgsAsWritten();
-  unsigned N = PartialSpec->getNumTemplateArgsAsWritten();
-
   TemplateArgumentListInfo InstTemplateArgs; // no angle locations
-  for (unsigned I = 0; I != N; ++I) {
-    TemplateArgumentLoc Loc;
-    if (SemaRef.Subst(PartialSpecTemplateArgs[I], Loc, TemplateArgs))
-      return 0;
-    InstTemplateArgs.addArgument(Loc);
-  }
+  if (SemaRef.Subst(PartialSpec->getTemplateArgsAsWritten(), 
+                    PartialSpec->getNumTemplateArgsAsWritten(), 
+                    InstTemplateArgs, TemplateArgs))
+    return 0;
   
-
   // Check that the template argument list is well-formed for this
   // class template.
   llvm::SmallVector<TemplateArgument, 4> Converted;

Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=122439&r1=122438&r2=122439&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Wed Dec 22 15:19:48 2010
@@ -253,6 +253,12 @@
   return true;
 }
 
+void Sema::collectUnexpandedParameterPacks(TemplateArgument Arg,
+                   llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
+  CollectUnexpandedParameterPacksVisitor(Unexpanded)
+    .TraverseTemplateArgument(Arg);
+}
+
 void Sema::collectUnexpandedParameterPacks(TemplateArgumentLoc Arg,
                    llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
   CollectUnexpandedParameterPacksVisitor(Unexpanded)

Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/count.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/count.cpp?rev=122439&r1=122438&r2=122439&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/count.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/count.cpp Wed Dec 22 15:19:48 2010
@@ -1,17 +1,36 @@
 // RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
 
-template<typename Head, typename ...Tail>
-struct count {
-  static const unsigned value = 1 + count<Tail...>::value;
-};
-
-template<typename T>
-struct count<T> {
-  static const unsigned value = 1;
-};
-
-int check1[count<int>::value == 1? 1 : -1];
-int check2[count<float, double>::value == 2? 1 : -1];
-int check3[count<char, signed char, unsigned char>::value == 3? 1 : -1];
+namespace Basic {
+  template<typename Head, typename ...Tail>
+  struct count {
+    static const unsigned value = 1 + count<Tail...>::value;
+  };
 
+  template<typename T>
+  struct count<T> {
+    static const unsigned value = 1;
+  };
 
+  int check1[count<int>::value == 1? 1 : -1];
+  int check2[count<float, double>::value == 2? 1 : -1];
+  int check3[count<char, signed char, unsigned char>::value == 3? 1 : -1];
+}
+
+namespace WithPackExpansion {
+  template<typename ...> struct count;
+
+  template<typename Head, typename ...Tail>
+  struct count<Head, Tail...> {
+    static const unsigned value = 1 + count<Tail...>::value;
+  };
+
+  template<>
+  struct count<> {
+    static const unsigned value = 0;
+  };
+
+  int check0[count<>::value == 0? 1 : -1];
+  int check1[count<int>::value == 1? 1 : -1];
+  int check2[count<float, double>::value == 2? 1 : -1];
+  int check3[count<char, signed char, unsigned char>::value == 3? 1 : -1];
+}





More information about the cfe-commits mailing list