nullptr.cpp updated this revision to Diff 314214.
nullptr.cpp edited the summary of this revision.
nullptr.cpp added a comment.

Separate out D93962 <https://reviews.llvm.org/D93962>


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D93955/new/

https://reviews.llvm.org/D93955

Files:
  clang/include/clang/Sema/Initialization.h
  clang/lib/Sema/SemaCast.cpp
  clang/lib/Sema/SemaInit.cpp
  clang/test/SemaCXX/diagnostic-initialization.cpp

Index: clang/test/SemaCXX/diagnostic-initialization.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/diagnostic-initialization.cpp
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -verify=expected %s
+
+namespace std {
+typedef decltype(sizeof(int)) size_t;
+
+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 std
+
+// C++11 [over.match.list]p1:
+//   In copy-list-initialization, if an explicit constructor is chosen, the
+//   initializer is ill-formed.
+struct A {
+  explicit A(std::initializer_list<int>) = delete;
+  // expected-note@-1 {{'A' has been explicitly marked deleted here}}
+  // expected-note@-2 {{explicit constructor declared here}}
+};
+
+A a = {1, 2, 3};
+// expected-error@-1 {{call to deleted constructor of 'A'}}
+// expected-error@-2 {{chosen constructor is explicit in copy-initialization}}
Index: clang/lib/Sema/SemaInit.cpp
===================================================================
--- clang/lib/Sema/SemaInit.cpp
+++ clang/lib/Sema/SemaInit.cpp
@@ -526,48 +526,52 @@
   // stlport does so too. Look for std::__debug for libstdc++, and for
   // std:: for stlport.  This is effectively a compiler-side implementation of
   // LWG2193.
-  if (!InitSeq && EmptyInitList && InitSeq.getFailureKind() ==
-          InitializationSequence::FK_ExplicitConstructor) {
-    OverloadCandidateSet::iterator Best;
-    OverloadingResult O =
-        InitSeq.getFailedCandidateSet()
-            .BestViableFunction(SemaRef, Kind.getLocation(), Best);
-    (void)O;
-    assert(O == OR_Success && "Inconsistent overload resolution");
-    CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function);
-    CXXRecordDecl *R = CtorDecl->getParent();
-
-    if (CtorDecl->getMinRequiredArguments() == 0 &&
-        CtorDecl->isExplicit() && R->getDeclName() &&
-        SemaRef.SourceMgr.isInSystemHeader(CtorDecl->getLocation())) {
-      bool IsInStd = false;
-      for (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(R->getDeclContext());
-           ND && !IsInStd; ND = dyn_cast<NamespaceDecl>(ND->getParent())) {
-        if (SemaRef.getStdNamespace()->InEnclosingNamespaceSetOf(ND))
-          IsInStd = true;
-      }
+  if (!InitSeq && EmptyInitList) {
+    auto Failures = InitSeq.getFailureKind();
+    if (Failures.end() !=
+        std::find(Failures.begin(), Failures.end(),
+                  InitializationSequence::FK_ExplicitConstructor)) {
+      OverloadCandidateSet::iterator Best;
+      OverloadingResult O = InitSeq.getFailedCandidateSet().BestViableFunction(
+          SemaRef, Kind.getLocation(), Best);
+      (void)O;
+      assert(O == OR_Success && "Inconsistent overload resolution");
+      CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function);
+      CXXRecordDecl *R = CtorDecl->getParent();
+
+      if (CtorDecl->getMinRequiredArguments() == 0 && CtorDecl->isExplicit() &&
+          R->getDeclName() &&
+          SemaRef.SourceMgr.isInSystemHeader(CtorDecl->getLocation())) {
+        bool IsInStd = false;
+        for (NamespaceDecl *ND = dyn_cast<NamespaceDecl>(R->getDeclContext());
+             ND && !IsInStd; ND = dyn_cast<NamespaceDecl>(ND->getParent())) {
+          if (SemaRef.getStdNamespace()->InEnclosingNamespaceSetOf(ND))
+            IsInStd = true;
+        }
 
-      if (IsInStd && llvm::StringSwitch<bool>(R->getName())
-              .Cases("basic_string", "deque", "forward_list", true)
-              .Cases("list", "map", "multimap", "multiset", true)
-              .Cases("priority_queue", "queue", "set", "stack", true)
-              .Cases("unordered_map", "unordered_set", "vector", true)
-              .Default(false)) {
-        InitSeq.InitializeFrom(
-            SemaRef, Entity,
-            InitializationKind::CreateValue(Loc, Loc, Loc, true),
-            MultiExprArg(), /*TopLevelOfInitList=*/false,
-            TreatUnavailableAsInvalid);
-        // Emit a warning for this.  System header warnings aren't shown
-        // by default, but people working on system headers should see it.
-        if (!VerifyOnly) {
-          SemaRef.Diag(CtorDecl->getLocation(),
-                       diag::warn_invalid_initializer_from_system_header);
-          if (Entity.getKind() == InitializedEntity::EK_Member)
-            SemaRef.Diag(Entity.getDecl()->getLocation(),
-                         diag::note_used_in_initialization_here);
-          else if (Entity.getKind() == InitializedEntity::EK_ArrayElement)
-            SemaRef.Diag(Loc, diag::note_used_in_initialization_here);
+        if (IsInStd &&
+            llvm::StringSwitch<bool>(R->getName())
+                .Cases("basic_string", "deque", "forward_list", true)
+                .Cases("list", "map", "multimap", "multiset", true)
+                .Cases("priority_queue", "queue", "set", "stack", true)
+                .Cases("unordered_map", "unordered_set", "vector", true)
+                .Default(false)) {
+          InitSeq.InitializeFrom(
+              SemaRef, Entity,
+              InitializationKind::CreateValue(Loc, Loc, Loc, true),
+              MultiExprArg(), /*TopLevelOfInitList=*/false,
+              TreatUnavailableAsInvalid);
+          // Emit a warning for this.  System header warnings aren't shown
+          // by default, but people working on system headers should see it.
+          if (!VerifyOnly) {
+            SemaRef.Diag(CtorDecl->getLocation(),
+                         diag::warn_invalid_initializer_from_system_header);
+            if (Entity.getKind() == InitializedEntity::EK_Member)
+              SemaRef.Diag(Entity.getDecl()->getLocation(),
+                           diag::note_used_in_initialization_here);
+            else if (Entity.getKind() == InitializedEntity::EK_ArrayElement)
+              SemaRef.Diag(Loc, diag::note_used_in_initialization_here);
+          }
         }
       }
     }
@@ -3488,49 +3492,51 @@
   if (!Failed())
     return false;
 
-  switch (getFailureKind()) {
-  case FK_TooManyInitsForReference:
-  case FK_ParenthesizedListInitForReference:
-  case FK_ArrayNeedsInitList:
-  case FK_ArrayNeedsInitListOrStringLiteral:
-  case FK_ArrayNeedsInitListOrWideStringLiteral:
-  case FK_NarrowStringIntoWideCharArray:
-  case FK_WideStringIntoCharArray:
-  case FK_IncompatWideStringIntoWideChar:
-  case FK_PlainStringIntoUTF8Char:
-  case FK_UTF8StringIntoPlainChar:
-  case FK_AddressOfOverloadFailed: // FIXME: Could do better
-  case FK_NonConstLValueReferenceBindingToTemporary:
-  case FK_NonConstLValueReferenceBindingToBitfield:
-  case FK_NonConstLValueReferenceBindingToVectorElement:
-  case FK_NonConstLValueReferenceBindingToMatrixElement:
-  case FK_NonConstLValueReferenceBindingToUnrelated:
-  case FK_RValueReferenceBindingToLValue:
-  case FK_ReferenceAddrspaceMismatchTemporary:
-  case FK_ReferenceInitDropsQualifiers:
-  case FK_ReferenceInitFailed:
-  case FK_ConversionFailed:
-  case FK_ConversionFromPropertyFailed:
-  case FK_TooManyInitsForScalar:
-  case FK_ParenthesizedListInitForScalar:
-  case FK_ReferenceBindingToInitList:
-  case FK_InitListBadDestinationType:
-  case FK_DefaultInitOfConst:
-  case FK_Incomplete:
-  case FK_ArrayTypeMismatch:
-  case FK_NonConstantArrayInit:
-  case FK_ListInitializationFailed:
-  case FK_VariableLengthArrayHasInitializer:
-  case FK_PlaceholderType:
-  case FK_ExplicitConstructor:
-  case FK_AddressOfUnaddressableFunction:
-    return false;
+  for (auto Failure : getFailureKind()) {
+    switch (Failure) {
+    case FK_TooManyInitsForReference:
+    case FK_ParenthesizedListInitForReference:
+    case FK_ArrayNeedsInitList:
+    case FK_ArrayNeedsInitListOrStringLiteral:
+    case FK_ArrayNeedsInitListOrWideStringLiteral:
+    case FK_NarrowStringIntoWideCharArray:
+    case FK_WideStringIntoCharArray:
+    case FK_IncompatWideStringIntoWideChar:
+    case FK_PlainStringIntoUTF8Char:
+    case FK_UTF8StringIntoPlainChar:
+    case FK_AddressOfOverloadFailed: // FIXME: Could do better
+    case FK_NonConstLValueReferenceBindingToTemporary:
+    case FK_NonConstLValueReferenceBindingToBitfield:
+    case FK_NonConstLValueReferenceBindingToVectorElement:
+    case FK_NonConstLValueReferenceBindingToMatrixElement:
+    case FK_NonConstLValueReferenceBindingToUnrelated:
+    case FK_RValueReferenceBindingToLValue:
+    case FK_ReferenceAddrspaceMismatchTemporary:
+    case FK_ReferenceInitDropsQualifiers:
+    case FK_ReferenceInitFailed:
+    case FK_ConversionFailed:
+    case FK_ConversionFromPropertyFailed:
+    case FK_TooManyInitsForScalar:
+    case FK_ParenthesizedListInitForScalar:
+    case FK_ReferenceBindingToInitList:
+    case FK_InitListBadDestinationType:
+    case FK_DefaultInitOfConst:
+    case FK_Incomplete:
+    case FK_ArrayTypeMismatch:
+    case FK_NonConstantArrayInit:
+    case FK_ListInitializationFailed:
+    case FK_VariableLengthArrayHasInitializer:
+    case FK_PlaceholderType:
+    case FK_ExplicitConstructor:
+    case FK_AddressOfUnaddressableFunction:
+      return false;
 
-  case FK_ReferenceInitOverloadFailed:
-  case FK_UserConversionOverloadFailed:
-  case FK_ConstructorOverloadFailed:
-  case FK_ListConstructorOverloadFailed:
-    return FailedOverloadResult == OR_Ambiguous;
+    case FK_ReferenceInitOverloadFailed:
+    case FK_UserConversionOverloadFailed:
+    case FK_ConstructorOverloadFailed:
+    case FK_ListConstructorOverloadFailed:
+      return FailedOverloadResult == OR_Ambiguous;
+    }
   }
 
   llvm_unreachable("Invalid EntityKind!");
@@ -3775,7 +3781,7 @@
 void InitializationSequence::SetOverloadFailure(FailureKind Failure,
                                                 OverloadingResult Result) {
   setSequenceKind(FailedSequence);
-  this->Failure = Failure;
+  this->Failures.push_back(Failure);
   this->FailedOverloadResult = Result;
 }
 
@@ -4143,34 +4149,33 @@
   }
 
   CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function);
-  if (Result != OR_Deleted) { // TODO: Support for more than one failure.
-    // C++11 [dcl.init]p6:
-    //   If a program calls for the default initialization of an object
-    //   of a const-qualified type T, T shall be a class type with a
-    //   user-provided default constructor.
-    // C++ core issue 253 proposal:
-    //   If the implicit default constructor initializes all subobjects, no
-    //   initializer should be required.
-    // The 253 proposal is for example needed to process libstdc++ headers
-    // in 5.x.
-    if (Kind.getKind() == InitializationKind::IK_Default &&
-        Entity.getType().isConstQualified()) {
-      if (!CtorDecl->getParent()->allowConstDefaultInit()) {
-        if (!maybeRecoverWithZeroInitialization(S, Sequence, Entity))
-          Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
-        return;
-      }
+  // C++11 [dcl.init]p6:
+  //   If a program calls for the default initialization of an object
+  //   of a const-qualified type T, T shall be a class type with a
+  //   user-provided default constructor.
+  // C++ core issue 253 proposal:
+  //   If the implicit default constructor initializes all subobjects, no
+  //   initializer should be required.
+  // The 253 proposal is for example needed to process libstdc++ headers
+  // in 5.x.
+  if (Kind.getKind() == InitializationKind::IK_Default &&
+      Entity.getType().isConstQualified()) {
+    if (!CtorDecl->getParent()->allowConstDefaultInit()) {
+      if (!maybeRecoverWithZeroInitialization(S, Sequence, Entity))
+        Sequence.SetFailed(InitializationSequence::FK_DefaultInitOfConst);
     }
+  }
 
-    // C++11 [over.match.list]p1:
-    //   In copy-list-initialization, if an explicit constructor is chosen, the
-    //   initializer is ill-formed.
-    if (IsListInit && !Kind.AllowExplicit() && CtorDecl->isExplicit()) {
-      Sequence.SetFailed(InitializationSequence::FK_ExplicitConstructor);
-      return;
-    }
+  // C++11 [over.match.list]p1:
+  //   In copy-list-initialization, if an explicit constructor is chosen, the
+  //   initializer is ill-formed.
+  if (IsListInit && !Kind.AllowExplicit() && CtorDecl->isExplicit()) {
+    Sequence.SetFailed(InitializationSequence::FK_ExplicitConstructor);
   }
 
+  if (Result == OR_Success && Sequence.Failed())
+    return;
+
   // [class.copy.elision]p3:
   // In some copy-initialization contexts, a two-stage overload resolution
   // is performed.
@@ -8916,311 +8921,306 @@
       OnlyArg = List->getInit(0);
     else
       OnlyArg = Args[0];
-  }
-  else
+  } else
     OnlyArg = nullptr;
 
   QualType DestType = Entity.getType();
-  switch (Failure) {
-  case FK_TooManyInitsForReference:
-    // FIXME: Customize for the initialized entity?
-    if (Args.empty()) {
-      // Dig out the reference subobject which is uninitialized and diagnose it.
-      // If this is value-initialization, this could be nested some way within
-      // the target type.
-      assert(Kind.getKind() == InitializationKind::IK_Value ||
-             DestType->isReferenceType());
-      bool Diagnosed =
-        DiagnoseUninitializedReference(S, Kind.getLocation(), DestType);
-      assert(Diagnosed && "couldn't find uninitialized reference to diagnose");
-      (void)Diagnosed;
-    } else  // FIXME: diagnostic below could be better!
-      S.Diag(Kind.getLocation(), diag::err_reference_has_multiple_inits)
-          << SourceRange(Args.front()->getBeginLoc(), Args.back()->getEndLoc());
-    break;
-  case FK_ParenthesizedListInitForReference:
-    S.Diag(Kind.getLocation(), diag::err_list_init_in_parens)
-      << 1 << Entity.getType() << Args[0]->getSourceRange();
-    break;
-
-  case FK_ArrayNeedsInitList:
-    S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list) << 0;
-    break;
-  case FK_ArrayNeedsInitListOrStringLiteral:
-    S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list) << 1;
-    break;
-  case FK_ArrayNeedsInitListOrWideStringLiteral:
-    S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list) << 2;
-    break;
-  case FK_NarrowStringIntoWideCharArray:
-    S.Diag(Kind.getLocation(), diag::err_array_init_narrow_string_into_wchar);
-    break;
-  case FK_WideStringIntoCharArray:
-    S.Diag(Kind.getLocation(), diag::err_array_init_wide_string_into_char);
-    break;
-  case FK_IncompatWideStringIntoWideChar:
-    S.Diag(Kind.getLocation(),
-           diag::err_array_init_incompat_wide_string_into_wchar);
-    break;
-  case FK_PlainStringIntoUTF8Char:
-    S.Diag(Kind.getLocation(),
-           diag::err_array_init_plain_string_into_char8_t);
-    S.Diag(Args.front()->getBeginLoc(),
-           diag::note_array_init_plain_string_into_char8_t)
-        << FixItHint::CreateInsertion(Args.front()->getBeginLoc(), "u8");
-    break;
-  case FK_UTF8StringIntoPlainChar:
-    S.Diag(Kind.getLocation(),
-           diag::err_array_init_utf8_string_into_char)
-      << S.getLangOpts().CPlusPlus20;
-    break;
-  case FK_ArrayTypeMismatch:
-  case FK_NonConstantArrayInit:
-    S.Diag(Kind.getLocation(),
-           (Failure == FK_ArrayTypeMismatch
-              ? diag::err_array_init_different_type
-              : diag::err_array_init_non_constant_array))
-      << DestType.getNonReferenceType()
-      << OnlyArg->getType()
-      << Args[0]->getSourceRange();
-    break;
-
-  case FK_VariableLengthArrayHasInitializer:
-    S.Diag(Kind.getLocation(), diag::err_variable_object_no_init)
-      << Args[0]->getSourceRange();
-    break;
+  for (auto Failure : Failures) {
+    switch (Failure) {
+    case FK_TooManyInitsForReference:
+      // FIXME: Customize for the initialized entity?
+      if (Args.empty()) {
+        // Dig out the reference subobject which is uninitialized and diagnose
+        // it. If this is value-initialization, this could be nested some way
+        // within the target type.
+        assert(Kind.getKind() == InitializationKind::IK_Value ||
+               DestType->isReferenceType());
+        bool Diagnosed =
+            DiagnoseUninitializedReference(S, Kind.getLocation(), DestType);
+        assert(Diagnosed &&
+               "couldn't find uninitialized reference to diagnose");
+        (void)Diagnosed;
+      } else // FIXME: diagnostic below could be better!
+        S.Diag(Kind.getLocation(), diag::err_reference_has_multiple_inits)
+            << SourceRange(Args.front()->getBeginLoc(),
+                           Args.back()->getEndLoc());
+      break;
+    case FK_ParenthesizedListInitForReference:
+      S.Diag(Kind.getLocation(), diag::err_list_init_in_parens)
+          << 1 << Entity.getType() << Args[0]->getSourceRange();
+      break;
 
-  case FK_AddressOfOverloadFailed: {
-    DeclAccessPair Found;
-    S.ResolveAddressOfOverloadedFunction(OnlyArg,
-                                         DestType.getNonReferenceType(),
-                                         true,
-                                         Found);
-    break;
-  }
+    case FK_ArrayNeedsInitList:
+      S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list) << 0;
+      break;
+    case FK_ArrayNeedsInitListOrStringLiteral:
+      S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list) << 1;
+      break;
+    case FK_ArrayNeedsInitListOrWideStringLiteral:
+      S.Diag(Kind.getLocation(), diag::err_array_init_not_init_list) << 2;
+      break;
+    case FK_NarrowStringIntoWideCharArray:
+      S.Diag(Kind.getLocation(), diag::err_array_init_narrow_string_into_wchar);
+      break;
+    case FK_WideStringIntoCharArray:
+      S.Diag(Kind.getLocation(), diag::err_array_init_wide_string_into_char);
+      break;
+    case FK_IncompatWideStringIntoWideChar:
+      S.Diag(Kind.getLocation(),
+             diag::err_array_init_incompat_wide_string_into_wchar);
+      break;
+    case FK_PlainStringIntoUTF8Char:
+      S.Diag(Kind.getLocation(),
+             diag::err_array_init_plain_string_into_char8_t);
+      S.Diag(Args.front()->getBeginLoc(),
+             diag::note_array_init_plain_string_into_char8_t)
+          << FixItHint::CreateInsertion(Args.front()->getBeginLoc(), "u8");
+      break;
+    case FK_UTF8StringIntoPlainChar:
+      S.Diag(Kind.getLocation(), diag::err_array_init_utf8_string_into_char)
+          << S.getLangOpts().CPlusPlus20;
+      break;
+    case FK_ArrayTypeMismatch:
+    case FK_NonConstantArrayInit:
+      S.Diag(Kind.getLocation(),
+             (Failure == FK_ArrayTypeMismatch
+                  ? diag::err_array_init_different_type
+                  : diag::err_array_init_non_constant_array))
+          << DestType.getNonReferenceType() << OnlyArg->getType()
+          << Args[0]->getSourceRange();
+      break;
 
-  case FK_AddressOfUnaddressableFunction: {
-    auto *FD = cast<FunctionDecl>(cast<DeclRefExpr>(OnlyArg)->getDecl());
-    S.checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true,
-                                        OnlyArg->getBeginLoc());
-    break;
-  }
+    case FK_VariableLengthArrayHasInitializer:
+      S.Diag(Kind.getLocation(), diag::err_variable_object_no_init)
+          << Args[0]->getSourceRange();
+      break;
 
