diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/Sema.h | 7 | ||||
-rw-r--r-- | lib/Sema/SemaInit.cpp | 50 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 131 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.h | 27 |
4 files changed, 138 insertions, 77 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 2d5cee43e6..ef76882ac0 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1064,8 +1064,7 @@ public: TryImplicitConversion(Expr* From, QualType ToType, bool SuppressUserConversions, bool AllowExplicit, - bool InOverloadResolution, - bool UserCast = false); + bool InOverloadResolution); bool IsStandardConversion(Expr *From, QualType ToType, bool InOverloadResolution, StandardConversionSequence& SCS); @@ -1090,9 +1089,7 @@ public: OverloadingResult IsUserDefinedConversion(Expr *From, QualType ToType, UserDefinedConversionSequence& User, OverloadCandidateSet& Conversions, - bool AllowConversionFunctions, - bool AllowExplicit, - bool UserCast); + bool AllowExplicit); bool DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType); 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 diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index c4a42cd1ef..11fc972ee2 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -436,14 +436,11 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old) { /// not permitted. /// If @p AllowExplicit, then explicit user-defined conversions are /// permitted. -/// 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 InOverloadResolution, - bool UserCast) { + bool InOverloadResolution) { ImplicitConversionSequence ICS; if (IsStandardConversion(From, ToType, InOverloadResolution, ICS.Standard)) { ICS.setStandard(); @@ -455,11 +452,47 @@ Sema::TryImplicitConversion(Expr* From, QualType ToType, return ICS; } + if (SuppressUserConversions) { + // C++ [over.ics.user]p4: + // A conversion of an expression of class type to the same class + // type is given Exact Match rank, and a conversion of an + // expression of class type to a base class of that type is + // given Conversion rank, in spite of the fact that a copy/move + // constructor (i.e., a user-defined conversion function) is + // called for those cases. + QualType FromType = From->getType(); + if (!ToType->getAs<RecordType>() || !FromType->getAs<RecordType>() || + !(Context.hasSameUnqualifiedType(FromType, ToType) || + IsDerivedFrom(FromType, ToType))) { + // We're not in the case above, so there is no conversion that + // we can perform. + ICS.setBad(BadConversionSequence::no_conversion, From, ToType); + return ICS; + } + + ICS.setStandard(); + ICS.Standard.setAsIdentityConversion(); + ICS.Standard.setFromType(FromType); + ICS.Standard.setAllToTypes(ToType); + + // We don't actually check at this point whether there is a valid + // copy/move constructor, since overloading just assumes that it + // exists. When we actually perform initialization, we'll find the + // appropriate constructor to copy the returned object, if needed. + ICS.Standard.CopyConstructor = 0; + + // Determine whether this is considered a derived-to-base conversion. + if (!Context.hasSameUnqualifiedType(FromType, ToType)) + ICS.Standard.Second = ICK_Derived_To_Base; + + return ICS; + } + + // Attempt user-defined conversion. OverloadCandidateSet Conversions(From->getExprLoc()); OverloadingResult UserDefResult = IsUserDefinedConversion(From, ToType, ICS.UserDefined, Conversions, - !SuppressUserConversions, AllowExplicit, - UserCast); + AllowExplicit); if (UserDefResult == OR_Success) { ICS.setUserDefined(); @@ -1509,45 +1542,39 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType) { /// and this routine will return true. Otherwise, this routine returns /// false and User is unspecified. /// -/// \param AllowConversionFunctions true if the conversion should -/// consider conversion functions at all. If false, only constructors -/// will be considered. -/// /// \param AllowExplicit true if the conversion should consider C++0x /// "explicit" conversion functions as well as non-explicit conversion /// functions (C++0x [class.conv.fct]p2). -/// -/// \param UserCast true if looking for user defined conversion for a static -/// cast. OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType, UserDefinedConversionSequence& User, - OverloadCandidateSet& CandidateSet, - bool AllowConversionFunctions, - bool AllowExplicit, - bool UserCast) { + OverloadCandidateSet& CandidateSet, + bool AllowExplicit) { + // Whether we will only visit constructors. + bool ConstructorsOnly = false; + + // If the type we are conversion to is a class type, enumerate its + // constructors. if (const RecordType *ToRecordType = ToType->getAs<RecordType>()) { + // C++ [over.match.ctor]p1: + // When objects of class type are direct-initialized (8.5), or + // copy-initialized from an expression of the same or a + // derived class type (8.5), overload resolution selects the + // constructor. [...] For copy-initialization, the candidate + // functions are all the converting constructors (12.3.1) of + // that class. The argument list is the expression-list within + // the parentheses of the initializer. + if (Context.hasSameUnqualifiedType(ToType, From->getType()) || + (From->getType()->getAs<RecordType>() && + IsDerivedFrom(From->getType(), ToType))) + ConstructorsOnly = true; + if (RequireCompleteType(From->getLocStart(), ToType, PDiag())) { // We're not going to find any constructors. } else if (CXXRecordDecl *ToRecordDecl = dyn_cast<CXXRecordDecl>(ToRecordType->getDecl())) { - // C++ [over.match.ctor]p1: - // When objects of class type are direct-initialized (8.5), or - // copy-initialized from an expression of the same or a - // derived class type (8.5), overload resolution selects the - // constructor. [...] For copy-initialization, the candidate - // functions are all the converting constructors (12.3.1) of - // that class. The argument list is the expression-list within - // the parentheses of the initializer. - bool SuppressUserConversions = !UserCast; - if (Context.hasSameUnqualifiedType(ToType, From->getType()) || - IsDerivedFrom(From->getType(), ToType)) { - SuppressUserConversions = false; - AllowConversionFunctions = false; - } - DeclarationName ConstructorName = Context.DeclarationNames.getCXXConstructorName( - Context.getCanonicalType(ToType).getUnqualifiedType()); + Context.getCanonicalType(ToType).getUnqualifiedType()); DeclContext::lookup_iterator Con, ConEnd; for (llvm::tie(Con, ConEnd) = ToRecordDecl->lookup(ConstructorName); @@ -1571,26 +1598,25 @@ OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType, AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, /*ExplicitArgs*/ 0, &From, 1, CandidateSet, - SuppressUserConversions); + /*SuppressUserConversions=*/!ConstructorsOnly); else // Allow one user-defined conversion when user specifies a // From->ToType conversion via an static cast (c-style, etc). AddOverloadCandidate(Constructor, FoundDecl, &From, 1, CandidateSet, - SuppressUserConversions); + /*SuppressUserConversions=*/!ConstructorsOnly); } } } } - if (!AllowConversionFunctions) { - // Don't allow any conversion functions to enter the overload set. + // Enumerate conversion functions, if we're allowed to. + if (ConstructorsOnly) { } else if (RequireCompleteType(From->getLocStart(), From->getType(), - PDiag(0) - << From->getSourceRange())) { + PDiag(0) << From->getSourceRange())) { // No conversion functions from incomplete types. } else if (const RecordType *FromRecordType - = From->getType()->getAs<RecordType>()) { + = From->getType()->getAs<RecordType>()) { if (CXXRecordDecl *FromRecordDecl = dyn_cast<CXXRecordDecl>(FromRecordType->getDecl())) { // Add all of the conversion functions as candidates. @@ -1696,7 +1722,7 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) { OverloadCandidateSet CandidateSet(From->getExprLoc()); OverloadingResult OvResult = IsUserDefinedConversion(From, ToType, ICS.UserDefined, - CandidateSet, true, false, false); + CandidateSet, false); if (OvResult == OR_Ambiguous) Diag(From->getSourceRange().getBegin(), diag::err_typecheck_ambiguous_condition) @@ -1732,16 +1758,10 @@ Sema::CompareImplicitConversionSequences(const ImplicitConversionSequence& ICS1, // described in 13.3.3.2, the ambiguous conversion sequence is // treated as a user-defined sequence that is indistinguishable // from any other user-defined conversion sequence. - if (ICS1.getKind() < ICS2.getKind()) { - if (!(ICS1.isUserDefined() && ICS2.isAmbiguous())) - return ImplicitConversionSequence::Better; - } else if (ICS2.getKind() < ICS1.getKind()) { - if (!(ICS2.isUserDefined() && ICS1.isAmbiguous())) - return ImplicitConversionSequence::Worse; - } - - if (ICS1.isAmbiguous() || ICS2.isAmbiguous()) - return ImplicitConversionSequence::Indistinguishable; + if (ICS1.getKindRank() < ICS2.getKindRank()) + return ImplicitConversionSequence::Better; + else if (ICS2.getKindRank() < ICS1.getKindRank()) + return ImplicitConversionSequence::Worse; // Two implicit conversion sequences of the same form are // indistinguishable conversion sequences unless one of the @@ -2167,9 +2187,7 @@ Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1, } } - if ((SCS1.ReferenceBinding || SCS1.CopyConstructor) && - (SCS2.ReferenceBinding || SCS2.CopyConstructor) && - SCS1.Second == ICK_Derived_To_Base) { + if (SCS1.Second == ICK_Derived_To_Base) { // -- conversion of C to B is better than conversion of C to A, // -- binding of an expression of type C to a reference of type // B& is better than binding an expression of type C to a @@ -3067,7 +3085,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, OverloadCandidateSet& CandidateSet) { assert(!Conversion->getDescribedFunctionTemplate() && "Conversion function templates use AddTemplateConversionCandidate"); - + QualType ConvType = Conversion->getConversionType().getNonReferenceType(); if (!CandidateSet.isNewCandidate(Conversion)) return; @@ -3082,7 +3100,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = false; Candidate.FinalConversion.setAsIdentityConversion(); - Candidate.FinalConversion.setFromType(Conversion->getConversionType()); + Candidate.FinalConversion.setFromType(ConvType); Candidate.FinalConversion.setAllToTypes(ToType); // Determine the implicit conversion sequence for the implicit @@ -3115,7 +3133,6 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, return; } - // To determine what the conversion from the result of calling the // conversion function to the type we're eventually trying to // convert to (ToType), we need to synthesize a call to the diff --git a/lib/Sema/SemaOverload.h b/lib/Sema/SemaOverload.h index 2b9604ac14..5e61111308 100644 --- a/lib/Sema/SemaOverload.h +++ b/lib/Sema/SemaOverload.h @@ -381,6 +381,33 @@ namespace clang { assert(isInitialized() && "querying uninitialized conversion"); return Kind(ConversionKind); } + + /// \brief Return a ranking of the implicit conversion sequence + /// kind, where smaller ranks represent better conversion + /// sequences. + /// + /// In particular, this routine gives user-defined conversion + /// sequences and ambiguous conversion sequences the same rank, + /// per C++ [over.best.ics]p10. + unsigned getKindRank() const { + switch (getKind()) { + case StandardConversion: + return 0; + + case UserDefinedConversion: + case AmbiguousConversion: + return 1; + + case EllipsisConversion: + return 2; + + case BadConversion: + return 3; + } + + return 3; + } + bool isBad() const { return getKind() == BadConversion; } bool isStandard() const { return getKind() == StandardConversion; } bool isEllipsis() const { return getKind() == EllipsisConversion; } |