diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 034790d..f7c9649 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -5121,6 +5121,89 @@ bool Sema::ICEConvertDiagnoser::match(QualType T) {
                                  : T->isIntegralOrUnscopedEnumerationType();
 }
 
+static ExprResult diagnoseAmbiguousConversion(Sema &SemaRef, SourceLocation Loc, Expr *From,
+    Sema::ContextualImplicitConverter &Converter, QualType T,
+    UnresolvedSetImpl &ViableConversions) {
+
+  if (Converter.Suppress)
+    return ExprError();
+
+  Converter.diagnoseAmbiguous(SemaRef, Loc, T) << From->getSourceRange();
+  for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) {
+    CXXConversionDecl *Conv = cast < CXXConversionDecl
+        > (ViableConversions[I]->getUnderlyingDecl());
+    QualType ConvTy = Conv->getConversionType().getNonReferenceType();
+    Converter.noteAmbiguous(SemaRef, Conv, ConvTy);
+  }
+  return SemaRef.Owned(From);
+}
+
+static bool diagnoseNoViableConversion(Sema &SemaRef, SourceLocation Loc, Expr *&From,
+    Sema::ContextualImplicitConverter &Converter, QualType T,
+    bool HadMultipleCandidates, UnresolvedSetImpl &ExplicitConversions) {
+  if (ExplicitConversions.size() == 1 && !Converter.Suppress) {
+    DeclAccessPair Found = ExplicitConversions[0];
+    CXXConversionDecl *Conversion = cast < CXXConversionDecl
+        > (Found->getUnderlyingDecl());
+
+    // The user probably meant to invoke the given explicit
+    // conversion; use it.
+    QualType ConvTy = Conversion->getConversionType().getNonReferenceType();
+    std::string TypeStr;
+    ConvTy.getAsStringInternal(TypeStr, SemaRef.getPrintingPolicy());
+
+    Converter.diagnoseExplicitConv(SemaRef, Loc, T, ConvTy)
+        << FixItHint::CreateInsertion(From->getLocStart(),
+            "static_cast<" + TypeStr + ">(")
+        << FixItHint::CreateInsertion(
+            SemaRef.PP.getLocForEndOfToken(From->getLocEnd()), ")");
+    Converter.noteExplicitConv(SemaRef, Conversion, ConvTy);
+
+    // If we aren't in a SFINAE context, build a call to the
+    // explicit conversion function.
+    if (SemaRef.isSFINAEContext())
+      return true;
+
+    SemaRef.CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found);
+    ExprResult Result = SemaRef.BuildCXXMemberCallExpr(From, Found,
+        Conversion, HadMultipleCandidates);
+    if (Result.isInvalid())
+      return true;
+    // Record usage of conversion in an implicit cast.
+    From = ImplicitCastExpr::Create(SemaRef.Context, Result.get()->getType(),
+        CK_UserDefinedConversion, Result.get(), 0,
+        Result.get()->getValueKind());
+  }
+  return false;
+}
+
+static bool recordConversion(Sema &SemaRef, SourceLocation Loc, Expr *&From,
+    Sema::ContextualImplicitConverter &Converter, QualType T,
+    bool HadMultipleCandidates, DeclAccessPair &Found, QualType ToType) {
+
+  SemaRef.CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found);
+
+  CXXConversionDecl *Conversion = cast < CXXConversionDecl
+      > (Found->getUnderlyingDecl());
+  if (!Converter.SuppressConversion) {
+    if (SemaRef.isSFINAEContext())
+      return true;
+
+    Converter.diagnoseConversion(SemaRef, Loc, T, ToType)
+        << From->getSourceRange();
+  }
+
+  ExprResult Result = SemaRef.BuildCXXMemberCallExpr(From, Found, Conversion,
+      HadMultipleCandidates);
+  if (Result.isInvalid())
+    return true;
+  // Record usage of conversion in an implicit cast.
+  From = ImplicitCastExpr::Create(SemaRef.Context, Result.get()->getType(),
+      CK_UserDefinedConversion, Result.get(), 0,
+      Result.get()->getValueKind());
+  return false;
+}
+
 /// \brief Attempt to convert the given expression to a type which is accepted
 /// by the given converter.
 ///