-  case FK_ReferenceInitOverloadFailed:
-  case FK_UserConversionOverloadFailed:
-    switch (FailedOverloadResult) {
-    case OR_Ambiguous:
-
-      FailedCandidateSet.NoteCandidates(
-          PartialDiagnosticAt(
-              Kind.getLocation(),
-              Failure == FK_UserConversionOverloadFailed
-                  ? (S.PDiag(diag::err_typecheck_ambiguous_condition)
-                     << OnlyArg->getType() << DestType
-                     << Args[0]->getSourceRange())
-                  : (S.PDiag(diag::err_ref_init_ambiguous)
-                     << DestType << OnlyArg->getType()
-                     << Args[0]->getSourceRange())),
-          S, OCD_AmbiguousCandidates, Args);
+    case FK_AddressOfOverloadFailed: {
+      DeclAccessPair Found;
+      S.ResolveAddressOfOverloadedFunction(
+          OnlyArg, DestType.getNonReferenceType(), true, Found);
       break;
+    }
 
-    case OR_No_Viable_Function: {
-      auto Cands = FailedCandidateSet.CompleteCandidates(S, OCD_AllCandidates, Args);
-      if (!S.RequireCompleteType(Kind.getLocation(),
-                                 DestType.getNonReferenceType(),
-                          diag::err_typecheck_nonviable_condition_incomplete,
-                               OnlyArg->getType(), Args[0]->getSourceRange()))
-        S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition)
-          << (Entity.getKind() == InitializedEntity::EK_Result)
-          << OnlyArg->getType() << Args[0]->getSourceRange()
-          << DestType.getNonReferenceType();
-
-      FailedCandidateSet.NoteCandidates(S, Args, Cands);
+    case FK_AddressOfUnaddressableFunction: {
+      auto *FD = cast<FunctionDecl>(cast<DeclRefExpr>(OnlyArg)->getDecl());
+      S.checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true,
+                                          OnlyArg->getBeginLoc());
       break;
     }
