- Have TryStaticImplicitCast set the cast kind to NoOp when binding a reference. CheckReferenceInit already inserts implicit casts to the necessary types. This fixes an assertion in CodeGen for some casts and brings a fix for PR5453 close, if I understand that bug correctly.
- Also, perform calculated implicit cast sequences if they're determined to work. This finally diagnoses static_cast to ambiguous or implicit bases and fixes two long-standing fixmes in the test case. For the C-style cast, this requires propagating the access check suppression pretty deep into other functions.
- Pass the expressions for TryStaticCast and TryStaticImplicitCast by reference. This should lead to a better AST being emitted for such casts, and also fixes a memory leak, because CheckReferenceInit and PerformImplicitConversion wrap the node passed to them. These wrappers were previously lost.

llvm-svn: 88809
diff --git a/clang/lib/Sema/SemaCXXCast.cpp b/clang/lib/Sema/SemaCXXCast.cpp
index 4d46b32..d055dd4 100644
--- a/clang/lib/Sema/SemaCXXCast.cpp
+++ b/clang/lib/Sema/SemaCXXCast.cpp
@@ -88,13 +88,13 @@
                                                   const SourceRange &OpRange,
                                                   unsigned &msg,
                                                   CastExpr::CastKind &Kind);
-static TryCastResult TryStaticImplicitCast(Sema &Self, Expr *SrcExpr,
+static TryCastResult TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr,
                                            QualType DestType, bool CStyle,
                                            const SourceRange &OpRange,
                                            unsigned &msg,
                                            CastExpr::CastKind &Kind,
                                            CXXMethodDecl *&ConversionDecl);
