Patch to implement static casting which requires one 
user-defined type conversion. Fixes PR5040.

llvm-svn: 83211
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h
index 6022083..b234d56 100644
--- a/clang/lib/Sema/Sema.h
+++ b/clang/lib/Sema/Sema.h
@@ -766,7 +766,8 @@
                         bool SuppressUserConversions,
                         bool AllowExplicit,
                         bool ForceRValue,
-                        bool InOverloadResolution);
+                        bool InOverloadResolution,
+                        bool UserCast = false);
   bool IsStandardConversion(Expr *From, QualType ToType,
                             bool InOverloadResolution,
                             StandardConversionSequence& SCS);
@@ -790,7 +791,8 @@
                                UserDefinedConversionSequence& User,
                                OverloadCandidateSet& Conversions,
                                bool AllowConversionFunctions,
-                               bool AllowExplicit, bool ForceRValue);
+                               bool AllowExplicit, bool ForceRValue,
+                               bool UserCast = false);
   bool DiagnoseAmbiguousUserDefinedConversion(Expr *From, QualType ToType);
                                               
 
diff --git a/clang/lib/Sema/SemaCXXCast.cpp b/clang/lib/Sema/SemaCXXCast.cpp
index e5c4390..9822a44 100644
--- a/clang/lib/Sema/SemaCXXCast.cpp
+++ b/clang/lib/Sema/SemaCXXCast.cpp
@@ -806,7 +806,8 @@
                                /*SuppressUserConversions=*/false,
                                /*AllowExplicit=*/true,
                                /*ForceRValue=*/false,
-                               /*InOverloadResolution=*/false);
+                               /*InOverloadResolution=*/false,
+                               /*one of user provided casts*/true);
 
   if (ICS.ConversionKind == ImplicitConversionSequence::BadConversion)
     return TC_NotApplicable;
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 6966926..18614f7 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -404,11 +404,14 @@
 /// permitted.
 /// If @p ForceRValue, then overloading is performed as if From was an rvalue,
 /// no matter its actual lvalueness.
+/// If @p UserCast, the implicit conversion is being done for a user-specified
+/// cast.
 ImplicitConversionSequence
 Sema::TryImplicitConversion(Expr* From, QualType ToType,
                             bool SuppressUserConversions,
                             bool AllowExplicit, bool ForceRValue,
-                            bool InOverloadResolution) {
+                            bool InOverloadResolution,
+                            bool UserCast) {
   ImplicitConversionSequence ICS;
   OverloadCandidateSet Conversions;
   OverloadingResult UserDefResult = OR_Success;
@@ -419,7 +422,7 @@
                                    ICS.UserDefined,
                                    Conversions,
                                    !SuppressUserConversions, AllowExplicit,
-                                   ForceRValue)) == OR_Success) {
+				   ForceRValue, UserCast)) == OR_Success) {
     ICS.ConversionKind = ImplicitConversionSequence::UserDefinedConversion;
     // C++ [over.ics.user]p4:
     //   A conversion of an expression of class type to the same class
@@ -1372,12 +1375,15 @@
 ///
 /// \param ForceRValue  true if the expression should be treated as an rvalue
 /// for overload resolution.
+/// \param UserCast true if looking for user defined conversion for a static
+/// cast.
 Sema::OverloadingResult Sema::IsUserDefinedConversion(
                                    Expr *From, QualType ToType,
                                    UserDefinedConversionSequence& User,
                                    OverloadCandidateSet& CandidateSet,
                                    bool AllowConversionFunctions,
-                                   bool AllowExplicit, bool ForceRValue) {
+                                   bool AllowExplicit, bool ForceRValue,
+                                   bool UserCast) {
   if (const RecordType *ToRecordType = ToType->getAs<RecordType>()) {
     if (CXXRecordDecl *ToRecordDecl
           = dyn_cast<CXXRecordDecl>(ToRecordType->getDecl())) {
@@ -1411,11 +1417,14 @@
           if (ConstructorTmpl)
             AddTemplateOverloadCandidate(ConstructorTmpl, false, 0, 0, &From,
                                          1, CandidateSet,
-                                         /*SuppressUserConversions=*/true,
+                                         /*SuppressUserConversions=*/!UserCast,
                                          ForceRValue);
           else
+            // Allow one user-defined conversion when user specifies a
+            // From->ToType conversion via an static cast (c-style, etc).
             AddOverloadCandidate(Constructor, &From, 1, CandidateSet,
-                                 /*SuppressUserConversions=*/true, ForceRValue);
+                                 /*SuppressUserConversions=*/!UserCast, 
+                                 ForceRValue);
         }
       }
     }