-    case OR_Deleted: {
-      S.Diag(Kind.getLocation(), diag::err_typecheck_deleted_function)
-        << OnlyArg->getType() << DestType.getNonReferenceType()
-        << Args[0]->getSourceRange();
-      OverloadCandidateSet::iterator Best;
-      OverloadingResult Ovl
-        = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best);
-      if (Ovl == OR_Deleted) {
-        S.NoteDeletedFunction(Best->Function);
-      } else {
-        llvm_unreachable("Inconsistent overload resolution?");
+
+    case FK_ReferenceInitOverloadFailed:
+    case FK_UserConversionOverloadFailed:
+      switch (FailedOverloadResult) {
+      case OR_Ambiguous:
+
+        FailedCandidateSet.NoteCandidates(
+            PartialDiagnosticAt(
+                Kind.getLocation(),
+                Failure == FK_UserConversionOverloadFailed
+                    ? (S.PDiag(diag::err_typecheck_ambiguous_condition)
+                       << OnlyArg->getType() << DestType
+                       << Args[0]->getSourceRange())
+                    : (S.PDiag(diag::err_ref_init_ambiguous)
+                       << DestType << OnlyArg->getType()
+                       << Args[0]->getSourceRange())),
+            S, OCD_AmbiguousCandidates, Args);
+        break;
+
+      case OR_No_Viable_Function: {
+        auto Cands =
+            FailedCandidateSet.CompleteCandidates(S, OCD_AllCandidates, Args);
+        if (!S.RequireCompleteType(
+                Kind.getLocation(), DestType.getNonReferenceType(),
+                diag::err_typecheck_nonviable_condition_incomplete,
+                OnlyArg->getType(), Args[0]->getSourceRange()))
+          S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition)
+              << (Entity.getKind() == InitializedEntity::EK_Result)
+              << OnlyArg->getType() << Args[0]->getSourceRange()
+              << DestType.getNonReferenceType();
+
+        FailedCandidateSet.NoteCandidates(S, Args, Cands);
+        break;
+      }
+      case OR_Deleted: {
+        S.Diag(Kind.getLocation(), diag::err_typecheck_deleted_function)
+            << OnlyArg->getType() << DestType.getNonReferenceType()
+            << Args[0]->getSourceRange();
+        OverloadCandidateSet::iterator Best;
+        OverloadingResult Ovl =
+            FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best);
+        if (Ovl == OR_Deleted) {
+          S.NoteDeletedFunction(Best->Function);
+        } else {
+          llvm_unreachable("Inconsistent overload resolution?");
+        }
+        break;
+      }
+
+      case OR_Success:
+        llvm_unreachable("Conversion did not fail!");
       }
       break;
