[cfe-commits] r122851 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateDeduction.cpp lib/Sema/SemaTemplateInstantiate.cpp test/CXX/temp/temp.decls/temp.class.spec/p9.cpp test/CXX/temp/temp.decls/temp.variadic/deduction.cpp

Douglas Gregor dgregor at apple.com
Tue Jan 4 15:35:54 PST 2011


Author: dgregor
Date: Tue Jan  4 17:35:54 2011
New Revision: 122851

URL: http://llvm.org/viewvc/llvm-project?rev=122851&view=rev
Log:
Improve our handling of non-type template parameters in partial
specializations. We weren't dealing with any of the cases where the
type of the non-type template argument differs from the type of the
corresponding template parameter in the primary template. We would
think that the template parameter in the partial specialization was
not deducible (and warn about it, incorrectly), then fail to convert a
deduced parameter to the type of the template parameter in the partial
specialization (which may involve truncation, among other
things). Fixes PR8905.

Added:
    cfe/trunk/test/CXX/temp/temp.decls/temp.class.spec/p9.cpp
Modified:
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/deduction.cpp

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=122851&r1=122850&r2=122851&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Jan  4 17:35:54 2011
@@ -3011,7 +3011,7 @@
 
   bool CheckTemplateArgument(NamedDecl *Param,
                              const TemplateArgumentLoc &Arg,
-                             TemplateDecl *Template,
+                             NamedDecl *Template,
                              SourceLocation TemplateLoc,
                              SourceLocation RAngleLoc,
                            llvm::SmallVectorImpl<TemplateArgument> &Converted,
@@ -3557,9 +3557,10 @@
     /// \brief The point of instantiation within the source code.
     SourceLocation PointOfInstantiation;
 
-    /// \brief The template in which we are performing the instantiation,
-    /// for substitutions of prior template arguments.
-    TemplateDecl *Template;
+    /// \brief The template (or partial specialization) in which we are 
+    /// performing the instantiation, for substitutions of prior template 
+    /// arguments.
+    NamedDecl *Template;
 
     /// \brief The entity that is being instantiated.
     uintptr_t Entity;
@@ -3745,14 +3746,14 @@
     /// \brief Note that we are substituting prior template arguments into a
     /// non-type or template template parameter.
     InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                          TemplateDecl *Template,
+                          NamedDecl *Template,
                           NonTypeTemplateParmDecl *Param,
                           const TemplateArgument *TemplateArgs,
                           unsigned NumTemplateArgs,
                           SourceRange InstantiationRange);
 
     InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                          TemplateDecl *Template,
+                          NamedDecl *Template,
                           TemplateTemplateParmDecl *Param,
                           const TemplateArgument *TemplateArgs,
                           unsigned NumTemplateArgs,

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=122851&r1=122850&r2=122851&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Jan  4 17:35:54 2011
@@ -2160,7 +2160,7 @@
 /// template parameter.
 bool Sema::CheckTemplateArgument(NamedDecl *Param,
                                  const TemplateArgumentLoc &Arg,
-                                 TemplateDecl *Template,
+                                 NamedDecl *Template,
                                  SourceLocation TemplateLoc,
                                  SourceLocation RAngleLoc,
                             llvm::SmallVectorImpl<TemplateArgument> &Converted,
@@ -3940,6 +3940,10 @@
     // We can have a pack expansion of any of the bullets below.
     if (PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(ArgExpr))
       ArgExpr = Expansion->getPattern();
+
+    // Strip off any implicit casts we added as part of type checking.
+    while (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(ArgExpr))
+      ArgExpr = ICE->getSubExpr();
     
     // C++ [temp.class.spec]p8:
     //   A non-type argument is non-specialized if it is the name of a
@@ -3950,7 +3954,7 @@
     // specialized non-type arguments, so skip any non-specialized
     // arguments.
     if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ArgExpr))
-      if (llvm::isa<NonTypeTemplateParmDecl>(DRE->getDecl()))
+      if (isa<NonTypeTemplateParmDecl>(DRE->getDecl()))
         continue;
     
     // C++ [temp.class.spec]p9:

Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=122851&r1=122850&r2=122851&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Tue Jan  4 17:35:54 2011
@@ -1314,6 +1314,114 @@
   return false;
 }
 
