From 249ceade4942a2a5d7888541c547abeda5bb85b4 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Thu, 1 Oct 2009 20:39:51 +0000 Subject: [PATCH] Patch to implement static casting which requires one 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 | 6 ++++-- lib/Sema/SemaCXXCast.cpp | 3 ++- lib/Sema/SemaOverload.cpp | 19 ++++++++++++----- test/CodeGenCXX/cast-conversion.cpp | 33 +++++++++++++++++++++++++++++ test/SemaCXX/cast-conversion.cpp | 21 ++++++++++++++++++ 5 files changed, 74 insertions(+), 8 deletions(-) create mode 100644 test/CodeGenCXX/cast-conversion.cpp create mode 100644 test/SemaCXX/cast-conversion.cpp diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 60220834db..b234d56fa0 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -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); diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp index e5c4390752..9822a44b0f 100644 --- a/lib/Sema/SemaCXXCast.cpp +++ b/lib/Sema/SemaCXXCast.cpp @@ -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; diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 6966926e9e..18614f7870 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -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()) { if (CXXRecordDecl *ToRecordDecl = dyn_cast(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 index 0000000000..f571f549d0 --- /dev/null +++ b/test/CodeGenCXX/cast-conversion.cpp @@ -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(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 index 0000000000..cbc24aef28 --- /dev/null +++ b/test/SemaCXX/cast-conversion.cpp @@ -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(10); // expected-error {{static_cast from 'int' to 'struct B' is not allowed}} \\ + // expected-warning {{expression result unused}} +} +