diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-04-17 22:01:05 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-04-17 22:01:05 +0000 |
commit | 3fbaf3e5d524bfff219d1e3e9ac4801a8411590f (patch) | |
tree | fa5ce3a9ca1ba76a1c6e063ba6e70fefa2ccae4f /lib/Sema/SemaInit.cpp | |
parent | 4803535dfef2626d2aec18ef92450b5008945352 (diff) |
Improve our handling of user-defined conversions as part of overload
resolution. There are two sources of problems involving user-defined
conversions that this change eliminates, along with providing simpler
interfaces for checking implicit conversions:
- It eliminates a case of infinite recursion found in Boost.
- It eliminates the search for the constructor needed to copy a temporary
generated by an implicit conversion from overload
resolution. Overload resolution assumes that, if it gets a value
of the parameter's class type (or a derived class thereof), there
is a way to copy if... even if there isn't. We now model this
properly.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@101680 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaInit.cpp')
-rw-r--r-- | lib/Sema/SemaInit.cpp | 50 |
1 files changed, 35 insertions, 15 deletions
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 76de0729b5..4986fcbedf 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -2531,8 +2531,7 @@ static void TryReferenceInitialization(Sema &S, ImplicitConversionSequence ICS = S.TryImplicitConversion(Initializer, cv1T1, /*SuppressUserConversions=*/false, AllowExplicit, - /*FIXME:InOverloadResolution=*/false, - /*UserCast=*/Kind.isExplicitCast()); + /*FIXME:InOverloadResolution=*/false); if (ICS.isBad()) { // FIXME: Use the conversion function set stored in ICS to turn @@ -2867,10 +2866,21 @@ static void TryUserDefinedConversion(Sema &S, // Add the user-defined conversion step that calls the conversion function. QualType ConvType = Function->getResultType().getNonReferenceType(); - Sequence.AddUserConversionStep(Function, Best->FoundDecl, ConvType); + if (ConvType->getAs<RecordType>()) { + // If we're converting to a class type, there may be an copy if + // the resulting temporary object (possible to create an object of + // a base class type). That copy is not a separate conversion, so + // we just make a note of the actual destination type (possibly a + // base class of the type returned by the conversion function) and + // let the user-defined conversion step handle the conversion. + Sequence.AddUserConversionStep(Function, Best->FoundDecl, DestType); + return; + } - // If the conversion following the call to the conversion function is - // interesting, add it as a separate step. + Sequence.AddUserConversionStep(Function, Best->FoundDecl, ConvType); + + // If the conversion following the call to the conversion function + // is interesting, add it as a separate step. if (Best->FinalConversion.First || Best->FinalConversion.Second || Best->FinalConversion.Third) { ImplicitConversionSequence ICS; @@ -2891,8 +2901,7 @@ static void TryImplicitConversion(Sema &S, = S.TryImplicitConversion(Initializer, Entity.getType(), /*SuppressUserConversions=*/true, /*AllowExplicit=*/false, - /*FIXME:InOverloadResolution=*/false, - /*UserCast=*/Kind.isExplicitCast()); + /*InOverloadResolution=*/false); if (ICS.isBad()) { Sequence.SetFailed(InitializationSequence::FK_ConversionFailed); @@ -3103,10 +3112,11 @@ static Sema::OwningExprResult CopyObject(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, Sema::OwningExprResult CurInit) { - // Determine which class type we're copying. + // Determine which class type we're copying to. Expr *CurInitExpr = (Expr *)CurInit.get(); CXXRecordDecl *Class = 0; - if (const RecordType *Record = CurInitExpr->getType()->getAs<RecordType>()) + if (const RecordType *Record + = Entity.getType().getNonReferenceType()->getAs<RecordType>()) Class = cast<CXXRecordDecl>(Record->getDecl()); if (!Class) return move(CurInit); @@ -3203,16 +3213,26 @@ static Sema::OwningExprResult CopyObject(Sema &S, return S.ExprError(); } - S.CheckConstructorAccess(Loc, - cast<CXXConstructorDecl>(Best->Function), + CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(Best->Function); + ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(S); + CurInit.release(); // Ownership transferred into MultiExprArg, below. + + // Determine the arguments required to actually perform the + // constructor call (we might have derived-to-base conversions). + if (S.CompleteConstructorCall(Constructor, + Sema::MultiExprArg(S, + (void **)&CurInitExpr, + 1), + Loc, ConstructorArgs)) + return S.ExprError(); + + S.CheckConstructorAccess(Loc, Constructor, Best->FoundDecl.getAccess()); - CurInit.release(); return S.BuildCXXConstructExpr(Loc, Entity.getType().getNonReferenceType(), - cast<CXXConstructorDecl>(Best->Function), + Constructor, Elidable, - Sema::MultiExprArg(S, - (void**)&CurInitExpr, 1)); + move_arg(ConstructorArgs)); } Action::OwningExprResult |