-    }
 
-    case OR_Success:
-      llvm_unreachable("Conversion did not fail!");
-    }
-    break;
+    case FK_NonConstLValueReferenceBindingToTemporary:
+      if (isa<InitListExpr>(Args[0])) {
+        S.Diag(Kind.getLocation(), diag::err_lvalue_reference_bind_to_initlist)
+            << DestType.getNonReferenceType().isVolatileQualified()
+            << DestType.getNonReferenceType() << Args[0]->getSourceRange();
+        break;
+      }
+      LLVM_FALLTHROUGH;
 
-  case FK_NonConstLValueReferenceBindingToTemporary:
-    if (isa<InitListExpr>(Args[0])) {
+    case FK_NonConstLValueReferenceBindingToUnrelated:
       S.Diag(Kind.getLocation(),
-             diag::err_lvalue_reference_bind_to_initlist)
-      << DestType.getNonReferenceType().isVolatileQualified()
-      << DestType.getNonReferenceType()
-      << Args[0]->getSourceRange();
+             Failure == FK_NonConstLValueReferenceBindingToTemporary
+                 ? diag::err_lvalue_reference_bind_to_temporary
+                 : diag::err_lvalue_reference_bind_to_unrelated)
+          << DestType.getNonReferenceType().isVolatileQualified()
+          << DestType.getNonReferenceType() << OnlyArg->getType()
+          << Args[0]->getSourceRange();
       break;
-    }
-    LLVM_FALLTHROUGH;
-
-  case FK_NonConstLValueReferenceBindingToUnrelated:
-    S.Diag(Kind.getLocation(),
-           Failure == FK_NonConstLValueReferenceBindingToTemporary
-             ? diag::err_lvalue_reference_bind_to_temporary
-             : diag::err_lvalue_reference_bind_to_unrelated)
-      << DestType.getNonReferenceType().isVolatileQualified()
-      << DestType.getNonReferenceType()
-      << OnlyArg->getType()
-      << Args[0]->getSourceRange();
-    break;
 
-  case FK_NonConstLValueReferenceBindingToBitfield: {
-    // We don't necessarily have an unambiguous source bit-field.
-    FieldDecl *BitField = Args[0]->getSourceBitField();
-    S.Diag(Kind.getLocation(), diag::err_reference_bind_to_bitfield)
-      << DestType.isVolatileQualified()
-      << (BitField ? BitField->getDeclName() : DeclarationName())
-      << (BitField != nullptr)
-      << Args[0]->getSourceRange();
-    if (BitField)
-      S.Diag(BitField->getLocation(), diag::note_bitfield_decl);
-    break;
-  }
+    case FK_NonConstLValueReferenceBindingToBitfield: {
+      // We don't necessarily have an unambiguous source bit-field.
+      FieldDecl *BitField = Args[0]->getSourceBitField();
+      S.Diag(Kind.getLocation(), diag::err_reference_bind_to_bitfield)
+          << DestType.isVolatileQualified()
+          << (BitField ? BitField->getDeclName() : DeclarationName())
+          << (BitField != nullptr) << Args[0]->getSourceRange();
+      if (BitField)
+        S.Diag(BitField->getLocation(), diag::note_bitfield_decl);
+      break;
+    }
 
-  case FK_NonConstLValueReferenceBindingToVectorElement:
-    S.Diag(Kind.getLocation(), diag::err_reference_bind_to_vector_element)
-      << DestType.isVolatileQualified()
-      << Args[0]->getSourceRange();
-    break;
+    case FK_NonConstLValueReferenceBindingToVectorElement:
+      S.Diag(Kind.getLocation(), diag::err_reference_bind_to_vector_element)
+          << DestType.isVolatileQualified() << Args[0]->getSourceRange();
+      break;
 
-  case FK_NonConstLValueReferenceBindingToMatrixElement:
-    S.Diag(Kind.getLocation(), diag::err_reference_bind_to_matrix_element)
-        << DestType.isVolatileQualified() << Args[0]->getSourceRange();
-    break;
+    case FK_NonConstLValueReferenceBindingToMatrixElement:
+      S.Diag(Kind.getLocation(), diag::err_reference_bind_to_matrix_element)
+          << DestType.isVolatileQualified() << Args[0]->getSourceRange();
+      break;
 
-  case FK_RValueReferenceBindingToLValue:
-    S.Diag(Kind.getLocation(), diag::err_lvalue_to_rvalue_ref)
-      << DestType.getNonReferenceType() << OnlyArg->getType()
-      << Args[0]->getSourceRange();
-    break;
+    case FK_RValueReferenceBindingToLValue:
+      S.Diag(Kind.getLocation(), diag::err_lvalue_to_rvalue_ref)
+          << DestType.getNonReferenceType() << OnlyArg->getType()
+          << Args[0]->getSourceRange();
+      break;
 
