]> granicus.if.org Git - clang/commitdiff
Patch to implement static casting which requires one
authorFariborz Jahanian <fjahanian@apple.com>
Thu, 1 Oct 2009 20:39:51 +0000 (20:39 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Thu, 1 Oct 2009 20:39:51 +0000 (20:39 +0000)
user-defined type conversion. Fixes PR5040.

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

lib/Sema/Sema.h
lib/Sema/SemaCXXCast.cpp
lib/Sema/SemaOverload.cpp
test/CodeGenCXX/cast-conversion.cpp [new file with mode: 0644]
test/SemaCXX/cast-conversion.cpp [new file with mode: 0644]

index 60220834dba693b948b1196a4ce4f55ea19cebb6..b234d56fa013c4dd16aae022158a748f219260e7 100644 (file)
@@ -766,7 +766,8 @@ public:
                         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 @@ public:
                                UserDefinedConversionSequence& User,
                                OverloadCandidateSet& Conversions,
                                bool AllowConversionFunctions,
-                               bool AllowExplicit, bool ForceRValue);
+                               bool AllowExplicit, bool ForceRValue,
+                               bool UserCast = false);
   bool DiagnoseAmbiguousUserDefinedConversion(Expr *From, QualType ToType);
                                               
 
index e5c4390752c9de11ad0434f67be0a0f3793e40df..9822a44b0f8ed2c1ead224b3f83e77f10f215652 100644 (file)
@@ -806,7 +806,8 @@ TryStaticImplicitCast(Sema &Self, Expr *SrcExpr, QualType DestType,
                                /*SuppressUserConversions=*/false,
                                /*AllowExplicit=*/true,
                                /*ForceRValue=*/false,
-                               /*InOverloadResolution=*/false);
+                               /*InOverloadResolution=*/false,
+                               /*one of user provided casts*/true);
 
   if (ICS.ConversionKind == ImplicitConversionSequence::BadConversion)
     return TC_NotApplicable;
index 6966926e9e920c034908459dda5e223352d049f1..18614f78709666cac0fe8d945fd8e00fb853c0b6 100644 (file)
@@ -404,11 +404,14 @@ Sema::IsOverload(FunctionDecl *New, Decl* OldD,
 /// 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 @@ Sema::TryImplicitConversion(Expr* From, QualType ToType,
                                    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 @@ static void GetFunctionAndTemplate(AnyFunctionDecl Orig, T *&Function,
 ///
 /// \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 @@ Sema::OverloadingResult Sema::IsUserDefinedConversion(
           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);
         }
       }
     }
diff --git a/test/CodeGenCXX/cast-conversion.cpp b/test/CodeGenCXX/cast-conversion.cpp
new file mode 100644 (file)
index 0000000..f571f54
--- /dev/null
@@ -0,0 +1,33 @@
+// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s &&
+// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s &&
+// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s &&
+// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s &&
+// RUN: true
+
+struct A {
+  A(int);
+};
+
+struct B {
+  B(A);
+};
+
+int main () {
+  (B)10;
+  B(10);
+  static_cast<B>(10);
+}
+
+// CHECK-LP64: call     __ZN1AC1Ei
+// CHECK-LP64: call     __ZN1BC1E1A
+// CHECK-LP64: call     __ZN1AC1Ei
+// CHECK-LP64: call     __ZN1BC1E1A
+// CHECK-LP64: call     __ZN1AC1Ei
+// CHECK-LP64: call     __ZN1BC1E1A
+
+// CHECK-LP32: call     L__ZN1AC1Ei
+// CHECK-LP32: call     L__ZN1BC1E1A
+// CHECK-LP32: call     L__ZN1AC1Ei
+// CHECK-LP32: call     L__ZN1BC1E1A
+// CHECK-LP32: call     L__ZN1AC1Ei
+// CHECK-LP32: call     L__ZN1BC1E1A
diff --git a/test/SemaCXX/cast-conversion.cpp b/test/SemaCXX/cast-conversion.cpp
new file mode 100644 (file)
index 0000000..cbc24ae
--- /dev/null
@@ -0,0 +1,21 @@
+// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x
+
+struct R {
+  R(int);
+};
+
+struct A {
+  A(R);
+};
+
+struct B {
+  B(A);
+};
+
+int main () {
+  B(10);       // expected-error {{functional-style cast from 'int' to 'struct B' is not allowed}}
+  (B)10;       // expected-error {{C-style cast from 'int' to 'struct B' is not allowed}}
+  static_cast<B>(10);  // expected-error {{static_cast from 'int' to 'struct B' is not allowed}} \\
+                       // expected-warning {{expression result unused}}
+}
+