]> granicus.if.org Git - clang/commitdiff
Refactor and simplify the computation of implicit conversion sequences
authorDouglas Gregor <dgregor@apple.com>
Tue, 13 Apr 2010 16:31:36 +0000 (16:31 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 13 Apr 2010 16:31:36 +0000 (16:31 +0000)
for reference binding. The code attempted to handle both the
computation of the ICS and the actual conversion, but the latter is an
anachronism: we now use InitializationSequence for that.

Sema::CheckReferenceInit is now a static function TryReferenceInit
that's only use within overload resolution, and has been simplified
slightly. It still needs to be updated per C++ [over.ics.ref], by
eliminating more of the lvalue/rvalue checks.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@101136 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/Sema.h
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaOverload.cpp

index 51105153666c0b89c5580747d7a0ef05cd8ac4ad..0b42e8dba1ee8ff854d642a00bc7c158e6161d5a 100644 (file)
@@ -4182,14 +4182,6 @@ public:
                                                       QualType T1, QualType T2,
                                                       bool& DerivedToBase);
 
-  bool CheckReferenceInit(Expr *&simpleInit_or_initList, QualType declType,
-                          SourceLocation DeclLoc,
-                          bool SuppressUserConversions,
-                          bool AllowExplicit,
-                          bool ForceRValue,
-                          ImplicitConversionSequence *ICS = 0,
-                          bool IgnoreBaseAccess = false);
-
   /// CheckCastTypes - Check type constraints for casting between types under
   /// C semantics, or forward to CXXCheckCStyleCast in C++.
   bool CheckCastTypes(SourceRange TyRange, QualType CastTy, Expr *&CastExpr,
index cc83e65b36a7842fa2238fb69e33a808fe82f093..214d57c7dce338f39330cf642d9b11ad2d011e28 100644 (file)
@@ -4388,474 +4388,6 @@ Sema::CompleteConstructorCall(CXXConstructorDecl *Constructor,
   return Invalid;
 }
 
-/// CompareReferenceRelationship - Compare the two types T1 and T2 to
-/// determine whether they are reference-related,
-/// reference-compatible, reference-compatible with added
-/// qualification, or incompatible, for use in C++ initialization by
-/// reference (C++ [dcl.ref.init]p4). Neither type can be a reference
-/// type, and the first type (T1) is the pointee type of the reference
-/// type being initialized.
-Sema::ReferenceCompareResult
-Sema::CompareReferenceRelationship(SourceLocation Loc,
-                                   QualType OrigT1, QualType OrigT2,
-                                   bool& DerivedToBase) {
-  assert(!OrigT1->isReferenceType() &&
-    "T1 must be the pointee type of the reference type");
-  assert(!OrigT2->isReferenceType() && "T2 cannot be a reference type");
-
-  QualType T1 = Context.getCanonicalType(OrigT1);
-  QualType T2 = Context.getCanonicalType(OrigT2);
-  Qualifiers T1Quals, T2Quals;
-  QualType UnqualT1 = Context.getUnqualifiedArrayType(T1, T1Quals);
-  QualType UnqualT2 = Context.getUnqualifiedArrayType(T2, T2Quals);
-
-  // C++ [dcl.init.ref]p4:
-  //   Given types "cv1 T1" and "cv2 T2," "cv1 T1" is
-  //   reference-related to "cv2 T2" if T1 is the same type as T2, or
-  //   T1 is a base class of T2.
-  if (UnqualT1 == UnqualT2)
-    DerivedToBase = false;
-  else if (!RequireCompleteType(Loc, OrigT1, PDiag()) &&
-           !RequireCompleteType(Loc, OrigT2, PDiag()) &&
-           IsDerivedFrom(UnqualT2, UnqualT1))
-    DerivedToBase = true;
-  else
-    return Ref_Incompatible;
-
-  // At this point, we know that T1 and T2 are reference-related (at
-  // least).
-
-  // If the type is an array type, promote the element qualifiers to the type
-  // for comparison.
-  if (isa<ArrayType>(T1) && T1Quals)
-    T1 = Context.getQualifiedType(UnqualT1, T1Quals);
-  if (isa<ArrayType>(T2) && T2Quals)
-    T2 = Context.getQualifiedType(UnqualT2, T2Quals);
-
-  // C++ [dcl.init.ref]p4:
-  //   "cv1 T1" is reference-compatible with "cv2 T2" if T1 is
-  //   reference-related to T2 and cv1 is the same cv-qualification
-  //   as, or greater cv-qualification than, cv2. For purposes of
-  //   overload resolution, cases for which cv1 is greater
-  //   cv-qualification than cv2 are identified as
-  //   reference-compatible with added qualification (see 13.3.3.2).
-  if (T1Quals.getCVRQualifiers() == T2Quals.getCVRQualifiers())
-    return Ref_Compatible;
-  else if (T1.isMoreQualifiedThan(T2))
-    return Ref_Compatible_With_Added_Qualification;
-  else
-    return Ref_Related;
-}
-
-/// CheckReferenceInit - Check the initialization of a reference
-/// variable with the given initializer (C++ [dcl.init.ref]). Init is
-/// the initializer (either a simple initializer or an initializer
-/// list), and DeclType is the type of the declaration. When ICS is
-/// non-null, this routine will compute the implicit conversion
-/// sequence according to C++ [over.ics.ref] and will not produce any
-/// diagnostics; when ICS is null, it will emit diagnostics when any
-/// errors are found. Either way, a return value of true indicates
-/// that there was a failure, a return value of false indicates that
-/// the reference initialization succeeded.
-///
-/// When @p SuppressUserConversions, user-defined conversions are
-/// suppressed.
-/// When @p AllowExplicit, we also permit explicit user-defined
-/// conversion functions.
-/// When @p ForceRValue, we unconditionally treat the initializer as an rvalue.
-/// When @p IgnoreBaseAccess, we don't do access control on to-base conversion.
-/// This is used when this is called from a C-style cast.
-bool
-Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
-                         SourceLocation DeclLoc,
-                         bool SuppressUserConversions,
-                         bool AllowExplicit, bool ForceRValue,
-                         ImplicitConversionSequence *ICS,
-                         bool IgnoreBaseAccess) {
-  assert(DeclType->isReferenceType() && "Reference init needs a reference");
-
-  QualType T1 = DeclType->getAs<ReferenceType>()->getPointeeType();
-  QualType T2 = Init->getType();
-
-  // If the initializer is the address of an overloaded function, try
-  // to resolve the overloaded function. If all goes well, T2 is the
-  // type of the resulting function.
-  if (Context.getCanonicalType(T2) == Context.OverloadTy) {
-    DeclAccessPair Found;
-    FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Init, DeclType,
-                                                          ICS != 0, Found);
-    if (Fn) {
-      // Since we're performing this reference-initialization for
-      // real, update the initializer with the resulting function.
-      if (!ICS) {
-        if (DiagnoseUseOfDecl(Fn, DeclLoc))
-          return true;
-
-        CheckAddressOfMemberAccess(Init, Found);
-        Init = FixOverloadedFunctionReference(Init, Found, Fn);
-      }
-
-      T2 = Fn->getType();
-    }
-  }
-
-  // Compute some basic properties of the types and the initializer.
-  bool isRValRef = DeclType->isRValueReferenceType();
-  bool DerivedToBase = false;
-  Expr::isLvalueResult InitLvalue = ForceRValue ? Expr::LV_InvalidExpression :
-                                                  Init->isLvalue(Context);
-  ReferenceCompareResult RefRelationship
-    = CompareReferenceRelationship(DeclLoc, T1, T2, DerivedToBase);
-
-  // Most paths end in a failed conversion.
-  if (ICS) {
-    ICS->setBad(BadConversionSequence::no_conversion, Init, DeclType);
-  }
-
-  // C++ [dcl.init.ref]p5:
-  //   A reference to type "cv1 T1" is initialized by an expression
-  //   of type "cv2 T2" as follows:
-
-  //     -- If the initializer expression
-
-  // Rvalue references cannot bind to lvalues (N2812).
-  // There is absolutely no situation where they can. In particular, note that
-  // this is ill-formed, even if B has a user-defined conversion to A&&:
-  //   B b;
-  //   A&& r = b;
-  if (isRValRef && InitLvalue == Expr::LV_Valid) {
-    if (!ICS)
-      Diag(DeclLoc, diag::err_lvalue_to_rvalue_ref)
-        << Init->getSourceRange();
-    return true;
-  }
-
-  bool BindsDirectly = false;
-  //       -- is an lvalue (but is not a bit-field), and "cv1 T1" is
-  //          reference-compatible with "cv2 T2," or
-  //
-  // Note that the bit-field check is skipped if we are just computing
-  // the implicit conversion sequence (C++ [over.best.ics]p2).
-  if (InitLvalue == Expr::LV_Valid && (ICS || !Init->getBitField()) &&
-      RefRelationship >= Ref_Compatible_With_Added_Qualification) {
-    BindsDirectly = true;
-
-    if (ICS) {
-      // C++ [over.ics.ref]p1:
-      //   When a parameter of reference type binds directly (8.5.3)
-      //   to an argument expression, the implicit conversion sequence
-      //   is the identity conversion, unless the argument expression
-      //   has a type that is a derived class of the parameter type,
-      //   in which case the implicit conversion sequence is a
-      //   derived-to-base Conversion (13.3.3.1).
-      ICS->setStandard();
-      ICS->Standard.First = ICK_Identity;
-      ICS->Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity;
-      ICS->Standard.Third = ICK_Identity;
-      ICS->Standard.FromTypePtr = T2.getAsOpaquePtr();
-      ICS->Standard.setToType(0, T2);
-      ICS->Standard.setToType(1, T1);
-      ICS->Standard.setToType(2, T1);
-      ICS->Standard.ReferenceBinding = true;
-      ICS->Standard.DirectBinding = true;
-      ICS->Standard.RRefBinding = false;
-      ICS->Standard.CopyConstructor = 0;
-
-      // Nothing more to do: the inaccessibility/ambiguity check for
-      // derived-to-base conversions is suppressed when we're
-      // computing the implicit conversion sequence (C++
-      // [over.best.ics]p2).
-      return false;
-    } else {
-      // Perform the conversion.
-      CastExpr::CastKind CK = CastExpr::CK_NoOp;
-      if (DerivedToBase)
-        CK = CastExpr::CK_DerivedToBase;
-      else if(CheckExceptionSpecCompatibility(Init, T1))
-        return true;
-      ImpCastExprToType(Init, T1, CK, /*isLvalue=*/true);
-    }
-  }
-
-  //       -- has a class type (i.e., T2 is a class type), where T1 is
-  //          not reference-related to T2, and can be implicitly
-  //          converted to an lvalue of type "cv3 T3," where "cv1 T1"
-  //          is reference-compatible with "cv3 T3" 92) (this
-  //          conversion is selected by enumerating the applicable
-  //          conversion functions (13.3.1.6) and choosing the best
-  //          one through overload resolution (13.3)),
-  if (!isRValRef && !SuppressUserConversions && T2->isRecordType() &&
-      !RequireCompleteType(DeclLoc, T2, 0) && 
-      RefRelationship == Ref_Incompatible) {
-    CXXRecordDecl *T2RecordDecl
-      = dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl());
-
-    OverloadCandidateSet CandidateSet(DeclLoc);
-    const UnresolvedSetImpl *Conversions
-      = T2RecordDecl->getVisibleConversionFunctions();
-    for (UnresolvedSetImpl::iterator I = Conversions->begin(),
-           E = Conversions->end(); I != E; ++I) {
-      NamedDecl *D = *I;
-      CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
-      if (isa<UsingShadowDecl>(D))
-        D = cast<UsingShadowDecl>(D)->getTargetDecl();
-
-      FunctionTemplateDecl *ConvTemplate
-        = dyn_cast<FunctionTemplateDecl>(D);
-      CXXConversionDecl *Conv;
-      if (ConvTemplate)
-        Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
-      else
-        Conv = cast<CXXConversionDecl>(D);
-      
-      // If the conversion function doesn't return a reference type,
-      // it can't be considered for this conversion.
-      if (Conv->getConversionType()->isLValueReferenceType() &&
-          (AllowExplicit || !Conv->isExplicit())) {
-        if (ConvTemplate)
-          AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC,
-                                         Init, DeclType, CandidateSet);
-        else
-          AddConversionCandidate(Conv, I.getPair(), ActingDC, Init,
-                                 DeclType, CandidateSet);
-      }
-    }
-
-    OverloadCandidateSet::iterator Best;
-    switch (BestViableFunction(CandidateSet, DeclLoc, Best)) {
-    case OR_Success:
-      // C++ [over.ics.ref]p1:
-      //
-      //   [...] If the parameter binds directly to the result of
-      //   applying a conversion function to the argument
-      //   expression, the implicit conversion sequence is a
-      //   user-defined conversion sequence (13.3.3.1.2), with the
-      //   second standard conversion sequence either an identity
-      //   conversion or, if the conversion function returns an
-      //   entity of a type that is a derived class of the parameter
-      //   type, a derived-to-base Conversion.
-      if (!Best->FinalConversion.DirectBinding)
-        break;
-
-      // This is a direct binding.
-      BindsDirectly = true;
-
-      if (ICS) {
-        ICS->setUserDefined();
-        ICS->UserDefined.Before = Best->Conversions[0].Standard;
-        ICS->UserDefined.After = Best->FinalConversion;
-        ICS->UserDefined.ConversionFunction = Best->Function;
-        ICS->UserDefined.EllipsisConversion = false;
-        assert(ICS->UserDefined.After.ReferenceBinding &&
-               ICS->UserDefined.After.DirectBinding &&
-               "Expected a direct reference binding!");
-        return false;
-      } else {
-        OwningExprResult InitConversion =
-          BuildCXXCastArgument(DeclLoc, QualType(),
-                               CastExpr::CK_UserDefinedConversion,
-                               cast<CXXMethodDecl>(Best->Function), 
-                               Owned(Init));
-        Init = InitConversion.takeAs<Expr>();
-
-        if (CheckExceptionSpecCompatibility(Init, T1))
-          return true;
-        ImpCastExprToType(Init, T1, CastExpr::CK_UserDefinedConversion, 
-                          /*isLvalue=*/true);
-      }
-      break;
-
-    case OR_Ambiguous:
-      if (ICS) {
-        ICS->setAmbiguous();
-        for (OverloadCandidateSet::iterator Cand = CandidateSet.begin();
-             Cand != CandidateSet.end(); ++Cand)
-          if (Cand->Viable)
-            ICS->Ambiguous.addConversion(Cand->Function);
-        break;
-      }
-      Diag(DeclLoc, diag::err_ref_init_ambiguous) << DeclType << Init->getType()
-            << Init->getSourceRange();
-      PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates, &Init, 1);
-      return true;
-
-    case OR_No_Viable_Function:
-    case OR_Deleted:
-      // There was no suitable conversion, or we found a deleted
-      // conversion; continue with other checks.
-      break;
-    }
-  }
-
-  if (BindsDirectly) {
-    // C++ [dcl.init.ref]p4:
-    //   [...] In all cases where the reference-related or
-    //   reference-compatible relationship of two types is used to
-    //   establish the validity of a reference binding, and T1 is a
-    //   base class of T2, a program that necessitates such a binding
-    //   is ill-formed if T1 is an inaccessible (clause 11) or
-    //   ambiguous (10.2) base class of T2.
-    //
-    // Note that we only check this condition when we're allowed to
-    // complain about errors, because we should not be checking for
-    // ambiguity (or inaccessibility) unless the reference binding
-    // actually happens.
-    if (DerivedToBase)
-      return CheckDerivedToBaseConversion(T2, T1, DeclLoc,
-                                          Init->getSourceRange(),
-                                          IgnoreBaseAccess);
-    else
-      return false;
-  }
-
-  //     -- Otherwise, the reference shall be to a non-volatile const
-  //        type (i.e., cv1 shall be const), or the reference shall be an
-  //        rvalue reference and the initializer expression shall be an rvalue.
-  if (!isRValRef && T1.getCVRQualifiers() != Qualifiers::Const) {
-    if (!ICS)
-      Diag(DeclLoc, diag::err_not_reference_to_const_init)
-        << T1.isVolatileQualified()
-        << T1 << int(InitLvalue != Expr::LV_Valid)
-        << T2 << Init->getSourceRange();
-    return true;
-  }
-
-  //       -- If the initializer expression is an rvalue, with T2 a
-  //          class type, and "cv1 T1" is reference-compatible with
-  //          "cv2 T2," the reference is bound in one of the
-  //          following ways (the choice is implementation-defined):
-  //
-  //          -- The reference is bound to the object represented by
-  //             the rvalue (see 3.10) or to a sub-object within that
-  //             object.
-  //
-  //          -- A temporary of type "cv1 T2" [sic] is created, and
-  //             a constructor is called to copy the entire rvalue
-  //             object into the temporary. The reference is bound to
-  //             the temporary or to a sub-object within the
-  //             temporary.
-  //
-  //          The constructor that would be used to make the copy
-  //          shall be callable whether or not the copy is actually
-  //          done.
-  //
-  // Note that C++0x [dcl.init.ref]p5 takes away this implementation
-  // freedom, so we will always take the first option and never build
-  // a temporary in this case. FIXME: We will, however, have to check
-  // for the presence of a copy constructor in C++98/03 mode.
-  if (InitLvalue != Expr::LV_Valid && T2->isRecordType() &&
-      RefRelationship >= Ref_Compatible_With_Added_Qualification) {
-    if (ICS) {
-      ICS->setStandard();
-      ICS->Standard.First = ICK_Identity;
-      ICS->Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity;
-      ICS->Standard.Third = ICK_Identity;
-      ICS->Standard.FromTypePtr = T2.getAsOpaquePtr();
-      ICS->Standard.setToType(0, T2);
-      ICS->Standard.setToType(1, T1);
-      ICS->Standard.setToType(2, T1);
-      ICS->Standard.ReferenceBinding = true;
-      ICS->Standard.DirectBinding = false;
-      ICS->Standard.RRefBinding = isRValRef;
-      ICS->Standard.CopyConstructor = 0;
-    } else {
-      CastExpr::CastKind CK = CastExpr::CK_NoOp;
-      if (DerivedToBase)
-        CK = CastExpr::CK_DerivedToBase;
-      else if(CheckExceptionSpecCompatibility(Init, T1))
-        return true;
-      ImpCastExprToType(Init, T1, CK, /*isLvalue=*/false);
-    }
-    return false;
-  }
-
-  //       -- Otherwise, a temporary of type "cv1 T1" is created and
-  //          initialized from the initializer expression using the
-  //          rules for a non-reference copy initialization (8.5). The
-  //          reference is then bound to the temporary. If T1 is
-  //          reference-related to T2, cv1 must be the same
-  //          cv-qualification as, or greater cv-qualification than,
-  //          cv2; otherwise, the program is ill-formed.
-  if (RefRelationship == Ref_Related) {
-    // If cv1 == cv2 or cv1 is a greater cv-qualified than cv2, then
-    // we would be reference-compatible or reference-compatible with
-    // added qualification. But that wasn't the case, so the reference
-    // initialization fails.
-    if (!ICS)
-      Diag(DeclLoc, diag::err_reference_init_drops_quals)
-        << T1 << int(InitLvalue != Expr::LV_Valid)
-        << T2 << Init->getSourceRange();
-    return true;
-  }
-
-  // If at least one of the types is a class type, the types are not
-  // related, and we aren't allowed any user conversions, the
-  // reference binding fails. This case is important for breaking
-  // recursion, since TryImplicitConversion below will attempt to
-  // create a temporary through the use of a copy constructor.
-  if (SuppressUserConversions && RefRelationship == Ref_Incompatible &&
-      (T1->isRecordType() || T2->isRecordType())) {
-    if (!ICS)
-      Diag(DeclLoc, diag::err_typecheck_convert_incompatible)
-        << DeclType << Init->getType() << AA_Initializing << Init->getSourceRange();
-    return true;
-  }
-
-  // Actually try to convert the initializer to T1.
-  if (ICS) {
-    // C++ [over.ics.ref]p2:
-    //
-    //   When a parameter of reference type is not bound directly to
-    //   an argument expression, the conversion sequence is the one
-    //   required to convert the argument expression to the
-    //   underlying type of the reference according to
-    //   13.3.3.1. Conceptually, this conversion sequence corresponds
-    //   to copy-initializing a temporary of the underlying type with
-    //   the argument expression. Any difference in top-level
-    //   cv-qualification is subsumed by the initialization itself
-    //   and does not constitute a conversion.
-    *ICS = TryImplicitConversion(Init, T1, SuppressUserConversions,
-                                 /*AllowExplicit=*/false,
-                                 /*ForceRValue=*/false,
-                                 /*InOverloadResolution=*/false);
-
-    // Of course, that's still a reference binding.
-    if (ICS->isStandard()) {
-      ICS->Standard.ReferenceBinding = true;
-      ICS->Standard.RRefBinding = isRValRef;
-    } else if (ICS->isUserDefined()) {
-      ICS->UserDefined.After.ReferenceBinding = true;
-      ICS->UserDefined.After.RRefBinding = isRValRef;
-    }
-    return ICS->isBad();
-  } else {
-    ImplicitConversionSequence Conversions;
-    bool badConversion = PerformImplicitConversion(Init, T1, AA_Initializing, 
-                                                   false, false, 
-                                                   Conversions);
-    if (badConversion) {
-      if (Conversions.isAmbiguous()) {
-        Diag(DeclLoc, 
-             diag::err_lvalue_to_rvalue_ambig_ref) << Init->getSourceRange();
-        for (int j = Conversions.Ambiguous.conversions().size()-1; 
-             j >= 0; j--) {
-          FunctionDecl *Func = Conversions.Ambiguous.conversions()[j];
-          NoteOverloadCandidate(Func);
-        }
-      }
-      else {
-        if (isRValRef)
-          Diag(DeclLoc, diag::err_lvalue_to_rvalue_ref) 
-            << Init->getSourceRange();
-        else
-          Diag(DeclLoc, diag::err_invalid_initialization)
-            << DeclType << Init->getType() << Init->getSourceRange();
-      }
-    }
-    return badConversion;
-  }
-}
-
 static inline bool
 CheckOperatorNewDeleteDeclarationScope(Sema &SemaRef, 
                                        const FunctionDecl *FnDecl) {
index 40d48e3cc6c5868367e2b50836b936dca079b995..c3d2e64f7bf79a75b4891710270419fbb75e5ac6 100644 (file)
@@ -2174,6 +2174,328 @@ Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1,
   return ImplicitConversionSequence::Indistinguishable;
 }
 