-  case FK_ReferenceAddrspaceMismatchTemporary:
-    S.Diag(Kind.getLocation(), diag::err_reference_bind_temporary_addrspace)
-        << DestType << Args[0]->getSourceRange();
-    break;
+    case FK_ReferenceAddrspaceMismatchTemporary:
+      S.Diag(Kind.getLocation(), diag::err_reference_bind_temporary_addrspace)
+          << DestType << Args[0]->getSourceRange();
+      break;
 
-  case FK_ReferenceInitDropsQualifiers: {
-    QualType SourceType = OnlyArg->getType();
-    QualType NonRefType = DestType.getNonReferenceType();
-    Qualifiers DroppedQualifiers =
-        SourceType.getQualifiers() - NonRefType.getQualifiers();
+    case FK_ReferenceInitDropsQualifiers: {
+      QualType SourceType = OnlyArg->getType();
+      QualType NonRefType = DestType.getNonReferenceType();
+      Qualifiers DroppedQualifiers =
+          SourceType.getQualifiers() - NonRefType.getQualifiers();
+
+      if (!NonRefType.getQualifiers().isAddressSpaceSupersetOf(
+              SourceType.getQualifiers()))
+        S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals)
+            << NonRefType << SourceType << 1 /*addr space*/
+            << Args[0]->getSourceRange();
+      else if (DroppedQualifiers.hasQualifiers())
+        S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals)
+            << NonRefType << SourceType << 0 /*cv quals*/
+            << Qualifiers::fromCVRMask(DroppedQualifiers.getCVRQualifiers())
+            << DroppedQualifiers.getCVRQualifiers()
+            << Args[0]->getSourceRange();
+      else
+        // FIXME: Consider decomposing the type and explaining which qualifiers
+        // were dropped where, or on which level a 'const' is missing, etc.
+        S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals)
+            << NonRefType << SourceType << 2 /*incompatible quals*/
+            << Args[0]->getSourceRange();
+      break;
+    }
 
-    if (!NonRefType.getQualifiers().isAddressSpaceSupersetOf(
-            SourceType.getQualifiers()))
-      S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals)
-          << NonRefType << SourceType << 1 /*addr space*/
-          << Args[0]->getSourceRange();
-    else if (DroppedQualifiers.hasQualifiers())
-      S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals)
-          << NonRefType << SourceType << 0 /*cv quals*/
-          << Qualifiers::fromCVRMask(DroppedQualifiers.getCVRQualifiers())
-          << DroppedQualifiers.getCVRQualifiers() << Args[0]->getSourceRange();
-    else
-      // FIXME: Consider decomposing the type and explaining which qualifiers
-      // were dropped where, or on which level a 'const' is missing, etc.
-      S.Diag(Kind.getLocation(), diag::err_reference_bind_drops_quals)
-          << NonRefType << SourceType << 2 /*incompatible quals*/
+    case FK_ReferenceInitFailed:
+      S.Diag(Kind.getLocation(), diag::err_reference_bind_failed)
+          << DestType.getNonReferenceType()
+          << DestType.getNonReferenceType()->isIncompleteType()
+          << OnlyArg->isLValue() << OnlyArg->getType()
           << Args[0]->getSourceRange();
-    break;
-  }
+      emitBadConversionNotes(S, Entity, Args[0]);
+      break;
 
-  case FK_ReferenceInitFailed:
-    S.Diag(Kind.getLocation(), diag::err_reference_bind_failed)
-      << DestType.getNonReferenceType()
-      << DestType.getNonReferenceType()->isIncompleteType()
-      << OnlyArg->isLValue()
-      << OnlyArg->getType()
-      << Args[0]->getSourceRange();
-    emitBadConversionNotes(S, Entity, Args[0]);
-    break;
+    case FK_ConversionFailed: {
+      QualType FromType = OnlyArg->getType();
+      PartialDiagnostic PDiag = S.PDiag(diag::err_init_conversion_failed)
+                                << (int)Entity.getKind() << DestType
+                                << OnlyArg->isLValue() << FromType
+                                << Args[0]->getSourceRange();
+      S.HandleFunctionTypeMismatch(PDiag, FromType, DestType);
+      S.Diag(Kind.getLocation(), PDiag);
+      emitBadConversionNotes(S, Entity, Args[0]);
+      break;
+    }
 
-  case FK_ConversionFailed: {
-    QualType FromType = OnlyArg->getType();
-    PartialDiagnostic PDiag = S.PDiag(diag::err_init_conversion_failed)
-      << (int)Entity.getKind()
-      << DestType
-      << OnlyArg->isLValue()
-      << FromType
-      << Args[0]->getSourceRange();
-    S.HandleFunctionTypeMismatch(PDiag, FromType, DestType);
-    S.Diag(Kind.getLocation(), PDiag);
-    emitBadConversionNotes(S, Entity, Args[0]);
-    break;
-  }
+    case FK_ConversionFromPropertyFailed:
+      // No-op. This error has already been reported.
+      break;
 
