Fix parsing new expressions using init lists. Probably still do the wrong thing in cases involving array new.
Show that many cases using initializer list constructors work, in that they parse and pass semantic analysis.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150316 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 3974909..7dee5ec 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -2182,8 +2182,10 @@
   } else if (Tok.is(tok::l_brace) && getLang().CPlusPlus0x) {
     Diag(Tok.getLocation(),
          diag::warn_cxx98_compat_generalized_initializer_lists);
-    // FIXME: Have to communicate the init-list to ActOnCXXNew.
-    ParseBraceInitializer();
+    ExprResult InitList = ParseBraceInitializer();
+    if (InitList.isInvalid())
+      return InitList;
+    ConstructorArgs.push_back(InitList.take());
   }
 
   return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen,
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 3493b2a..b20dc95 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -2750,6 +2750,76 @@
   return UnwrappedAnyPointer && Context.hasSameUnqualifiedType(FromType,ToType);
 }
 
+static OverloadingResult
+IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType,
+                                       CXXRecordDecl *To,
+                                       UserDefinedConversionSequence &User,
+                                       OverloadCandidateSet &CandidateSet,
+                                       bool AllowExplicit) {
+  DeclContext::lookup_iterator Con, ConEnd;
+  for (llvm::tie(Con, ConEnd) = S.LookupConstructors(To);
+       Con != ConEnd; ++Con) {
+    NamedDecl *D = *Con;
+    DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
+
+    // Find the constructor (which may be a template).
+    CXXConstructorDecl *Constructor = 0;
+    FunctionTemplateDecl *ConstructorTmpl
+      = dyn_cast<FunctionTemplateDecl>(D);
+    if (ConstructorTmpl)
+      Constructor
+        = cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl());
+    else
+      Constructor = cast<CXXConstructorDecl>(D);
+
+    bool Usable = !Constructor->isInvalidDecl() &&
+                  S.isInitListConstructor(Constructor) &&
+                  (AllowExplicit || !Constructor->isExplicit());
+    if (Usable) {
+      if (ConstructorTmpl)
+        S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
+                                       /*ExplicitArgs*/ 0,
+                                       &From, 1, CandidateSet,
+                                       /*SuppressUserConversions=*/true);
+      else
+        S.AddOverloadCandidate(Constructor, FoundDecl,
+                               &From, 1, CandidateSet,
+                               /*SuppressUserConversions=*/true);
+    }
+  }
+
+  bool HadMultipleCandidates = (CandidateSet.size() > 1);
+
+  OverloadCandidateSet::iterator Best;
+  switch (CandidateSet.BestViableFunction(S, From->getLocStart(), Best, true)) {
+  case OR_Success: {
+    // Record the standard conversion we used and the conversion function.
+    CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function);
+    S.MarkFunctionReferenced(From->getLocStart(), Constructor);
+
+    QualType ThisType = Constructor->getThisType(S.Context);
+    // Initializer lists don't have conversions as such.
+    User.Before.setAsIdentityConversion();
+    User.HadMultipleCandidates = HadMultipleCandidates;
+    User.ConversionFunction = Constructor;
+    User.FoundConversionFunction = Best->FoundDecl;
+    User.After.setAsIdentityConversion();
+    User.After.setFromType(ThisType->getAs<PointerType>()->getPointeeType());
+    User.After.setAllToTypes(ToType);
+    return OR_Success;
+  }
+
+  case OR_No_Viable_Function:
+    return OR_No_Viable_Function;
+  case OR_Deleted:
+    return OR_Deleted;
+  case OR_Ambiguous:
+    return OR_Ambiguous;
+  }
+
+  llvm_unreachable("Invalid OverloadResult!");
+}
+
 /// Determines whether there is a user-defined conversion sequence
 /// (C++ [over.ics.user]) that converts expression From to the type
 /// ToType. If such a conversion exists, User will contain the
@@ -2762,8 +2832,8 @@
 /// functions (C++0x [class.conv.fct]p2).
 static OverloadingResult
 IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
