Patch to implement static casting which requires one

user-defined type conversion. Fixes PR5040.

llvm-svn: 83211
This commit is contained in:
Fariborz Jahanian 2009-10-01 20:39:51 +00:00
parent 75cc16c0f2
commit b3c44f9ee9
5 changed files with 74 additions and 8 deletions

View 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);

View 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;

View 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);
}
}
}

View File

@ -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

View File

@ -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}}
}