aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-08-19 15:57:50 +0000
committerDouglas Gregor <dgregor@apple.com>2010-08-19 15:57:50 +0000
commitc774b2f66478008196f497a227d5ab88ea157582 (patch)
tree376b9c65ef3fb2d6edd62022c6b93aa4794f5a2b /lib
parentbca393259bc01955b334709de0f5a202470f913a (diff)
Properly implement the part of C++ [over.match.funcs]p4 that treats
conversion functions as if their acting context were the class that we're converting from (the implicit object argument's type). Retroactively tweaking the implicit conversion sequence, as we were trying to do before, breaks the invariants of that implicit conversion sequence (e.g., the types and conversions don't match up). Fixes <rdar://problem/8018274>. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111520 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Sema/SemaOverload.cpp38
1 files changed, 29 insertions, 9 deletions
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 2ee36f8101..f8f04defb1 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -3741,26 +3741,46 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
Candidate.FinalConversion.setAsIdentityConversion();
Candidate.FinalConversion.setFromType(ConvType);
Candidate.FinalConversion.setAllToTypes(ToType);
-
- // Determine the implicit conversion sequence for the implicit
- // object parameter.
Candidate.Viable = true;
Candidate.Conversions.resize(1);
- Candidate.Conversions[0]
- = TryObjectArgumentInitialization(From->getType(), Conversion,
- ActingContext);
-
+
// C++ [over.match.funcs]p4:
// For conversion functions, the function is considered to be a member of
// the class of the implicit implied object argument for the purpose of
// defining the type of the implicit object parameter.
- if (Candidate.Conversions[0].Standard.Second == ICK_Derived_To_Base)
- Candidate.Conversions[0].Standard.Second = ICK_Identity;
+ //
+ // Determine the implicit conversion sequence for the implicit
+ // object parameter.
+ QualType ImplicitParamType = From->getType();
+ if (const PointerType *FromPtrType = ImplicitParamType->getAs<PointerType>())
+ ImplicitParamType = FromPtrType->getPointeeType();
+ CXXRecordDecl *ConversionContext
+ = cast<CXXRecordDecl>(ImplicitParamType->getAs<RecordType>()->getDecl());
+
+ Candidate.Conversions[0]
+ = TryObjectArgumentInitialization(From->getType(), Conversion,
+ ConversionContext);
+
if (Candidate.Conversions[0].isBad()) {
Candidate.Viable = false;
Candidate.FailureKind = ovl_fail_bad_conversion;
return;
}
+
+ // Make sure that the actual object argument initialization will work, when
+ // it comes down to it. This takes into account the actual acting context.
+ if (ConversionContext->getCanonicalDecl()
+ != ActingContext->getCanonicalDecl()) {
+ ImplicitConversionSequence ObjectConvertICS
+ = TryObjectArgumentInitialization(From->getType(), Conversion,
+ ActingContext);
+ if (ObjectConvertICS.isBad()) {
+ Candidate.Viable = false;
+ Candidate.FailureKind = ovl_fail_bad_conversion;
+ Candidate.Conversions[0] = ObjectConvertICS;
+ return;
+ }
+ }
// We won't go through a user-define type conversion function to convert a
// derived to base as such conversions are given Conversion Rank. They only