+/// CompareReferenceRelationship - Compare the two types T1 and T2 to
+/// determine whether they are reference-related,
+/// reference-compatible, reference-compatible with added
+/// qualification, or incompatible, for use in C++ initialization by
+/// reference (C++ [dcl.ref.init]p4). Neither type can be a reference
+/// type, and the first type (T1) is the pointee type of the reference
+/// type being initialized.
+Sema::ReferenceCompareResult
+Sema::CompareReferenceRelationship(SourceLocation Loc,
+                                   QualType OrigT1, QualType OrigT2,
+                                   bool& DerivedToBase) {
+  assert(!OrigT1->isReferenceType() &&
+    "T1 must be the pointee type of the reference type");
+  assert(!OrigT2->isReferenceType() && "T2 cannot be a reference type");
+
+  QualType T1 = Context.getCanonicalType(OrigT1);
+  QualType T2 = Context.getCanonicalType(OrigT2);
+  Qualifiers T1Quals, T2Quals;
+  QualType UnqualT1 = Context.getUnqualifiedArrayType(T1, T1Quals);
+  QualType UnqualT2 = Context.getUnqualifiedArrayType(T2, T2Quals);
+
+  // C++ [dcl.init.ref]p4:
+  //   Given types "cv1 T1" and "cv2 T2," "cv1 T1" is
+  //   reference-related to "cv2 T2" if T1 is the same type as T2, or
+  //   T1 is a base class of T2.
+  if (UnqualT1 == UnqualT2)
+    DerivedToBase = false;
+  else if (!RequireCompleteType(Loc, OrigT1, PDiag()) &&
+           !RequireCompleteType(Loc, OrigT2, PDiag()) &&
+           IsDerivedFrom(UnqualT2, UnqualT1))
+    DerivedToBase = true;
+  else
+    return Ref_Incompatible;
+
+  // At this point, we know that T1 and T2 are reference-related (at
+  // least).
+
+  // If the type is an array type, promote the element qualifiers to the type
+  // for comparison.
+  if (isa<ArrayType>(T1) && T1Quals)
+    T1 = Context.getQualifiedType(UnqualT1, T1Quals);
+  if (isa<ArrayType>(T2) && T2Quals)
+    T2 = Context.getQualifiedType(UnqualT2, T2Quals);
+
+  // C++ [dcl.init.ref]p4:
+  //   "cv1 T1" is reference-compatible with "cv2 T2" if T1 is
+  //   reference-related to T2 and cv1 is the same cv-qualification
+  //   as, or greater cv-qualification than, cv2. For purposes of
+  //   overload resolution, cases for which cv1 is greater
+  //   cv-qualification than cv2 are identified as
+  //   reference-compatible with added qualification (see 13.3.3.2).
+  if (T1Quals.getCVRQualifiers() == T2Quals.getCVRQualifiers())
+    return Ref_Compatible;
+  else if (T1.isMoreQualifiedThan(T2))
+    return Ref_Compatible_With_Added_Qualification;
+  else
+    return Ref_Related;
+}
+
+/// \brief Compute an implicit conversion sequence for reference
+/// initialization.
+static ImplicitConversionSequence
+TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType,
+                 SourceLocation DeclLoc,
+                 bool SuppressUserConversions,
+                 bool AllowExplicit, bool ForceRValue) {
+  assert(DeclType->isReferenceType() && "Reference init needs a reference");
+
+  // Most paths end in a failed conversion.
+  ImplicitConversionSequence ICS;
+  ICS.setBad(BadConversionSequence::no_conversion, Init, DeclType);
+
+  QualType T1 = DeclType->getAs<ReferenceType>()->getPointeeType();
+  QualType T2 = Init->getType();
+
+  // If the initializer is the address of an overloaded function, try
+  // to resolve the overloaded function. If all goes well, T2 is the
+  // type of the resulting function.
+  if (S.Context.getCanonicalType(T2) == S.Context.OverloadTy) {
+    DeclAccessPair Found;
+    if (FunctionDecl *Fn = S.ResolveAddressOfOverloadedFunction(Init, DeclType,
+                                                                false, Found))
+      T2 = Fn->getType();
+  }
+
+  // Compute some basic properties of the types and the initializer.
+  bool isRValRef = DeclType->isRValueReferenceType();
+  bool DerivedToBase = false;
+  Expr::isLvalueResult InitLvalue = ForceRValue ? Expr::LV_InvalidExpression :
+                                                  Init->isLvalue(S.Context);
+  Sema::ReferenceCompareResult RefRelationship
+    = S.CompareReferenceRelationship(DeclLoc, T1, T2, DerivedToBase);
+
+  // C++ [dcl.init.ref]p5:
+  //   A reference to type "cv1 T1" is initialized by an expression
+  //   of type "cv2 T2" as follows:
+
+  //     -- If the initializer expression
+
+  // C++ [over.ics.ref]p3:
+  //   Except for an implicit object parameter, for which see 13.3.1,
+  //   a standard conversion sequence cannot be formed if it requires
+  //   binding an lvalue reference to non-const to an rvalue or
+  //   binding an rvalue reference to an lvalue.
+  if (isRValRef && InitLvalue == Expr::LV_Valid)
+    return ICS;
+
+  //       -- is an lvalue (but is not a bit-field), and "cv1 T1" is
+  //          reference-compatible with "cv2 T2," or
+  //
+  // Per C++ [over.ics.ref]p4, we don't check the bit-field property here.
+  if (InitLvalue == Expr::LV_Valid &&
+      RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) {
+    // C++ [over.ics.ref]p1:
+    //   When a parameter of reference type binds directly (8.5.3)
+    //   to an argument expression, the implicit conversion sequence
+    //   is the identity conversion, unless the argument expression
+    //   has a type that is a derived class of the parameter type,
+    //   in which case the implicit conversion sequence is a
+    //   derived-to-base Conversion (13.3.3.1).
+    ICS.setStandard();
+    ICS.Standard.First = ICK_Identity;
+    ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity;
+    ICS.Standard.Third = ICK_Identity;
+    ICS.Standard.FromTypePtr = T2.getAsOpaquePtr();
+    ICS.Standard.setToType(0, T2);
+    ICS.Standard.setToType(1, T1);
+    ICS.Standard.setToType(2, T1);
+    ICS.Standard.ReferenceBinding = true;
+    ICS.Standard.DirectBinding = true;
+    ICS.Standard.RRefBinding = false;
+    ICS.Standard.CopyConstructor = 0;
+
+    // Nothing more to do: the inaccessibility/ambiguity check for
+    // derived-to-base conversions is suppressed when we're
+    // computing the implicit conversion sequence (C++
+    // [over.best.ics]p2).
+    return ICS;
+  }
+
+  //       -- has a class type (i.e., T2 is a class type), where T1 is
+  //          not reference-related to T2, and can be implicitly
+  //          converted to an lvalue of type "cv3 T3," where "cv1 T1"
+  //          is reference-compatible with "cv3 T3" 92) (this
+  //          conversion is selected by enumerating the applicable
+  //          conversion functions (13.3.1.6) and choosing the best
+  //          one through overload resolution (13.3)),
+  if (!isRValRef && !SuppressUserConversions && T2->isRecordType() &&
+      !S.RequireCompleteType(DeclLoc, T2, 0) && 
+      RefRelationship == Sema::Ref_Incompatible) {
+    CXXRecordDecl *T2RecordDecl
+      = dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl());
+
+    OverloadCandidateSet CandidateSet(DeclLoc);
+    const UnresolvedSetImpl *Conversions
+      = T2RecordDecl->getVisibleConversionFunctions();
+    for (UnresolvedSetImpl::iterator I = Conversions->begin(),
+           E = Conversions->end(); I != E; ++I) {
+      NamedDecl *D = *I;
+      CXXRecordDecl *ActingDC = cast<CXXRecordDecl>(D->getDeclContext());
+      if (isa<UsingShadowDecl>(D))
+        D = cast<UsingShadowDecl>(D)->getTargetDecl();
+
+      FunctionTemplateDecl *ConvTemplate
+        = dyn_cast<FunctionTemplateDecl>(D);
+      CXXConversionDecl *Conv;
+      if (ConvTemplate)
+        Conv = cast<CXXConversionDecl>(ConvTemplate->getTemplatedDecl());
+      else
+        Conv = cast<CXXConversionDecl>(D);
+      
+      // If the conversion function doesn't return a reference type,
+      // it can't be considered for this conversion.
+      if (Conv->getConversionType()->isLValueReferenceType() &&
+          (AllowExplicit || !Conv->isExplicit())) {
+        if (ConvTemplate)
+          S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC,
+                                         Init, DeclType, CandidateSet);
+        else
+          S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Init,
+                                 DeclType, CandidateSet);
+      }
+    }
+
+    OverloadCandidateSet::iterator Best;
+    switch (S.BestViableFunction(CandidateSet, DeclLoc, Best)) {
+    case OR_Success:
+      // C++ [over.ics.ref]p1:
+      //
+      //   [...] If the parameter binds directly to the result of
+      //   applying a conversion function to the argument
+      //   expression, the implicit conversion sequence is a
+      //   user-defined conversion sequence (13.3.3.1.2), with the
+      //   second standard conversion sequence either an identity
+      //   conversion or, if the conversion function returns an
+      //   entity of a type that is a derived class of the parameter
+      //   type, a derived-to-base Conversion.
+      if (!Best->FinalConversion.DirectBinding)
+        break;
+
+      ICS.setUserDefined();
+      ICS.UserDefined.Before = Best->Conversions[0].Standard;
+      ICS.UserDefined.After = Best->FinalConversion;
+      ICS.UserDefined.ConversionFunction = Best->Function;
+      ICS.UserDefined.EllipsisConversion = false;
+      assert(ICS.UserDefined.After.ReferenceBinding &&
+             ICS.UserDefined.After.DirectBinding &&
+             "Expected a direct reference binding!");
+      return ICS;
+
+    case OR_Ambiguous:
+      ICS.setAmbiguous();
+      for (OverloadCandidateSet::iterator Cand = CandidateSet.begin();
+           Cand != CandidateSet.end(); ++Cand)
+        if (Cand->Viable)
+          ICS.Ambiguous.addConversion(Cand->Function);
+      return ICS;
+
+    case OR_No_Viable_Function:
+    case OR_Deleted:
+      // There was no suitable conversion, or we found a deleted
+      // conversion; continue with other checks.
+      break;
+    }
+  }
+
+  //     -- Otherwise, the reference shall be to a non-volatile const
+  //        type (i.e., cv1 shall be const), or the reference shall be an
+  //        rvalue reference and the initializer expression shall be an rvalue.
+  if (!isRValRef && T1.getCVRQualifiers() != Qualifiers::Const)
+    return ICS;
+
+  //       -- If the initializer expression is an rvalue, with T2 a
+  //          class type, and "cv1 T1" is reference-compatible with
+  //          "cv2 T2," the reference is bound in one of the
+  //          following ways (the choice is implementation-defined):
+  //
+  //          -- The reference is bound to the object represented by
+  //             the rvalue (see 3.10) or to a sub-object within that
+  //             object.
+  //
+  //          -- A temporary of type "cv1 T2" [sic] is created, and
+  //             a constructor is called to copy the entire rvalue
+  //             object into the temporary. The reference is bound to
+  //             the temporary or to a sub-object within the
+  //             temporary.
+  //
+  //          The constructor that would be used to make the copy
+  //          shall be callable whether or not the copy is actually
+  //          done.
+  //
+  // Note that C++0x [dcl.init.ref]p5 takes away this implementation
+  // freedom, so we will always take the first option and never build
+  // a temporary in this case. 
+  if (InitLvalue != Expr::LV_Valid && T2->isRecordType() &&
+      RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) {
+    ICS.setStandard();
+    ICS.Standard.First = ICK_Identity;
+    ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity;
+    ICS.Standard.Third = ICK_Identity;
+    ICS.Standard.FromTypePtr = T2.getAsOpaquePtr();
+    ICS.Standard.setToType(0, T2);
+    ICS.Standard.setToType(1, T1);
+    ICS.Standard.setToType(2, T1);
+    ICS.Standard.ReferenceBinding = true;
+    ICS.Standard.DirectBinding = false;
+    ICS.Standard.RRefBinding = isRValRef;
+    ICS.Standard.CopyConstructor = 0;
+    return ICS;
+  }
+
+  //       -- Otherwise, a temporary of type "cv1 T1" is created and
+  //          initialized from the initializer expression using the
+  //          rules for a non-reference copy initialization (8.5). The
+  //          reference is then bound to the temporary. If T1 is
+  //          reference-related to T2, cv1 must be the same
+  //          cv-qualification as, or greater cv-qualification than,
+  //          cv2; otherwise, the program is ill-formed.
+  if (RefRelationship == Sema::Ref_Related) {
+    // If cv1 == cv2 or cv1 is a greater cv-qualified than cv2, then
+    // we would be reference-compatible or reference-compatible with
+    // added qualification. But that wasn't the case, so the reference
+    // initialization fails.
+    return ICS;
+  }
+
+  // If at least one of the types is a class type, the types are not
+  // related, and we aren't allowed any user conversions, the
+  // reference binding fails. This case is important for breaking
+  // recursion, since TryImplicitConversion below will attempt to
+  // create a temporary through the use of a copy constructor.
+  if (SuppressUserConversions && RefRelationship == Sema::Ref_Incompatible &&
+      (T1->isRecordType() || T2->isRecordType()))
+    return ICS;
+
+  // C++ [over.ics.ref]p2:
+  //
+  //   When a parameter of reference type is not bound directly to
+  //   an argument expression, the conversion sequence is the one
+  //   required to convert the argument expression to the
+  //   underlying type of the reference according to
+  //   13.3.3.1. Conceptually, this conversion sequence corresponds
+  //   to copy-initializing a temporary of the underlying type with
+  //   the argument expression. Any difference in top-level
+  //   cv-qualification is subsumed by the initialization itself
+  //   and does not constitute a conversion.
+  ICS = S.TryImplicitConversion(Init, T1, SuppressUserConversions,
+                                /*AllowExplicit=*/false,
+                                /*ForceRValue=*/false,
+                                /*InOverloadResolution=*/false);
+
+  // Of course, that's still a reference binding.
+  if (ICS.isStandard()) {
+    ICS.Standard.ReferenceBinding = true;
+    ICS.Standard.RRefBinding = isRValRef;
+  } else if (ICS.isUserDefined()) {
+    ICS.UserDefined.After.ReferenceBinding = true;
+    ICS.UserDefined.After.RRefBinding = isRValRef;
+  }
+  return ICS;
+}
+
 /// TryCopyInitialization - Try to copy-initialize a value of type
 /// ToType from the expression From. Return the implicit conversion
 /// sequence required to pass this argument, which may be a bad