-  case FK_ConversionFromPropertyFailed:
-    // No-op. This error has already been reported.
-    break;
+    case FK_TooManyInitsForScalar: {
+      SourceRange R;
 
-  case FK_TooManyInitsForScalar: {
-    SourceRange R;
+      auto *InitList = dyn_cast<InitListExpr>(Args[0]);
+      if (InitList && InitList->getNumInits() >= 1) {
+        R = SourceRange(InitList->getInit(0)->getEndLoc(),
+                        InitList->getEndLoc());
+      } else {
+        assert(Args.size() > 1 && "Expected multiple initializers!");
+        R = SourceRange(Args.front()->getEndLoc(), Args.back()->getEndLoc());
+      }
 
-    auto *InitList = dyn_cast<InitListExpr>(Args[0]);
-    if (InitList && InitList->getNumInits() >= 1) {
-      R = SourceRange(InitList->getInit(0)->getEndLoc(), InitList->getEndLoc());
-    } else {
-      assert(Args.size() > 1 && "Expected multiple initializers!");
-      R = SourceRange(Args.front()->getEndLoc(), Args.back()->getEndLoc());
+      R.setBegin(S.getLocForEndOfToken(R.getBegin()));
+      if (Kind.isCStyleOrFunctionalCast())
+        S.Diag(Kind.getLocation(),
+               diag::err_builtin_func_cast_more_than_one_arg)
+            << R;
+      else
+        S.Diag(Kind.getLocation(), diag::err_excess_initializers)
+            << /*scalar=*/2 << R;
+      break;
     }
 
-    R.setBegin(S.getLocForEndOfToken(R.getBegin()));
-    if (Kind.isCStyleOrFunctionalCast())
-      S.Diag(Kind.getLocation(), diag::err_builtin_func_cast_more_than_one_arg)
-        << R;
-    else
-      S.Diag(Kind.getLocation(), diag::err_excess_initializers)
-        << /*scalar=*/2 << R;
-    break;
-  }
-
-  case FK_ParenthesizedListInitForScalar:
-    S.Diag(Kind.getLocation(), diag::err_list_init_in_parens)
-      << 0 << Entity.getType() << Args[0]->getSourceRange();
-    break;
-
-  case FK_ReferenceBindingToInitList:
-    S.Diag(Kind.getLocation(), diag::err_reference_bind_init_list)
-      << DestType.getNonReferenceType() << Args[0]->getSourceRange();
-    break;
+    case FK_ParenthesizedListInitForScalar:
+      S.Diag(Kind.getLocation(), diag::err_list_init_in_parens)
+          << 0 << Entity.getType() << Args[0]->getSourceRange();
+      break;
 
-  case FK_InitListBadDestinationType:
-    S.Diag(Kind.getLocation(), diag::err_init_list_bad_dest_type)
-      << (DestType->isRecordType()) << DestType << Args[0]->getSourceRange();
-    break;
+    case FK_ReferenceBindingToInitList:
+      S.Diag(Kind.getLocation(), diag::err_reference_bind_init_list)
+          << DestType.getNonReferenceType() << Args[0]->getSourceRange();
+      break;
 
-  case FK_ListConstructorOverloadFailed:
-  case FK_ConstructorOverloadFailed: {
-    SourceRange ArgsRange;
-    if (Args.size())
-      ArgsRange =
-          SourceRange(Args.front()->getBeginLoc(), Args.back()->getEndLoc());
+    case FK_InitListBadDestinationType:
+      S.Diag(Kind.getLocation(), diag::err_init_list_bad_dest_type)
+          << (DestType->isRecordType()) << DestType
+          << Args[0]->getSourceRange();
+      break;
 
-    if (Failure == FK_ListConstructorOverloadFailed) {
-      assert(Args.size() == 1 &&
-             "List construction from other than 1 argument.");
-      InitListExpr *InitList = cast<InitListExpr>(Args[0]);
-      Args = MultiExprArg(InitList->getInits(), InitList->getNumInits());
-    }
+    case FK_ListConstructorOverloadFailed:
+    case FK_ConstructorOverloadFailed: {
+      SourceRange ArgsRange;
+      if (Args.size())
+        ArgsRange =
+            SourceRange(Args.front()->getBeginLoc(), Args.back()->getEndLoc());
+
+      if (Failure == FK_ListConstructorOverloadFailed) {
+        assert(Args.size() == 1 &&
+               "List construction from other than 1 argument.");
+        InitListExpr *InitList = cast<InitListExpr>(Args[0]);
+        Args = MultiExprArg(InitList->getInits(), InitList->getNumInits());
+      }
 
-    // FIXME: Using "DestType" for the entity we're printing is probably
-    // bad.
-    switch (FailedOverloadResult) {
+      // FIXME: Using "DestType" for the entity we're printing is probably
+      // bad.
+      switch (FailedOverloadResult) {
       case OR_Ambiguous:
         FailedCandidateSet.NoteCandidates(
             PartialDiagnosticAt(Kind.getLocation(),
@@ -9238,39 +9238,39 @@
           // base within a constructor. If no viable function was
           // found, notify the user that they need to explicitly
           // initialize this base/member.
-          CXXConstructorDecl *Constructor
-            = cast<CXXConstructorDecl>(S.CurContext);
+          CXXConstructorDecl *Constructor =
+              cast<CXXConstructorDecl>(S.CurContext);
           const CXXRecordDecl *InheritedFrom = nullptr;
           if (auto Inherited = Constructor->getInheritedConstructor())
             InheritedFrom = Inherited.getShadowDecl()->getNominatedBaseClass();
           if (Entity.getKind() == InitializedEntity::EK_Base) {
             S.Diag(Kind.getLocation(), diag::err_missing_default_ctor)
-              << (InheritedFrom ? 2 : Constructor->isImplicit() ? 1 : 0)
-              << S.Context.getTypeDeclType(Constructor->getParent())
-              << /*base=*/0
-              << Entity.getType()
-              << InheritedFrom;
-
-            RecordDecl *BaseDecl
-              = Entity.getBaseSpecifier()->getType()->castAs<RecordType>()
-                                                                  ->getDecl();
+                << (InheritedFrom               ? 2
+                    : Constructor->isImplicit() ? 1
+                                                : 0)
+                << S.Context.getTypeDeclType(Constructor->getParent())
+                << /*base=*/0 << Entity.getType() << InheritedFrom;
+
+            RecordDecl *BaseDecl = Entity.getBaseSpecifier()
+                                       ->getType()
+                                       ->castAs<RecordType>()
+                                       ->getDecl();
             S.Diag(BaseDecl->getLocation(), diag::note_previous_decl)
-              << S.Context.getTagDeclType(BaseDecl);
+                << S.Context.getTagDeclType(BaseDecl);
           } else {
             S.Diag(Kind.getLocation(), diag::err_missing_default_ctor)
-              << (InheritedFrom ? 2 : Constructor->isImplicit() ? 1 : 0)
-              << S.Context.getTypeDeclType(Constructor->getParent())
-              << /*member=*/1
-              << Entity.getName()
-              << InheritedFrom;
+                << (InheritedFrom               ? 2
+                    : Constructor->isImplicit() ? 1
+                                                : 0)
+                << S.Context.getTypeDeclType(Constructor->getParent())
+                << /*member=*/1 << Entity.getName() << InheritedFrom;
             S.Diag(Entity.getDecl()->getLocation(),
                    diag::note_member_declared_at);
 
-            if (const RecordType *Record
-                                 = Entity.getType()->getAs<RecordType>())
-              S.Diag(Record->getDecl()->getLocation(),
-                     diag::note_previous_decl)
-                << S.Context.getTagDeclType(Record->getDecl());
+            if (const RecordType *Record =
+                    Entity.getType()->getAs<RecordType>())
+              S.Diag(Record->getDecl()->getLocation(), diag::note_previous_decl)
+                  << S.Context.getTagDeclType(Record->getDecl());
           }
           break;
         }
@@ -9285,8 +9285,8 @@
 
       case OR_Deleted: {
         OverloadCandidateSet::iterator Best;
-        OverloadingResult Ovl
-          = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best);
+        OverloadingResult Ovl =
+            FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best);
         if (Ovl != OR_Deleted) {
           S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init)
               << DestType << ArgsRange;
@@ -9299,8 +9299,8 @@
         // implicit.
         if (S.isImplicitlyDeleted(Best->Function))
           S.Diag(Kind.getLocation(), diag::err_ovl_deleted_special_init)
-            << S.getSpecialMember(cast<CXXMethodDecl>(Best->Function))
-            << DestType << ArgsRange;
+              << S.getSpecialMember(cast<CXXMethodDecl>(Best->Function))
+              << DestType << ArgsRange;
         else
           S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init)
               << DestType << ArgsRange;
@@ -9311,61 +9311,64 @@
 
       case OR_Success:
         llvm_unreachable("Conversion did not fail!");
-    }
-  }
-  break;
-
-  case FK_DefaultInitOfConst:
-    if (Entity.getKind() == InitializedEntity::EK_Member &&
-        isa<CXXConstructorDecl>(S.CurContext)) {
-      // This is implicit default-initialization of a const member in
-      // a constructor. Complain that it needs to be explicitly
-      // initialized.
-      CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(S.CurContext);
-      S.Diag(Kind.getLocation(), diag::err_uninitialized_member_in_ctor)
-        << (Constructor->getInheritedConstructor() ? 2 :
-            Constructor->isImplicit() ? 1 : 0)
-        << S.Context.getTypeDeclType(Constructor->getParent())
-        << /*const=*/1
-        << Entity.getName();
-      S.Diag(Entity.getDecl()->getLocation(), diag::note_previous_decl)
-        << Entity.getName();
-    } else {
-      S.Diag(Kind.getLocation(), diag::err_default_init_const)
-          << DestType << (bool)DestType->getAs<RecordType>();
-    }
-    break;
+      }
+    } break;
 