-                        UserDefinedConversionSequence& User,
-                        OverloadCandidateSet& CandidateSet,
+                        UserDefinedConversionSequence &User,
+                        OverloadCandidateSet &CandidateSet,
                         bool AllowExplicit) {
   // Whether we will only visit constructors.
   bool ConstructorsOnly = false;
@@ -2796,9 +2866,17 @@
       Expr **Args = &From;
       unsigned NumArgs = 1;
       bool ListInitializing = false;
-      // If we're list-initializing, we pass the individual elements as
-      // arguments, not the entire list.
       if (InitListExpr *InitList = dyn_cast<InitListExpr>(From)) {
+        // But first, see if there is an init-list-contructor that will work.
+        OverloadingResult Result = IsInitializerListConstructorConversion(
+            S, From, ToType, ToRecordDecl, User, CandidateSet, AllowExplicit);
+        if (Result != OR_No_Viable_Function)
+          return Result;
+        // Never mind.
+        CandidateSet.clear();
+
+        // If we're list-initializing, we pass the individual elements as
+        // arguments, not the entire list.
         Args = InitList->getInits();
         NumArgs = InitList->getNumInits();
         ListInitializing = true;
diff --git a/test/SemaCXX/cxx0x-initializer-constructor.cpp b/test/SemaCXX/cxx0x-initializer-constructor.cpp
index c083366..4858d7a 100644
--- a/test/SemaCXX/cxx0x-initializer-constructor.cpp
+++ b/test/SemaCXX/cxx0x-initializer-constructor.cpp
@@ -3,6 +3,38 @@
 struct one { char c[1]; };
 struct two { char c[2]; };
 
+namespace std {
+  typedef decltype(sizeof(int)) size_t;
+
+  // libc++'s implementation
+  template <class _E>
+  class initializer_list
+  {
+    const _E* __begin_;
+    size_t    __size_;
+
+    initializer_list(const _E* __b, size_t __s)
+      : __begin_(__b),
+        __size_(__s)
+    {}
+
+  public:
+    typedef _E        value_type;
+    typedef const _E& reference;
+    typedef const _E& const_reference;
+    typedef size_t    size_type;
+
+    typedef const _E* iterator;
+    typedef const _E* const_iterator;
+
+    initializer_list() : __begin_(nullptr), __size_(0) {}
+
+    size_t    size()  const {return __size_;}
+    const _E* begin() const {return __begin_;}
+    const _E* end()   const {return __begin_ + __size_;}
+  };
+}
+
 namespace objects {
 
   struct X1 { X1(int); };
@@ -15,6 +47,19 @@
   };
 
   template <int N>
+  struct F {
+    F() { static_assert(N == 0, ""); }
+    F(int, double) { static_assert(N == 1, ""); }
+    F(std::initializer_list<int>) { static_assert(N == 3, ""); }
+  };
+
+  template <int N>
+  struct D {
+    D(std::initializer_list<int>) { static_assert(N == 0, ""); } // expected-note 1 {{candidate}}
+    D(std::initializer_list<double>) { static_assert(N == 1, ""); } // expected-note 1 {{candidate}}
+  };
+
+  template <int N>
   struct E {
     E(int, int) { static_assert(N == 0, ""); }
     E(X1, int) { static_assert(N == 1, ""); }
@@ -26,6 +71,22 @@
     { A<1> a{1, 1.0}; }
     { A<1> a = {1, 1.0}; }
 
+    { F<0> f{}; }
+    { F<0> f = {}; }
+    // Narrowing conversions don't affect viability. The next two choose
+    // the initializer_list constructor.
+    // FIXME: Emit narrowing conversion errors.
+    { F<3> f{1, 1.0}; } // xpected-error {{narrowing conversion}}
+    { F<3> f = {1, 1.0}; } // xpected-error {{narrowing conversion}}
+    { F<3> f{1, 2, 3, 4, 5, 6, 7, 8}; }
+    { F<3> f = {1, 2, 3, 4, 5, 6, 7, 8}; }
+    { F<3> f{1, 2, 3, 4, 5, 6, 7, 8}; }
+    { F<3> f{1, 2}; }
+
+    { D<0> d{1, 2, 3}; }
+    { D<1> d{1.0, 2.0, 3.0}; }
+    { D<-1> d{1, 2.0}; } // expected-error {{ambiguous}}
+
     { E<0> e{1, 2}; }
   }
 
@@ -57,6 +118,8 @@
   void inline_init() {
     (void) C{1, 1.0};
     (void) new C{1, 1.0};
+    (void) A<1>{1, 1.0};
+    (void) new A<1>{1, 1.0};
   }
 
   struct B { // expected-note 2 {{candidate constructor}}
@@ -77,5 +140,10 @@
     static_assert(sizeof(ov1({{1, 1.0}, 2, {3, 4}})) == sizeof(one), "bad overload");
 
     ov1({1}); // expected-error {{no matching function}}
+
+    one ov2(int);
+    two ov2(F<3>);
+    static_assert(sizeof(ov2({1})) == sizeof(one), "bad overload"); // list -> int ranks as identity
+    static_assert(sizeof(ov2({1, 2, 3})) == sizeof(two), "bad overload"); // list -> F only viable
   }
 }
diff --git a/test/SemaCXX/cxx98-compat.cpp b/test/SemaCXX/cxx98-compat.cpp
index 56e64d2..13456e0 100644
--- a/test/SemaCXX/cxx98-compat.cpp
+++ b/test/SemaCXX/cxx98-compat.cpp
@@ -39,7 +39,8 @@
 }
 
 int InitList() {
-  (void)new int {}; // expected-warning {{generalized initializer lists are incompatible with C++98}}
+  (void)new int {}; // expected-warning {{generalized initializer lists are incompatible with C++98}} \
+                    // expected-warning {{scalar initialized from empty initializer list is incompatible with C++98}}
   (void)int{}; // expected-warning {{generalized initializer lists are incompatible with C++98}}
   int x { 0 }; // expected-warning {{generalized initializer lists are incompatible with C++98}}
   return { 0 }; // expected-warning {{generalized initializer lists are incompatible with C++98}}
diff --git a/test/SemaCXX/generalized-initializers.cpp b/test/SemaCXX/generalized-initializers.cpp
index d696650..e62ff36 100644
--- a/test/SemaCXX/generalized-initializers.cpp
+++ b/test/SemaCXX/generalized-initializers.cpp
@@ -38,89 +38,6 @@
   };
 }
 
