When performing template argument deduction for an initializer list,
be sure to perform the argument type adjustments in
[temp.deduct.call]p2, e.g., array decay.

And, when performing these deductions in the context of 'auto', make
sure that we're deducing the P' in std::initializer_list<P'> rather
than the whole initializer list.

Together, this makes code like

  for( auto s : {"Deferred", "New", "Open", "Review"}) { }

work properly.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153998 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index bc6138d..b448633 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -2935,8 +2935,12 @@
   }
 
   // For all other cases, just match by type.
+  QualType ArgType = Arg->getType();
+  if (AdjustFunctionParmAndArgTypesForDeduction(S, TemplateParams, ParamType, 
+                                                ArgType, Arg, TDF))
+    return Sema::TDK_FailedOverloadResolution;
   return DeduceTemplateArgumentsByTypeMatch(S, TemplateParams, ParamType,
-                                            Arg->getType(), Info, Deduced, TDF);
+                                            ArgType, Info, Deduced, TDF);
 }
 
 /// \brief Perform template argument deduction from a function call
@@ -3494,22 +3498,24 @@
   Deduced.resize(1);
   QualType InitType = Init->getType();
   unsigned TDF = 0;
-  if (AdjustFunctionParmAndArgTypesForDeduction(*this, &TemplateParams,
-                                                FuncParam, InitType, Init,
-                                                TDF))
-    return DAR_Failed;
 
   TemplateDeductionInfo Info(Context, Loc);
 
   InitListExpr * InitList = dyn_cast<InitListExpr>(Init);
   if (InitList) {
     for (unsigned i = 0, e = InitList->getNumInits(); i < e; ++i) {
-      if (DeduceTemplateArgumentsByTypeMatch(*this, &TemplateParams, FuncParam,
-                                             InitList->getInit(i)->getType(),
-                                             Info, Deduced, TDF))
+      if (DeduceTemplateArgumentByListElement(*this, &TemplateParams, 
+                                              TemplArg,
+                                              InitList->getInit(i),
+                                              Info, Deduced, TDF))
         return DAR_Failed;
     }
   } else {
+    if (AdjustFunctionParmAndArgTypesForDeduction(*this, &TemplateParams,
+                                                  FuncParam, InitType, Init,
+                                                  TDF))
+      return DAR_Failed;
+    
     if (DeduceTemplateArgumentsByTypeMatch(*this, &TemplateParams, FuncParam,
                                            InitType, Info, Deduced, TDF))
       return DAR_Failed;
diff --git a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
index 0e0e8f2..3437849 100644
--- a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
+++ b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
@@ -150,3 +150,19 @@
     g({il, {2, 3}});
   }
 }
+
+namespace Decay {
+  template<typename T>
+  void f(std::initializer_list<T>) {
+    T x = 1; // expected-error{{cannot initialize a variable of type 'const char *' with an rvalue of type 'int'}}
+  }
+
+  void g() {
+    f({"A", "BB", "CCC"}); // expected-note{{in instantiation of function template specialization 'Decay::f<const char *>' requested here}}
+
+    auto x = { "A", "BB", "CCC" };
+    std::initializer_list<const char *> *il = &x;
+
+    for( auto s : {"A", "BB", "CCC", "DDD"}) { }
+  }
+}