-  case FK_Incomplete:
-    S.RequireCompleteType(Kind.getLocation(), FailedIncompleteType,
-                          diag::err_init_incomplete_type);
-    break;
+    case FK_DefaultInitOfConst:
+      if (Entity.getKind() == InitializedEntity::EK_Member &&
+          isa<CXXConstructorDecl>(S.CurContext)) {
+        // This is implicit default-initialization of a const member in
+        // a constructor. Complain that it needs to be explicitly
+        // initialized.
+        CXXConstructorDecl *Constructor =
+            cast<CXXConstructorDecl>(S.CurContext);
+        S.Diag(Kind.getLocation(), diag::err_uninitialized_member_in_ctor)
+            << (Constructor->getInheritedConstructor() ? 2
+                : Constructor->isImplicit()            ? 1
+                                                       : 0)
+            << S.Context.getTypeDeclType(Constructor->getParent())
+            << /*const=*/1 << Entity.getName();
+        S.Diag(Entity.getDecl()->getLocation(), diag::note_previous_decl)
+            << Entity.getName();
+      } else {
+        S.Diag(Kind.getLocation(), diag::err_default_init_const)
+            << DestType << (bool)DestType->getAs<RecordType>();
+      }
+      break;
 
-  case FK_ListInitializationFailed: {
-    // Run the init list checker again to emit diagnostics.
-    InitListExpr *InitList = cast<InitListExpr>(Args[0]);
-    diagnoseListInit(S, Entity, InitList);
-    break;
-  }
+    case FK_Incomplete:
+      S.RequireCompleteType(Kind.getLocation(), FailedIncompleteType,
+                            diag::err_init_incomplete_type);
+      break;
 
-  case FK_PlaceholderType: {
-    // FIXME: Already diagnosed!
-    break;
-  }
+    case FK_ListInitializationFailed: {
+      // Run the init list checker again to emit diagnostics.
+      InitListExpr *InitList = cast<InitListExpr>(Args[0]);
+      diagnoseListInit(S, Entity, InitList);
+      break;
+    }
 
-  case FK_ExplicitConstructor: {
-    S.Diag(Kind.getLocation(), diag::err_selected_explicit_constructor)
-      << Args[0]->getSourceRange();
-    OverloadCandidateSet::iterator Best;
-    OverloadingResult Ovl
-      = FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best);
-    (void)Ovl;
-    assert(Ovl == OR_Success && "Inconsistent overload resolution");
-    CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function);
-    S.Diag(CtorDecl->getLocation(),
-           diag::note_explicit_ctor_deduction_guide_here) << false;
-    break;
-  }
+    case FK_PlaceholderType: {
+      // FIXME: Already diagnosed!
+      break;
+    }
+
+    case FK_ExplicitConstructor: {
+      S.Diag(Kind.getLocation(), diag::err_selected_explicit_constructor)
+          << Args[0]->getSourceRange();
+      OverloadCandidateSet::iterator Best;
+      OverloadingResult Ovl =
+          FailedCandidateSet.BestViableFunction(S, Kind.getLocation(), Best);
+      (void)Ovl;
+      assert((Ovl == OR_Success || Ovl == OR_Deleted) &&
+             "Inconsistent overload resolution");
+      CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function);
+      S.Diag(CtorDecl->getLocation(),
+             diag::note_explicit_ctor_deduction_guide_here)
+          << false;
+      break;
+    }
+    }
   }
 
   PrintInitLocationNote(S, Entity);