-namespace objects {
-
-  struct X1 { X1(int); };
-  struct X2 { explicit X2(int); };
-
-  template <int N>
-  struct A {
-    A() { static_assert(N == 0, ""); }
-    A(int, double) { static_assert(N == 1, ""); }
-    A(std::initializer_list<int>) { static_assert(N == 3, ""); }
-  };
-
-  template <int N>
-  struct D {
-    D(std::initializer_list<int>) { static_assert(N == 0, ""); } // expected-note 1 {{candidate}}
-    D(std::initializer_list<double>) { static_assert(N == 1, ""); } // expected-note 1 {{candidate}}
-  };
-
-  template <int N>
-  struct E {
-    E(int, int) { static_assert(N == 0, ""); }
-    E(X1, int) { static_assert(N == 1, ""); }
-  };
-
-  void overload_resolution() {
-    { A<0> a{}; }
-    { A<0> a = {}; }
-    // Narrowing conversions don't affect viability. The next two choose
-    // the initializer_list constructor.
-    { A<3> a{1, 1.0}; } // expected-error {{narrowing conversion}}
-    { A<3> a = {1, 1.0}; } // expected-error {{narrowing conversion}}
-    { A<3> a{1, 2, 3, 4, 5, 6, 7, 8}; }
-    { A<3> a = {1, 2, 3, 4, 5, 6, 7, 8}; }
-    { A<3> a{1, 2, 3, 4, 5, 6, 7, 8}; }
-    { A<3> a{1, 2}; }
-
-    { D<0> d{1, 2, 3}; }
-    { D<1> d{1.0, 2.0, 3.0}; }
-    { D<-1> d{1, 2.0}; } // expected-error {{ambiguous}}
-
-    { E<0> e{1, 2}; }
-  }
-
-  void explicit_implicit() {
-    { X1 x{0}; }
-    { X1 x = {0}; }
-    { X2 x{0}; }
-    { X2 x = {0}; } // expected-error {{explicit}}
-  }
-
-  struct C {
-    C();
-    C(int, double);
-    C(int, int);
-    C(std::initializer_list<int>);
-
-    int operator[](C);
-  };
-
-  C function_call() {
-    void takes_C(C);
-    takes_C({1, 1.0});
-
-    C c;
-    c[{1, 1.0}];
-
-    return {1, 1.0};
-  }
-
-  void inline_init() {
-    (void) A<1>{1, 1.0};
-    (void) new A<1>{1, 1.0};
-  }
-
-  struct B {
-    B(C, int, C);
-  };
-
-  void nested_init() {
-    B b{{1, 1.0}, 2, {3, 4, 5, 6, 7}};
-  }
-}
-
 namespace litb {
 
   // invalid