-static TryCastResult TryStaticCast(Sema &Self, Expr *SrcExpr,
+static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
                                    QualType DestType, bool CStyle,
                                    const SourceRange &OpRange,
                                    unsigned &msg,
@@ -387,15 +387,14 @@
   // This test is outside everything else because it's the only case where
   // a non-lvalue-reference target type does not lead to decay.
   // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void".
-  if (DestType->isVoidType()) {
+  if (DestType->isVoidType())
     return;
-  }
 
   if (!DestType->isLValueReferenceType() && !DestType->isRecordType())
     Self.DefaultFunctionArrayConversion(SrcExpr);
 
   unsigned msg = diag::err_bad_cxx_cast_generic;
-  if (TryStaticCast(Self, SrcExpr, DestType, /*CStyle*/false,OpRange, msg, 
+  if (TryStaticCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange, msg,
                     Kind, ConversionDecl)
       != TC_Success && msg != 0)
     Self.Diag(OpRange.getBegin(), msg) << CT_Static
@@ -405,7 +404,7 @@
 /// TryStaticCast - Check if a static cast can be performed, and do so if
 /// possible. If @p CStyle, ignore access restrictions on hierarchy casting
 /// and casting away constness.
-static TryCastResult TryStaticCast(Sema &Self, Expr *SrcExpr,
+static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
                                    QualType DestType, bool CStyle,
                                    const SourceRange &OpRange, unsigned &msg,
                                    CastExpr::CastKind &Kind,
@@ -430,7 +429,7 @@
   // C++ 5.2.9p5, reference downcast.
   // See the function for details.
   // DR 427 specifies that this is to be applied before paragraph 2.
-  tcr = TryStaticReferenceDowncast(Self, SrcExpr, DestType, CStyle, OpRange, 
+  tcr = TryStaticReferenceDowncast(Self, SrcExpr, DestType, CStyle, OpRange,
                                    msg, Kind);
   if (tcr != TC_NotApplicable)
     return tcr;
@@ -438,8 +437,10 @@
   // N2844 5.2.9p3: An lvalue of type "cv1 T1" can be cast to type "rvalue
   //   reference to cv2 T2" if "cv2 T2" is reference-compatible with "cv1 T1".
   tcr = TryLValueToRValueCast(Self, SrcExpr, DestType, msg);
-  if (tcr != TC_NotApplicable)
+  if (tcr != TC_NotApplicable) {
+    Kind = CastExpr::CK_NoOp;
     return tcr;
+  }
 
   // C++ 5.2.9p2: An expression e can be explicitly converted to a type T
   //   [...] if the declaration "T t(e);" is well-formed, [...].
@@ -779,7 +780,7 @@
 ///   An expression e can be explicitly converted to a type T using a
 ///   @c static_cast if the declaration "T t(e);" is well-formed [...].
 TryCastResult
-TryStaticImplicitCast(Sema &Self, Expr *SrcExpr, QualType DestType,
+TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
                       bool CStyle, const SourceRange &OpRange, unsigned &msg,
                       CastExpr::CastKind &Kind, 
                       CXXMethodDecl *&ConversionDecl) {
@@ -792,30 +793,39 @@
   }
 
   if (DestType->isReferenceType()) {
+    // All reference bindings insert implicit casts above that do the actual
+    // casting.
+    Kind = CastExpr::CK_NoOp;
+
     // At this point of CheckStaticCast, if the destination is a reference,
     // this has to work. There is no other way that works.
     // On the other hand, if we're checking a C-style cast, we've still got
-    // the reinterpret_cast way. In that case, we pass an ICS so we don't
-    // get error messages.
-    ImplicitConversionSequence ICS;
-    bool failed = Self.CheckReferenceInit(SrcExpr, DestType,
-                                          OpRange.getBegin(),
-                                          /*SuppressUserConversions=*/false,
-                                          /*AllowExplicit=*/false,
-                                          /*ForceRValue=*/false,
-                                          CStyle ? &ICS : 0);
-    if (!failed)
+    // the reinterpret_cast way. So in C-style mode, we first try the call
+    // with an ICS to suppress errors.
+    if (CStyle) {
+      ImplicitConversionSequence ICS;
+      if(Self.CheckReferenceInit(SrcExpr, DestType, OpRange.getBegin(),
+                                 /*SuppressUserConversions=*/false,
+                                 /*AllowExplicit=*/false, /*ForceRValue=*/false,
+                                 &ICS))
+        return TC_NotApplicable;
+    }
+    // Now we're committed either way.
+    if(!Self.CheckReferenceInit(SrcExpr, DestType, OpRange.getBegin(),
+                                /*SuppressUserConversions=*/false,
+                                /*AllowExplicit=*/false,
+                                /*ForceRValue=*/false, 0,
+                                /*IgnoreBaseAccess=*/CStyle))
       return TC_Success;
-    if (CStyle)
-      return TC_NotApplicable;
-    // If we didn't pass the ICS, we already got an error message.
+
+    // We already got an error message.
     msg = 0;
     return TC_Failed;
   }
 
   if (DestType->isRecordType()) {
     if (CXXConstructorDecl *Constructor
-          = Self.TryInitializationByConstructor(DestType, &SrcExpr, 1, 
+          = Self.TryInitializationByConstructor(DestType, &SrcExpr, 1,
                                                 OpRange.getBegin(),
                                                 Sema::IK_Direct)) {
       ConversionDecl = Constructor;
@@ -825,7 +835,7 @@
     
     return TC_NotApplicable;
   }
-  
+
   // FIXME: To get a proper error from invalid conversions here, we need to
   // reimplement more of this.
   // FIXME: This does not actually perform the conversion, and thus does not
@@ -841,18 +851,11 @@
   if (ICS.ConversionKind == ImplicitConversionSequence::BadConversion)
     return TC_NotApplicable;
 
-  if (ICS.ConversionKind == ImplicitConversionSequence::UserDefinedConversion) {
-    ConversionDecl = cast<CXXMethodDecl>(ICS.UserDefined.ConversionFunction);
-    if (isa<CXXConstructorDecl>(ConversionDecl))
-      Kind = CastExpr::CK_ConstructorConversion;
-    else if (isa<CXXConversionDecl>(ConversionDecl))
-      Kind = CastExpr::CK_UserDefinedConversion;
-  } else if (ICS.ConversionKind ==
-              ImplicitConversionSequence::StandardConversion) {
-    // FIXME: Set the cast kind depending on which types of conversions we have.
-  }
-
-  return TC_Success;
+  // The conversion is possible, so commit to it.
+  msg = 0;
+  return Self.PerformImplicitConversion(SrcExpr, DestType, ICS, "casting",
+                                        /*IgnoreBaseAccess*/CStyle) ?
+      TC_Failed : TC_Success;
 }
 
 /// TryConstCast - See if a const_cast from source to destination is allowed,