@@ -9376,164 +9379,166 @@
   switch (SequenceKind) {
   case FailedSequence: {
     OS << "Failed sequence: ";
-    switch (Failure) {
-    case FK_TooManyInitsForReference:
-      OS << "too many initializers for reference";
-      break;
+    for (auto Failure : Failures) {
+      switch (Failure) {
+      case FK_TooManyInitsForReference:
+        OS << "too many initializers for reference";
+        break;
 
-    case FK_ParenthesizedListInitForReference:
-      OS << "parenthesized list init for reference";
-      break;
+      case FK_ParenthesizedListInitForReference:
+        OS << "parenthesized list init for reference";
+        break;
 
-    case FK_ArrayNeedsInitList:
-      OS << "array requires initializer list";
-      break;
+      case FK_ArrayNeedsInitList:
+        OS << "array requires initializer list";
+        break;
 
-    case FK_AddressOfUnaddressableFunction:
-      OS << "address of unaddressable function was taken";
-      break;
+      case FK_AddressOfUnaddressableFunction:
+        OS << "address of unaddressable function was taken";
+        break;
 
-    case FK_ArrayNeedsInitListOrStringLiteral:
-      OS << "array requires initializer list or string literal";
-      break;
+      case FK_ArrayNeedsInitListOrStringLiteral:
+        OS << "array requires initializer list or string literal";
+        break;
 
-    case FK_ArrayNeedsInitListOrWideStringLiteral:
-      OS << "array requires initializer list or wide string literal";
-      break;
+      case FK_ArrayNeedsInitListOrWideStringLiteral:
+        OS << "array requires initializer list or wide string literal";
+        break;
 
-    case FK_NarrowStringIntoWideCharArray:
-      OS << "narrow string into wide char array";
-      break;
+      case FK_NarrowStringIntoWideCharArray:
+        OS << "narrow string into wide char array";
+        break;
 
-    case FK_WideStringIntoCharArray:
-      OS << "wide string into char array";
-      break;
+      case FK_WideStringIntoCharArray:
+        OS << "wide string into char array";
+        break;
 
-    case FK_IncompatWideStringIntoWideChar:
-      OS << "incompatible wide string into wide char array";
-      break;
+      case FK_IncompatWideStringIntoWideChar:
+        OS << "incompatible wide string into wide char array";
+        break;
 
-    case FK_PlainStringIntoUTF8Char:
-      OS << "plain string literal into char8_t array";
-      break;
+      case FK_PlainStringIntoUTF8Char:
+        OS << "plain string literal into char8_t array";
+        break;
 
-    case FK_UTF8StringIntoPlainChar:
-      OS << "u8 string literal into char array";
-      break;
+      case FK_UTF8StringIntoPlainChar:
+        OS << "u8 string literal into char array";
+        break;
 
-    case FK_ArrayTypeMismatch:
-      OS << "array type mismatch";
-      break;
+      case FK_ArrayTypeMismatch:
+        OS << "array type mismatch";
+        break;
 
-    case FK_NonConstantArrayInit:
-      OS << "non-constant array initializer";
-      break;
+      case FK_NonConstantArrayInit:
+        OS << "non-constant array initializer";
+        break;
 
-    case FK_AddressOfOverloadFailed:
-      OS << "address of overloaded function failed";
-      break;
+      case FK_AddressOfOverloadFailed:
+        OS << "address of overloaded function failed";
+        break;
 
-    case FK_ReferenceInitOverloadFailed:
-      OS << "overload resolution for reference initialization failed";
-      break;
+      case FK_ReferenceInitOverloadFailed:
+        OS << "overload resolution for reference initialization failed";
+        break;
 
-    case FK_NonConstLValueReferenceBindingToTemporary:
-      OS << "non-const lvalue reference bound to temporary";
-      break;
+      case FK_NonConstLValueReferenceBindingToTemporary:
+        OS << "non-const lvalue reference bound to temporary";
+        break;
 
-    case FK_NonConstLValueReferenceBindingToBitfield:
-      OS << "non-const lvalue reference bound to bit-field";
-      break;
+      case FK_NonConstLValueReferenceBindingToBitfield:
+        OS << "non-const lvalue reference bound to bit-field";
+        break;
 
-    case FK_NonConstLValueReferenceBindingToVectorElement:
-      OS << "non-const lvalue reference bound to vector element";
-      break;
+      case FK_NonConstLValueReferenceBindingToVectorElement:
+        OS << "non-const lvalue reference bound to vector element";
+        break;
 
-    case FK_NonConstLValueReferenceBindingToMatrixElement:
-      OS << "non-const lvalue reference bound to matrix element";
-      break;
+      case FK_NonConstLValueReferenceBindingToMatrixElement:
+        OS << "non-const lvalue reference bound to matrix element";
+        break;
 
-    case FK_NonConstLValueReferenceBindingToUnrelated:
-      OS << "non-const lvalue reference bound to unrelated type";
-      break;
+      case FK_NonConstLValueReferenceBindingToUnrelated:
+        OS << "non-const lvalue reference bound to unrelated type";
+        break;
 
-    case FK_RValueReferenceBindingToLValue:
-      OS << "rvalue reference bound to an lvalue";
-      break;
+      case FK_RValueReferenceBindingToLValue:
+        OS << "rvalue reference bound to an lvalue";
+        break;
 
-    case FK_ReferenceInitDropsQualifiers:
-      OS << "reference initialization drops qualifiers";
-      break;
+      case FK_ReferenceInitDropsQualifiers:
+        OS << "reference initialization drops qualifiers";
+        break;
 
-    case FK_ReferenceAddrspaceMismatchTemporary:
-      OS << "reference with mismatching address space bound to temporary";
-      break;
+      case FK_ReferenceAddrspaceMismatchTemporary:
+        OS << "reference with mismatching address space bound to temporary";
+        break;
 
-    case FK_ReferenceInitFailed:
-      OS << "reference initialization failed";
-      break;
+      case FK_ReferenceInitFailed:
+        OS << "reference initialization failed";
+        break;
 
-    case FK_ConversionFailed:
-      OS << "conversion failed";
-      break;
+      case FK_ConversionFailed:
+        OS << "conversion failed";
+        break;
 
-    case FK_ConversionFromPropertyFailed:
-      OS << "conversion from property failed";
-      break;
+      case FK_ConversionFromPropertyFailed:
+        OS << "conversion from property failed";
+        break;
 
-    case FK_TooManyInitsForScalar:
-      OS << "too many initializers for scalar";
-      break;
+      case FK_TooManyInitsForScalar:
+        OS << "too many initializers for scalar";
+        break;
 
-    case FK_ParenthesizedListInitForScalar:
-      OS << "parenthesized list init for reference";
-      break;
+      case FK_ParenthesizedListInitForScalar:
+        OS << "parenthesized list init for reference";
+        break;
 
-    case FK_ReferenceBindingToInitList:
-      OS << "referencing binding to initializer list";
-      break;
+      case FK_ReferenceBindingToInitList:
+        OS << "referencing binding to initializer list";
+        break;
 
-    case FK_InitListBadDestinationType:
-      OS << "initializer list for non-aggregate, non-scalar type";
-      break;
+      case FK_InitListBadDestinationType:
+        OS << "initializer list for non-aggregate, non-scalar type";
+        break;
 
-    case FK_UserConversionOverloadFailed:
-      OS << "overloading failed for user-defined conversion";
-      break;
+      case FK_UserConversionOverloadFailed:
+        OS << "overloading failed for user-defined conversion";
+        break;
 
-    case FK_ConstructorOverloadFailed:
-      OS << "constructor overloading failed";
-      break;
+      case FK_ConstructorOverloadFailed:
+        OS << "constructor overloading failed";
+        break;
 
-    case FK_DefaultInitOfConst:
-      OS << "default initialization of a const variable";
-      break;
+      case FK_DefaultInitOfConst:
+        OS << "default initialization of a const variable";
+        break;
 
-    case FK_Incomplete:
-      OS << "initialization of incomplete type";
-      break;
+      case FK_Incomplete:
+        OS << "initialization of incomplete type";
+        break;
 
-    case FK_ListInitializationFailed:
-      OS << "list initialization checker failure";
-      break;
+      case FK_ListInitializationFailed:
+        OS << "list initialization checker failure";
+        break;
 
-    case FK_VariableLengthArrayHasInitializer:
-      OS << "variable length array has an initializer";
-      break;
+      case FK_VariableLengthArrayHasInitializer:
+        OS << "variable length array has an initializer";
+        break;
 
-    case FK_PlaceholderType:
-      OS << "initializer expression isn't contextually valid";
-      break;
+      case FK_PlaceholderType:
+        OS << "initializer expression isn't contextually valid";
+        break;
 
-    case FK_ListConstructorOverloadFailed:
-      OS << "list constructor overloading failed";
-      break;
+      case FK_ListConstructorOverloadFailed:
+        OS << "list constructor overloading failed";
+        break;
 
-    case FK_ExplicitConstructor:
-      OS << "list copy initialization chose explicit constructor";
-      break;
+      case FK_ExplicitConstructor:
+        OS << "list copy initialization chose explicit constructor";
+        break;
+      }
+      OS << '\n';
     }
-    OS << '\n';
     return;
   }
 
Index: clang/lib/Sema/SemaCast.cpp
===================================================================
--- clang/lib/Sema/SemaCast.cpp
+++ clang/lib/Sema/SemaCast.cpp
@@ -427,21 +427,24 @@
     return false;
 
   InitializedEntity entity = InitializedEntity::InitializeTemporary(destType);
-  InitializationKind initKind
-    = (CT == CT_CStyle)? InitializationKind::CreateCStyleCast(range.getBegin(),
-                                                      range, listInitialization)
-    : (CT == CT_Functional)? InitializationKind::CreateFunctionalCast(range,
-                                                             listInitialization)
-    : InitializationKind::CreateCast(/*type range?*/ range);
+  InitializationKind initKind =
+      (CT == CT_CStyle) ? InitializationKind::CreateCStyleCast(
+                              range.getBegin(), range, listInitialization)
+      : (CT == CT_Functional)
+          ? InitializationKind::CreateFunctionalCast(range, listInitialization)
+          : InitializationKind::CreateCast(/*type range?*/ range);
   InitializationSequence sequence(S, entity, initKind, src);
 
   assert(sequence.Failed() && "initialization succeeded on second try?");
-  switch (sequence.getFailureKind()) {
-  default: return false;
+  for (auto Failure : sequence.getFailureKind()) {
+    switch (Failure) {
+    default:
+      return false;
 
-  case InitializationSequence::FK_ConstructorOverloadFailed:
-  case InitializationSequence::FK_UserConversionOverloadFailed:
-    break;
+    case InitializationSequence::FK_ConstructorOverloadFailed:
+    case InitializationSequence::FK_UserConversionOverloadFailed:
+      break;
+    }
   }
 
   OverloadCandidateSet &candidates = sequence.getFailedCandidateSet();
Index: clang/include/clang/Sema/Initialization.h
===================================================================
--- clang/include/clang/Sema/Initialization.h
+++ clang/include/clang/Sema/Initialization.h
@@ -1097,7 +1097,7 @@
 
 private:
   /// The reason why initialization failed.
-  FailureKind Failure;
+  SmallVector<FailureKind> Failures;
 
   /// The failed result of overload resolution.
   OverloadingResult FailedOverloadResult;
@@ -1358,7 +1358,7 @@
   /// Note that this initialization sequence failed.
   void SetFailed(FailureKind Failure) {
     SequenceKind = FailedSequence;
-    this->Failure = Failure;
+    this->Failures.push_back(Failure);
     assert((Failure != FK_Incomplete || !FailedIncompleteType.isNull()) &&
            "Incomplete type failure requires a type!");
   }
@@ -1387,9 +1387,9 @@
   }
 
   /// Determine why initialization failed.
-  FailureKind getFailureKind() const {
+  SmallVector<FailureKind> getFailureKind() const {
     assert(Failed() && "Not an initialization failure!");
-    return Failure;
+    return Failures;
   }
 
   /// Dump a representation of this initialization sequence to
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to