bool SuppressUserConversions,
bool AllowExplicit,
bool ForceRValue,
- bool InOverloadResolution);
+ bool InOverloadResolution,
+ bool UserCast = false);
bool IsStandardConversion(Expr *From, QualType ToType,
bool InOverloadResolution,
StandardConversionSequence& SCS);
UserDefinedConversionSequence& User,
OverloadCandidateSet& Conversions,
bool AllowConversionFunctions,
- bool AllowExplicit, bool ForceRValue);
+ bool AllowExplicit, bool ForceRValue,
+ bool UserCast = false);
bool DiagnoseAmbiguousUserDefinedConversion(Expr *From, QualType ToType);
/// 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;
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
///
/// \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())) {
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);
}
}
}
--- /dev/null
+// 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