@@ -2185,23 +2507,18 @@ ImplicitConversionSequence
 Sema::TryCopyInitialization(Expr *From, QualType ToType,
                             bool SuppressUserConversions, bool ForceRValue,
                             bool InOverloadResolution) {
-  if (ToType->isReferenceType()) {
-    ImplicitConversionSequence ICS;
-    ICS.setBad(BadConversionSequence::no_conversion, From, ToType);
-    CheckReferenceInit(From, ToType,
-                       /*FIXME:*/From->getLocStart(),
-                       SuppressUserConversions,
-                       /*AllowExplicit=*/false,
-                       ForceRValue,
-                       &ICS);
-    return ICS;
-  } else {
-    return TryImplicitConversion(From, ToType,
-                                 SuppressUserConversions,
-                                 /*AllowExplicit=*/false,
-                                 ForceRValue,
-                                 InOverloadResolution);
-  }
+  if (ToType->isReferenceType())
+    return TryReferenceInit(*this, From, ToType,
+                            /*FIXME:*/From->getLocStart(),
+                            SuppressUserConversions,
+                            /*AllowExplicit=*/false,
+                            ForceRValue);
+
+  return TryImplicitConversion(From, ToType,
+                               SuppressUserConversions,
+                               /*AllowExplicit=*/false,
+                               ForceRValue,
+                               InOverloadResolution);
 }
 
 /// TryObjectArgumentInitialization - Try to initialize the object