+/// \brief Allocate a TemplateArgumentLoc where all locations have
+/// been initialized to the given location.
+///
+/// \param S The semantic analysis object.
+///
+/// \param The template argument we are producing template argument
+/// location information for.
+///
+/// \param NTTPType For a declaration template argument, the type of
+/// the non-type template parameter that corresponds to this template
+/// argument.
+///
+/// \param Loc The source location to use for the resulting template
+/// argument.
+static TemplateArgumentLoc 
+getTrivialTemplateArgumentLoc(Sema &S,
+                              const TemplateArgument &Arg, 
+                              QualType NTTPType,
+                              SourceLocation Loc) {
+  switch (Arg.getKind()) {
+  case TemplateArgument::Null:
+    llvm_unreachable("Can't get a NULL template argument here");
+    break;
+    
+  case TemplateArgument::Type:
+    return TemplateArgumentLoc(Arg, 
+                     S.Context.getTrivialTypeSourceInfo(Arg.getAsType(), Loc));
+    
+  case TemplateArgument::Declaration: {
+    Expr *E
+    = S.BuildExpressionFromDeclTemplateArgument(Arg, NTTPType, Loc)
+    .takeAs<Expr>();
+    return TemplateArgumentLoc(TemplateArgument(E), E);
+  }
+    
+  case TemplateArgument::Integral: {
+    Expr *E
+    = S.BuildExpressionFromIntegralTemplateArgument(Arg, Loc).takeAs<Expr>();
+    return TemplateArgumentLoc(TemplateArgument(E), E);
+  }
+    
+  case TemplateArgument::Template:
+    return TemplateArgumentLoc(Arg, SourceRange(), Loc);
+    
+  case TemplateArgument::Expression:
+    return TemplateArgumentLoc(Arg, Arg.getAsExpr());
+    
+  case TemplateArgument::Pack:
+    return TemplateArgumentLoc(Arg, TemplateArgumentLocInfo());
+  }
+  
+  return TemplateArgumentLoc();
+}
+
+
+/// \brief Convert the given deduced template argument and add it to the set of
+/// fully-converted template arguments.
+static bool ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param, 
+                                           DeducedTemplateArgument Arg,
+                                           NamedDecl *Template, 
+                                           QualType NTTPType, 
+                                           TemplateDeductionInfo &Info,
+                                           bool InFunctionTemplate,
+                             llvm::SmallVectorImpl<TemplateArgument> &Output) {
+  if (Arg.getKind() == TemplateArgument::Pack) {
+    // This is a template argument pack, so check each of its arguments against
+    // the template parameter.
+    llvm::SmallVector<TemplateArgument, 2> PackedArgsBuilder;
+    for (TemplateArgument::pack_iterator PA = Arg.pack_begin(), 
+         PAEnd = Arg.pack_end();
+         PA != PAEnd; ++PA) {
+      DeducedTemplateArgument InnerArg(*PA);
+      InnerArg.setDeducedFromArrayBound(Arg.wasDeducedFromArrayBound());
+      if (ConvertDeducedTemplateArgument(S, Param, InnerArg, Template, 
+                                         NTTPType, Info, 
+                                         InFunctionTemplate, PackedArgsBuilder))
+        return true;
+    }
+    
+    // Create the resulting argument pack.
+    TemplateArgument *PackedArgs = 0;
+    if (!PackedArgsBuilder.empty()) {
+      PackedArgs = new (S.Context) TemplateArgument[PackedArgsBuilder.size()];
+      std::copy(PackedArgsBuilder.begin(), PackedArgsBuilder.end(), PackedArgs);
+    }
+    Output.push_back(TemplateArgument(PackedArgs, PackedArgsBuilder.size()));
+    return false;
+  }
+  
+  // Convert the deduced template argument into a template
+  // argument that we can check, almost as if the user had written
+  // the template argument explicitly.
+  TemplateArgumentLoc ArgLoc = getTrivialTemplateArgumentLoc(S, Arg, NTTPType,
+                                                             Info.getLocation());
+  
+  // Check the template argument, converting it as necessary.
+  return S.CheckTemplateArgument(Param, ArgLoc,
+                                 Template,
+                                 Template->getLocation(),
+                                 Template->getSourceRange().getEnd(),
+                                 Output,
+                                 InFunctionTemplate
+                                  ? (Arg.wasDeducedFromArrayBound()
+                                       ? Sema::CTAK_DeducedFromArrayBound 
+                                       : Sema::CTAK_Deduced)
+                                 : Sema::CTAK_Specified);
+}
+
 /// Complete template argument deduction for a class template partial
 /// specialization.
 static Sema::TemplateDeductionResult