@@ -5139,8 +5222,8 @@ bool Sema::ICEConvertDiagnoser::match(QualType T) {
 ///
 /// \returns The expression, converted to an integral or enumeration type if
 /// successful.
-ExprResult Sema::PerformContextualImplicitConversion(
-    SourceLocation Loc, Expr *From, ContextualImplicitConverter &Converter) {
+ExprResult Sema::PerformContextualImplicitConversion(SourceLocation Loc, Expr *From,
+    ContextualImplicitConverter &Converter) {
   // We can't perform any more checking for type-dependent expressions.
   if (From->isTypeDependent())
     return Owned(From);
@@ -5148,7 +5231,8 @@ ExprResult Sema::PerformContextualImplicitConversion(
   // Process placeholders immediately.
   if (From->hasPlaceholderType()) {
     ExprResult result = CheckPlaceholderExpr(From);
-    if (result.isInvalid()) return result;
+    if (result.isInvalid())
+      return result;
     From = result.take();
   }
 
@@ -5173,10 +5257,13 @@ ExprResult Sema::PerformContextualImplicitConversion(
     ContextualImplicitConverter &Converter;
     Expr *From;
 
-    TypeDiagnoserPartialDiag(ContextualImplicitConverter &Converter, Expr *From)
-        : TypeDiagnoser(Converter.Suppress), Converter(Converter), From(From) {}
+    TypeDiagnoserPartialDiag(ContextualImplicitConverter &Converter,
+        Expr *From)
+        : TypeDiagnoser(Converter.Suppress), Converter(Converter), From(From) {
+    }
 
-    virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {
+    virtual void
+    diagnose(Sema &S, SourceLocation Loc, QualType T) {
       Converter.diagnoseIncomplete(S, Loc, T) << From->getSourceRange();
     }
   } IncompleteDiagnoser(Converter, From);
@@ -5185,117 +5272,143 @@ ExprResult Sema::PerformContextualImplicitConversion(
     return Owned(From);
 
   // Look for a conversion to an integral or enumeration type.
-  UnresolvedSet<4> ViableConversions;
-  UnresolvedSet<4> ExplicitConversions;
-  std::pair<CXXRecordDecl::conversion_iterator,
-            CXXRecordDecl::conversion_iterator> Conversions
-    = cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions();
-
-  bool HadMultipleCandidates
-    = (std::distance(Conversions.first, Conversions.second) > 1);
-
-  for (CXXRecordDecl::conversion_iterator
-         I = Conversions.first, E = Conversions.second; I != E; ++I) {
-    if (CXXConversionDecl *Conversion
-          = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) {
-      if (Converter.match(
-              Conversion->getConversionType().getNonReferenceType())) {
+  UnresolvedSet < 4 > ViableConversions;
+  UnresolvedSet < 4 > ExplicitConversions;
+  std::pair < CXXRecordDecl::conversion_iterator, CXXRecordDecl::conversion_iterator
+      > Conversions = cast < CXXRecordDecl
+      > (RecordTy->getDecl())->getVisibleConversionFunctions();
+
+  bool HadMultipleCandidates = (std::distance(Conversions.first,
+      Conversions.second) > 1);
+
+  // To check that there is only one target type, in C++1y:
+  QualType ToType;
+  bool HasUniqueTargetType = true;
+
+  for (CXXRecordDecl::conversion_iterator I = Conversions.first, E =
+      Conversions.second; I != E; ++I) {
+    if (CXXConversionDecl * Conversion = dyn_cast < CXXConversionDecl
+        > ((*I)->getUnderlyingDecl())) {
+      QualType CurToType =
+          Conversion->getConversionType().getNonReferenceType();
+
+      if (Converter.match(CurToType)) {
         if (Conversion->isExplicit())
           ExplicitConversions.addDecl(I.getDecl(), I.getAccess());
-        else
+        else {
+          if (getLangOpts().CPlusPlus1y) {
+            if (ToType.isNull())
+              ToType = CurToType;
+            else if (HasUniqueTargetType) {
+              if (CurToType.getUnqualifiedType()
+                  != ToType.getUnqualifiedType())
+                HasUniqueTargetType = false;
+              else {
+                // Fixme: this assumes that both types will be equally restrict-qualified.
+                // The standard only considers cv qualifiers, not cvr.
+                if (ToType.isMoreQualifiedThan(CurToType))
+                  ToType = CurToType;
+              }
+            }
+          }
           ViableConversions.addDecl(I.getDecl(), I.getAccess());
+        }
       }
     }
   }
 
-  // FIXME: Implement the C++11 rules!
-  switch (ViableConversions.size()) {
-  case 0:
-    if (ExplicitConversions.size() == 1 && !Converter.Suppress) {
-      DeclAccessPair Found = ExplicitConversions[0];
-      CXXConversionDecl *Conversion
-        = cast<CXXConversionDecl>(Found->getUnderlyingDecl());
+  if (getLangOpts().CPlusPlus1y) {
+    // C++1y [conv]p6:
+    // ... An expression e of class type E appearing in such a context
+    // is said to be contextually implicitly converted to a specified
+    // type T and is well-formed if and only if e can be implicitly
+    // converted to a type T that is determined as follows: E is searched
+    // for conversion functions whose return type is cv T or reference
+    // to cv T such that T is allowed by the context. There shall be
+    // exactly one such T.
 
-      // The user probably meant to invoke the given explicit
-      // conversion; use it.
-      QualType ConvTy
-        = Conversion->getConversionType().getNonReferenceType();
-      std::string TypeStr;
-      ConvTy.getAsStringInternal(TypeStr, getPrintingPolicy());
+    if (!HasUniqueTargetType)
+      return diagnoseAmbiguousConversion(*this, Loc, From, Converter, T,
+          ViableConversions);
 
-      Converter.diagnoseExplicitConv(*this, Loc, T, ConvTy)
-        << FixItHint::CreateInsertion(From->getLocStart(),
-                                      "static_cast<" + TypeStr + ">(")
-        << FixItHint::CreateInsertion(PP.getLocForEndOfToken(From->getLocEnd()),
-                                      ")");
-      Converter.noteExplicitConv(*this, Conversion, ConvTy);
-
-      // If we aren't in a SFINAE context, build a call to the
-      // explicit conversion function.
-      if (isSFINAEContext())
-        return ExprError();
+    OverloadCandidateSet CandidateSet(Loc);
+    for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) {
+      DeclAccessPair FoundDecl = ViableConversions[I];
+      NamedDecl *D = FoundDecl.getDecl();
+      CXXRecordDecl *ActingContext = cast < CXXRecordDecl
+          > (D->getDeclContext());
+      if (isa < UsingShadowDecl > (D))
+        D = cast < UsingShadowDecl > (D)->getTargetDecl();
+
+      CXXConversionDecl *Conv;
+      FunctionTemplateDecl *ConvTemplate;
+      if ((ConvTemplate = dyn_cast < FunctionTemplateDecl > (D)))
+        Conv = cast < CXXConversionDecl > (ConvTemplate->getTemplatedDecl());
+      else
+        Conv = cast < CXXConversionDecl > (D);
 
-      CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found);
-      ExprResult Result = BuildCXXMemberCallExpr(From, Found, Conversion,
-                                                 HadMultipleCandidates);
-      if (Result.isInvalid())
-        return ExprError();
-      // Record usage of conversion in an implicit cast.
-      From = ImplicitCastExpr::Create(Context, Result.get()->getType(),
-                                      CK_UserDefinedConversion,
-                                      Result.get(), 0,
-                                      Result.get()->getValueKind());
+      if (ConvTemplate)
+        AddTemplateConversionCandidate(ConvTemplate, FoundDecl, ActingContext,
+            From, ToType, CandidateSet);
+      else
+        AddConversionCandidate(Conv, FoundDecl, ActingContext, From, ToType,
+            CandidateSet);
     }
 
-    // We'll complain below about a non-integral condition type.
-    break;
-
-  case 1: {
-    // Apply this conversion.
-    DeclAccessPair Found = ViableConversions[0];
-    CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found);
-
-    CXXConversionDecl *Conversion
-      = cast<CXXConversionDecl>(Found->getUnderlyingDecl());
-    QualType ConvTy
-      = Conversion->getConversionType().getNonReferenceType();
-    if (!Converter.SuppressConversion) {
-      if (isSFINAEContext())
+    OverloadCandidateSet::iterator Best;
+    switch (CandidateSet.BestViableFunction(*this, Loc, Best)) {
+    case OR_Success: {
+      // Apply this conversion.
+      DeclAccessPair Found = Best->FoundDecl;
+      if (recordConversion(*this, Loc, From, Converter, T,
+          HadMultipleCandidates, Found, ToType))
         return ExprError();
-
-      Converter.diagnoseConversion(*this, Loc, T, ConvTy)
-        << From->getSourceRange();
+      break;
+    }
+    case OR_Ambiguous:
+      return diagnoseAmbiguousConversion(*this, Loc, From, Converter, T,
+          ViableConversions);
+    case OR_No_Viable_Function:
+      if (diagnoseNoViableConversion(*this, Loc, From, Converter, T,
+          HadMultipleCandidates, ExplicitConversions))
+        return ExprError();
+      // fall through 'OR_Deleted' case.
+    case OR_Deleted:
+      // We'll complain below about a non-integral condition type.
+      break;
     }
-
-    ExprResult Result = BuildCXXMemberCallExpr(From, Found, Conversion,
-                                               HadMultipleCandidates);
-    if (Result.isInvalid())
-      return ExprError();
-    // Record usage of conversion in an implicit cast.
-    From = ImplicitCastExpr::Create(Context, Result.get()->getType(),
-                                    CK_UserDefinedConversion,
-                                    Result.get(), 0,
-                                    Result.get()->getValueKind());
-    break;
   }
+  else {
+    switch (ViableConversions.size()) {
+    case 0: {
+      if (diagnoseNoViableConversion(*this, Loc, From, Converter, T,
+          HadMultipleCandidates, ExplicitConversions))
+        return ExprError();
 
-  default:
-    if (Converter.Suppress)
-      return ExprError();
+      // We'll complain below about a non-integral condition type.
+      break;
+    }
+    case 1: {
+      // Apply this conversion.
+      DeclAccessPair Found = ViableConversions[0];
+      CXXConversionDecl *Conversion = cast < CXXConversionDecl
+          > (Found->getUnderlyingDecl());
+      QualType ConvTy = Conversion->getConversionType().getNonReferenceType();
 
-    Converter.diagnoseAmbiguous(*this, Loc, T) << From->getSourceRange();
-    for (unsigned I = 0, N = ViableConversions.size(); I != N; ++I) {
-      CXXConversionDecl *Conv
-        = cast<CXXConversionDecl>(ViableConversions[I]->getUnderlyingDecl());
-      QualType ConvTy = Conv->getConversionType().getNonReferenceType();
-      Converter.noteAmbiguous(*this, Conv, ConvTy);
+      if (recordConversion(*this, Loc, From, Converter, T,
+          HadMultipleCandidates, Found, ConvTy))
+        return ExprError();
+      break;
+    }
+    default:
+      return diagnoseAmbiguousConversion(*this, Loc, From, Converter, T,
+          ViableConversions);
     }
-    return Owned(From);
   }
 
   if (!Converter.match(From->getType()) && !Converter.Suppress)
     Converter.diagnoseNoMatch(*this, Loc, From->getType())
-      << From->getSourceRange();
+        << From->getSourceRange();
 
   return DefaultLvalueConversion(From);
 }
diff --git a/test/SemaCXX/cxx1y-contextual-conversion-tweaks.cpp b/test/SemaCXX/cxx1y-contextual-conversion-tweaks.cpp
new file mode 100644
index 0000000..54bd10a
--- /dev/null
+++ b/test/SemaCXX/cxx1y-contextual-conversion-tweaks.cpp
@@ -0,0 +1,46 @@
+// RUN: %clang_cc1 -std=c++11 -verify -fsyntax-only %s
+// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only %s -DCXX1Y
+
+namespace n3323_example {
+  template< class T>
+  class zero_init {
+  public:
+    zero_init() : val(static_cast<T>(0)) { }
+    zero_init(T val) : val( val) { }
+
+    operator T & () { return val; }     //@11
+    operator T () const { return val; } //@12
+
+  private:
+    T val;
+  };
+
+  void Delete() {
+    zero_init<int*> p;
+    p = new int(7);
+    delete p;     //@21
+    delete (p+0);
+    delete +p;
+  }
+
+  void Switch() {
+    zero_init<int> i;
+    i = 7;
+    switch (i) { }  // @29
+    switch (i+0) { }
+    switch (+i) { }
+  }
+}
+
+// FIXME: Extend with [expr.const] and [expr.new] example.
+
+#ifdef CXX1Y
+// expected-no-diagnostics
+#else
+// expected-error@21 {{ambiguous conversion of delete expression of type 'zero_init<int *>' to a pointer}}
+// expected-note@11 {{conversion to pointer type 'int *'}}
+// expected-note@12 {{conversion to pointer type 'int *'}}
+// expected-error@29 {{multiple conversions from switch condition type 'zero_init<int>' to an integral or enumeration type}}
+// expected-note@11 {{conversion to integral type 'int'}}
+// expected-note@12 {{conversion to integral type 'int'}}
+#endif
