From 966256afd49a4af0c002046a19bb0041a507909b Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Fri, 6 Nov 2009 00:23:08 +0000 Subject: [PATCH] This patch implements Sema for clause 13.3.3.1p4. It has to do with vararg constructors used as conversion functions. Code gen needs work. This is WIP. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86207 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDeclCXX.cpp | 1 + lib/Sema/SemaExprCXX.cpp | 21 ++++++++++++--------- lib/Sema/SemaOverload.cpp | 11 +++++++++-- lib/Sema/SemaOverload.h | 8 ++++++++ 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index b8977cfa14..f3561bfa0f 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -3827,6 +3827,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, ICS->UserDefined.Before = Best->Conversions[0].Standard; ICS->UserDefined.After = Best->FinalConversion; ICS->UserDefined.ConversionFunction = Best->Function; + ICS->UserDefined.EllipsisConversion = false; assert(ICS->UserDefined.After.ReferenceBinding && ICS->UserDefined.After.DirectBinding && "Expected a direct reference binding!"); diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index dc57681573..3408ff7087 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -1086,18 +1086,21 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, } else if (const CXXConstructorDecl *Ctor = dyn_cast(FD)) { CastKind = CastExpr::CK_ConstructorConversion; - - // If the user-defined conversion is specified by a constructor, the - // initial standard conversion sequence converts the source type to the - // type required by the argument of the constructor - BeforeToType = Ctor->getParamDecl(0)->getType(); + // Do no conversion if dealing with ... for the first conversion. + if (!ICS.UserDefined.EllipsisConversion) + // If the user-defined conversion is specified by a constructor, the + // initial standard conversion sequence converts the source type to the + // type required by the argument of the constructor + BeforeToType = Ctor->getParamDecl(0)->getType(); } else assert(0 && "Unknown conversion function kind!"); - - if (PerformImplicitConversion(From, BeforeToType, - ICS.UserDefined.Before, "converting")) - return true; + // Whatch out for elipsis conversion. + if (!BeforeToType.isNull()) { + if (PerformImplicitConversion(From, BeforeToType, + ICS.UserDefined.Before, "converting")) + return true; + } OwningExprResult CastArg = BuildCXXCastArgument(From->getLocStart(), diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 3e6778bc47..19f0885e8e 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -1481,9 +1481,14 @@ Sema::OverloadingResult Sema::IsUserDefinedConversion( // sequence converts the source type to the type required by // the argument of the constructor. // - // FIXME: What about ellipsis conversions? QualType ThisType = Constructor->getThisType(Context); - User.Before = Best->Conversions[0].Standard; + if (Best->Conversions[0].ConversionKind == + ImplicitConversionSequence::EllipsisConversion) + User.EllipsisConversion = true; + else { + User.Before = Best->Conversions[0].Standard; + User.EllipsisConversion = false; + } User.ConversionFunction = Constructor; User.After.setAsIdentityConversion(); User.After.FromTypePtr @@ -1500,6 +1505,7 @@ Sema::OverloadingResult Sema::IsUserDefinedConversion( // implicit object parameter of the conversion function. User.Before = Best->Conversions[0].Standard; User.ConversionFunction = Conversion; + User.EllipsisConversion = false; // C++ [over.ics.user]p2: // The second standard conversion sequence converts the @@ -2693,6 +2699,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, Candidate.Conversions[0].ConversionKind = ImplicitConversionSequence::UserDefinedConversion; Candidate.Conversions[0].UserDefined.Before = ObjectInit.Standard; + Candidate.Conversions[0].UserDefined.EllipsisConversion = false; Candidate.Conversions[0].UserDefined.ConversionFunction = Conversion; Candidate.Conversions[0].UserDefined.After = Candidate.Conversions[0].UserDefined.Before; diff --git a/lib/Sema/SemaOverload.h b/lib/Sema/SemaOverload.h index 898393a9e4..0d1f37aa4b 100644 --- a/lib/Sema/SemaOverload.h +++ b/lib/Sema/SemaOverload.h @@ -156,6 +156,14 @@ namespace clang { /// object parameter of the conversion function. StandardConversionSequence Before; + /// EllipsisConversion - When this is true, it means user-defined + /// conversion sequence starts with a ... (elipsis) conversion, instead of + /// a standard conversion. In this case, 'Before' field must be ignored. + // FIXME. I much rather put this as the first field. But there seems to be + // a gcc code gen. bug which causes a crash in a test. Putting it here seems + // to work around the crash. + bool EllipsisConversion : 1; + /// After - Represents the standard conversion that occurs after /// the actual user-defined conversion. StandardConversionSequence After; -- 2.40.0