@@ -1333,12 +1441,32 @@
   llvm::SmallVector<TemplateArgument, 4> Builder;
   TemplateParameterList *PartialParams = Partial->getTemplateParameters();
   for (unsigned I = 0, N = PartialParams->size(); I != N; ++I) {
+    NamedDecl *Param = PartialParams->getParam(I);
     if (Deduced[I].isNull()) {
-      Info.Param = makeTemplateParameter(PartialParams->getParam(I));
+      Info.Param = makeTemplateParameter(Param);
       return Sema::TDK_Incomplete;
     }
     
-    Builder.push_back(Deduced[I]);
+    // We have deduced this argument, so it still needs to be
+    // checked and converted.
+    
+    // First, for a non-type template parameter type that is
+    // initialized by a declaration, we need the type of the
+    // corresponding non-type template parameter.
+    QualType NTTPType;
+    if (NonTypeTemplateParmDecl *NTTP 
+                                     = dyn_cast<NonTypeTemplateParmDecl>(Param))
+      NTTPType = NTTP->getType();
+    
+    if (ConvertDeducedTemplateArgument(S, Param, Deduced[I],
+                                       Partial, NTTPType, Info, false,
+                                       Builder)) {
+      Info.Param = makeTemplateParameter(Param);
+      // FIXME: These template arguments are temporary. Free them!
+      Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder.data(), 
+                                                  Builder.size()));  
+      return Sema::TDK_SubstitutionFailure;
+    }
   }
   
   // Form the template argument list from the deduced template arguments.
@@ -1380,23 +1508,39 @@
 
   llvm::SmallVector<TemplateArgument, 4> ConvertedInstArgs;
   if (S.CheckTemplateArgumentList(ClassTemplate, Partial->getLocation(),
-                                InstArgs, false, ConvertedInstArgs))
+                                  InstArgs, false, ConvertedInstArgs))
     return Sema::TDK_SubstitutionFailure;
   
