A useful approximation of initializer list constructors.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149792 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h
index 8b4573b..36ffde9 100644
--- a/include/clang/Sema/Initialization.h
+++ b/include/clang/Sema/Initialization.h
@@ -838,11 +838,15 @@
   void AddListInitializationStep(QualType T);
 
   /// \brief Add a constructor-initialization step.
+  ///
+  /// \arg FromInitList The constructor call is syntactically an initializer
+  /// list.
+  /// \arg AsInitList The constructor is called as an init list constructor.
   void AddConstructorInitializationStep(CXXConstructorDecl *Constructor,
                                         AccessSpecifier Access,
                                         QualType T,
                                         bool HadMultipleCandidates,
-                                        bool FromInitList);
+                                        bool FromInitList, bool AsInitList);
 
   /// \brief Add a zero-initialization step.
   void AddZeroInitializationStep(QualType T);
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 6a7af45..7673f1d 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -5824,9 +5824,6 @@
     if (!Specialization)
       return false;
 
-    if (Specialization->getSpecializationKind() != TSK_ImplicitInstantiation)
-      return false;
-
     Template = Specialization->getSpecializedTemplate();
     Arguments = Specialization->getTemplateArgs().data();
   } else if (const TemplateSpecializationType *TST =
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 5caced9..406f524 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -2566,9 +2566,10 @@
                                    AccessSpecifier Access,
                                    QualType T,
                                    bool HadMultipleCandidates,
-                                   bool FromInitList) {
+                                   bool FromInitList, bool AsInitList) {
   Step S;
-  S.Kind = FromInitList ? SK_ListConstructorCall : SK_ConstructorInitialization;
+  S.Kind = FromInitList && !AsInitList ? SK_ListConstructorCall
+                                       : SK_ConstructorInitialization;
   S.Type = T;
   S.Function.HadMultipleCandidates = HadMultipleCandidates;
   S.Function.Function = Constructor;
@@ -2727,7 +2728,8 @@
                                                 DefaultConstructor->getAccess(),
                                                   DestType,
                                                   /*MultipleCandidates=*/false,
-                                                  /*FromInitList=*/true);
+                                                  /*FromInitList=*/true,
+                                                  /*AsInitList=*/false);
       return true;
     }
   }
@@ -2795,7 +2797,7 @@
 
     if (!Constructor->isInvalidDecl() &&
         (AllowExplicit || !Constructor->isExplicit()) &&
-        (!OnlyListConstructors || !S.isInitListConstructor(Constructor))) {
+        (!OnlyListConstructors || S.isInitListConstructor(Constructor))) {
       if (ConstructorTmpl)
         S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
                                        /*ExplicitArgs*/ 0,
@@ -2860,13 +2862,7 @@
   bool AllowExplicit = (Kind.getKind() == InitializationKind::IK_Direct ||
                         Kind.getKind() == InitializationKind::IK_Value ||
                         Kind.getKind() == InitializationKind::IK_Default);
-
-  if (InitListSyntax) {
-    // Time to unwrap the init list.
-    InitListExpr *ILE = cast<InitListExpr>(Args[0]);
-    Args = ILE->getInits();
-    NumArgs = ILE->getNumInits();
-  }
+  bool CopyInitialization = Kind.getKind() == InitializationKind::IK_Copy;
 
   //   - Otherwise, if T is a class type, constructors are considered. The
   //     applicable constructors are enumerated, and the best one is chosen
@@ -2874,13 +2870,42 @@
   DeclContext::lookup_iterator ConStart, ConEnd;
   llvm::tie(ConStart, ConEnd) = S.LookupConstructors(DestRecordDecl);
 
+  OverloadingResult Result = OR_No_Viable_Function;
   OverloadCandidateSet::iterator Best;
-  if (OverloadingResult Result =
-      ResolveConstructorOverload(S, Kind.getLocation(), Args, NumArgs,
-                                 CandidateSet, ConStart, ConEnd, Best,
-                                 Kind.getKind() == InitializationKind::IK_Copy,
-                                 AllowExplicit,
-                                 /*OnlyListConstructors=*/false)) {
+  bool AsInitializerList = false;
+
+  // C++11 [over.match.list]p1:
+  //   When objects of non-aggregate type T are list-initialized, overload
+  //   resolution selects the constructor in two phases:
+  //   - Initially, the candidate functions are the initializer-list
+  //     constructors of the class T and the argument list consists of the
+  //     initializer list as a single argument.
+  if (InitListSyntax) {
+    AsInitializerList = true;
+    Result = ResolveConstructorOverload(S, Kind.getLocation(), Args, NumArgs,
+                                        CandidateSet, ConStart, ConEnd, Best,
+                                        CopyInitialization, AllowExplicit,
+                                        /*OnlyListConstructor=*/true);
+
+    // Time to unwrap the init list.
+    InitListExpr *ILE = cast<InitListExpr>(Args[0]);
+    Args = ILE->getInits();
+    NumArgs = ILE->getNumInits();
+  }
+
+  // C++11 [over.match.list]p1:
+  //   - If no viable initializer-list constructor is found, overload resolution
+  //     is performed again, where the candidate functions are all the
+  //     constructors of the class T nad the argument list consists of the
+  //     elements of the initializer list.
+  if (Result == OR_No_Viable_Function) {
+    AsInitializerList = false;
+    Result = ResolveConstructorOverload(S, Kind.getLocation(), Args, NumArgs,
+                                        CandidateSet, ConStart, ConEnd, Best,
+                                        CopyInitialization, AllowExplicit,
+                                        /*OnlyListConstructors=*/false);
+  }
+  if (Result) {
     Sequence.SetOverloadFailure(InitListSyntax ?
                       InitializationSequence::FK_ListConstructorOverloadFailed :
                       InitializationSequence::FK_ConstructorOverloadFailed,
@@ -2906,7 +2931,7 @@
   Sequence.AddConstructorInitializationStep(CtorDecl,
                                             Best->FoundDecl.getAccess(),
                                             DestType, HadMultipleCandidates,
-                                            InitListSyntax);
+                                            InitListSyntax, AsInitializerList);
 }
 
 static bool