-  for (unsigned I = 0, E = ConvertedInstArgs.size(); I != E; ++I) {
+  TemplateParameterList *TemplateParams
+    = ClassTemplate->getTemplateParameters();
+  for (unsigned I = 0, E = TemplateParams->size(); I != E; ++I) {
     TemplateArgument InstArg = ConvertedInstArgs.data()[I];
 
-    Decl *Param = const_cast<NamedDecl *>(
-                    ClassTemplate->getTemplateParameters()->getParam(I));
+    Decl *Param = TemplateParams->getParam(I);
 
-    if (InstArg.getKind() == TemplateArgument::Expression) {
+    if (NonTypeTemplateParmDecl *NTTP
+        = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
       // When the argument is an expression, check the expression result
       // against the actual template parameter to get down to the canonical
       // template argument.
-      // FIXME: Variadic templates.
-      Expr *InstExpr = InstArg.getAsExpr();
-      if (NonTypeTemplateParmDecl *NTTP
-            = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+      Expr *InstExpr = 0;
+      if (InstArg.getKind() == TemplateArgument::Expression)
+        InstExpr = InstArg.getAsExpr();
+      else if (InstArg.getKind() == TemplateArgument::Integral) {
+        ExprResult InstExprFromArg
+          = S.BuildExpressionFromIntegralTemplateArgument(InstArg, 
+                                                          Info.getLocation());
+        if (InstExprFromArg.isInvalid()) {
+          Info.Param = makeTemplateParameter(Param);
+          Info.FirstArg = InstArg;
+          return Sema::TDK_SubstitutionFailure;
+        }
+        
+        InstExpr = InstExprFromArg.get();
+      }
+      
+      if (InstExpr) {
+        // FIXME: Variadic templates.
         if (S.CheckTemplateArgument(NTTP, NTTP->getType(), InstExpr, InstArg)) {
           Info.Param = makeTemplateParameter(Param);
           Info.FirstArg = Partial->getTemplateArgs()[I];
@@ -1615,109 +1759,6 @@
   return TDK_Success;
 }
 
-/// \brief Allocate a TemplateArgumentLoc where all locations have
-/// been initialized to the given location.
-///
-/// \param S The semantic analysis object.
-///
-/// \param The template argument we are producing template argument
-/// location information for.
-///
-/// \param NTTPType For a declaration template argument, the type of
-/// the non-type template parameter that corresponds to this template
-/// argument.
-///
-/// \param Loc The source location to use for the resulting template
-/// argument.
-static TemplateArgumentLoc 
-getTrivialTemplateArgumentLoc(Sema &S,
-                              const TemplateArgument &Arg, 
-                              QualType NTTPType,
-                              SourceLocation Loc) {
-  switch (Arg.getKind()) {
-  case TemplateArgument::Null:
-    llvm_unreachable("Can't get a NULL template argument here");
-    break;
-
-  case TemplateArgument::Type:
-    return TemplateArgumentLoc(Arg, 
-                    S.Context.getTrivialTypeSourceInfo(Arg.getAsType(), Loc));
-
-  case TemplateArgument::Declaration: {
-    Expr *E
-      = S.BuildExpressionFromDeclTemplateArgument(Arg, NTTPType, Loc)
-                                                              .takeAs<Expr>();
-    return TemplateArgumentLoc(TemplateArgument(E), E);
-  }
-
-  case TemplateArgument::Integral: {
-    Expr *E
-      = S.BuildExpressionFromIntegralTemplateArgument(Arg, Loc).takeAs<Expr>();
-    return TemplateArgumentLoc(TemplateArgument(E), E);
-  }
-
-  case TemplateArgument::Template:
-    return TemplateArgumentLoc(Arg, SourceRange(), Loc);
-
-  case TemplateArgument::Expression:
-    return TemplateArgumentLoc(Arg, Arg.getAsExpr());
-
-  case TemplateArgument::Pack:
-    return TemplateArgumentLoc(Arg, TemplateArgumentLocInfo());
-  }
-
-  return TemplateArgumentLoc();
-}
-
-/// \brief Convert the given deduced template argument and add it to the set of
-/// fully-converted template arguments.
-static bool ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param, 
-                                           DeducedTemplateArgument Arg,
-                                         FunctionTemplateDecl *FunctionTemplate, 
-                                           QualType NTTPType, 
-                                           TemplateDeductionInfo &Info,
-                       llvm::SmallVectorImpl<TemplateArgument> &Output) {
-  if (Arg.getKind() == TemplateArgument::Pack) {
-    // This is a template argument pack, so check each of its arguments against
-    // the template parameter.
-    llvm::SmallVector<TemplateArgument, 2> PackedArgsBuilder;
-    for (TemplateArgument::pack_iterator PA = Arg.pack_begin(), 
-                                      PAEnd = Arg.pack_end();
-         PA != PAEnd; ++PA) {
-      DeducedTemplateArgument InnerArg(*PA);
-      InnerArg.setDeducedFromArrayBound(Arg.wasDeducedFromArrayBound());
-      if (ConvertDeducedTemplateArgument(S, Param, InnerArg, FunctionTemplate, 
-                                         NTTPType, Info, PackedArgsBuilder))
-        return true;
-    }
-    
-    // Create the resulting argument pack.
-    TemplateArgument *PackedArgs = 0;
-    if (!PackedArgsBuilder.empty()) {
-      PackedArgs = new (S.Context) TemplateArgument[PackedArgsBuilder.size()];
-      std::copy(PackedArgsBuilder.begin(), PackedArgsBuilder.end(), PackedArgs);
-    }
-    Output.push_back(TemplateArgument(PackedArgs, PackedArgsBuilder.size()));
-    return false;
-  }
-  
-  // Convert the deduced template argument into a template
-  // argument that we can check, almost as if the user had written
-  // the template argument explicitly.
-  TemplateArgumentLoc ArgLoc = getTrivialTemplateArgumentLoc(S, Arg, NTTPType,
-                                                           Info.getLocation());
-
-  // Check the template argument, converting it as necessary.
-  return S.CheckTemplateArgument(Param, ArgLoc,
-                                 FunctionTemplate,
-                                 FunctionTemplate->getLocation(),
-                                 FunctionTemplate->getSourceRange().getEnd(),
-                                 Output,
-                                 Arg.wasDeducedFromArrayBound()
-                                  ? Sema::CTAK_DeducedFromArrayBound 
-                                  : Sema::CTAK_Deduced);
-}
-
 /// \brief Finish template argument deduction for a function template,
 /// checking the deduced template arguments for completeness and forming
 /// the function template specialization.
@@ -1791,7 +1832,7 @@
 
       if (ConvertDeducedTemplateArgument(*this, Param, Deduced[I],
                                          FunctionTemplate, NTTPType, Info,
-                                         Builder)) {
+                                         true, Builder)) {
         Info.Param = makeTemplateParameter(Param);
         // FIXME: These template arguments are temporary. Free them!
         Info.reset(TemplateArgumentList::CreateCopy(Context, Builder.data(), 
@@ -2953,6 +2994,10 @@
   if (const PackExpansionExpr *Expansion = dyn_cast<PackExpansionExpr>(E))
     E = Expansion->getPattern();
       
+  // Skip through any implicit casts we added while type-checking.
+  while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
+    E = ICE->getSubExpr();
+  
   // FIXME: if !OnlyDeduced, we have to walk the whole subexpression to 
   // find other occurrences of template parameters.
   const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=122851&r1=122850&r2=122851&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Tue Jan  4 17:35:54 2011
@@ -263,7 +263,7 @@
 
 Sema::InstantiatingTemplate::
 InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                      TemplateDecl *Template,
+                      NamedDecl *Template,
                       NonTypeTemplateParmDecl *Param,
                       const TemplateArgument *TemplateArgs,
                       unsigned NumTemplateArgs,
@@ -286,7 +286,7 @@
 
 Sema::InstantiatingTemplate::
 InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
-                      TemplateDecl *Template,
+                      NamedDecl *Template,
                       TemplateTemplateParmDecl *Param,
                       const TemplateArgument *TemplateArgs,
                       unsigned NumTemplateArgs,
@@ -490,13 +490,19 @@
       std::string Name;
       if (!Parm->getName().empty())
         Name = std::string(" '") + Parm->getName().str() + "'";
-                                        
+                    
+      TemplateParameterList *TemplateParams = 0;
+      if (TemplateDecl *Template = dyn_cast<TemplateDecl>(Active->Template))
+        TemplateParams = Template->getTemplateParameters();
+      else
+        TemplateParams =
+          cast<ClassTemplatePartialSpecializationDecl>(Active->Template)
+                                                      ->getTemplateParameters();
       Diags.Report(Active->PointOfInstantiation,
                    diag::note_prior_template_arg_substitution)
         << isa<TemplateTemplateParmDecl>(Parm)
         << Name
-        << getTemplateArgumentBindingsText(
-                                    Active->Template->getTemplateParameters(), 
+        << getTemplateArgumentBindingsText(TemplateParams, 
                                            Active->TemplateArgs, 
                                            Active->NumTemplateArgs)
         << Active->InstantiationRange;
@@ -504,10 +510,17 @@
     }
 
     case ActiveTemplateInstantiation::DefaultTemplateArgumentChecking: {
+      TemplateParameterList *TemplateParams = 0;
+      if (TemplateDecl *Template = dyn_cast<TemplateDecl>(Active->Template))
+        TemplateParams = Template->getTemplateParameters();
+      else
+        TemplateParams =
+          cast<ClassTemplatePartialSpecializationDecl>(Active->Template)
+                                                      ->getTemplateParameters();
+
       Diags.Report(Active->PointOfInstantiation,
                    diag::note_template_default_arg_checking)
-        << getTemplateArgumentBindingsText(
-                                     Active->Template->getTemplateParameters(), 
+        << getTemplateArgumentBindingsText(TemplateParams, 
                                            Active->TemplateArgs, 
                                            Active->NumTemplateArgs)
         << Active->InstantiationRange;

Added: cfe/trunk/test/CXX/temp/temp.decls/temp.class.spec/p9.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.class.spec/p9.cpp?rev=122851&view=auto
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.class.spec/p9.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.class.spec/p9.cpp Tue Jan  4 17:35:54 2011
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// PR8905
+template<char C1, char C2>
+struct X {
+  static const bool value = 0;
+};
+
+template<int C1>
+struct X<C1, C1> {
+  static const bool value = 1;
+};
+
+int check0[X<1, 2>::value == 0? 1 : -1];
+int check1[X<1, 1>::value == 1? 1 : -1];
+
+template<int, int, int> struct int_values {
+  static const unsigned value = 0;
+};
+
+template<unsigned char C1, unsigned char C3>
+struct int_values<C1, 12, C3> {
+  static const unsigned value = 1;
+};
+
+int check2[int_values<256, 12, 3>::value == 0? 1 : -1];  

Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/deduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/deduction.cpp?rev=122851&r1=122850&r2=122851&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/deduction.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/deduction.cpp Tue Jan  4 17:35:54 2011
@@ -23,3 +23,28 @@
   // FIXME: Extension of explicitly-specified arguments
   //  template void f0<short, int>(X<3, short&, int&, long&>);
 }
+
+namespace DeductionWithConversion {
+  template<char...> struct char_values {
+    static const unsigned value = 0;
+  };
+
+  template<int C1, char C3>
+  struct char_values<C1, 12, C3> {
+    static const unsigned value = 1;
+  };
+
+  int check0[char_values<1, 12, 3>::value == 1? 1 : -1];
+
+  template<int...> struct int_values {
+    static const unsigned value = 0;
+  };
+
+  template<unsigned char C1, unsigned char C3>
+  struct int_values<C1, 12, C3> {
+    static const unsigned value = 1;
+  };
+
+  int check1[int_values<256, 12, 3>::value == 0? 1 : -1];  
+  int check2[int_values<3, 12, 3>::value == 1? 1 : -1];  
+}





More information about the cfe-commits mailing list