diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp | 3982 |
1 files changed, 2535 insertions, 1447 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp index 11b4bb3..6fb789c 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaOverload.cpp @@ -23,8 +23,10 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" #include "clang/AST/TypeOrdering.h" #include "clang/Basic/PartialDiagnostic.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/STLExtras.h" #include <algorithm> @@ -32,9 +34,20 @@ namespace clang { using namespace sema; +/// A convenience routine for creating a decayed reference to a +/// function. +static Expr * +CreateFunctionRefExpr(Sema &S, FunctionDecl *Fn, + SourceLocation Loc = SourceLocation()) { + Expr *E = new (S.Context) DeclRefExpr(Fn, Fn->getType(), VK_LValue, Loc); + S.DefaultFunctionArrayConversion(E); + return E; +} + static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, bool InOverloadResolution, - StandardConversionSequence &SCS); + StandardConversionSequence &SCS, + bool CStyle); static OverloadingResult IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, UserDefinedConversionSequence& User, @@ -158,7 +171,10 @@ void StandardConversionSequence::setAsIdentityConversion() { DeprecatedStringLiteralToCharPtr = false; ReferenceBinding = false; DirectBinding = false; - RRefBinding = false; + IsLvalueReference = true; + BindsToFunctionLvalue = false; + BindsToRvalue = false; + BindsImplicitObjectArgumentWithoutRefQualifier = false; CopyConstructor = 0; } @@ -189,6 +205,7 @@ bool StandardConversionSequence::isPointerConversionToBool() const { (getFromType()->isPointerType() || getFromType()->isObjCObjectPointerType() || getFromType()->isBlockPointerType() || + getFromType()->isNullPtrType() || First == ICK_Array_To_Pointer || First == ICK_Function_To_Pointer)) return true; @@ -323,7 +340,7 @@ namespace { TemplateArgument SecondArg; }; } - + /// \brief Convert from Sema's representation of template deduction information /// to the form used in overload-candidate information. OverloadCandidate::DeductionFailureInfo @@ -339,12 +356,12 @@ static MakeDeductionFailureInfo(ASTContext &Context, case Sema::TDK_TooManyArguments: case Sema::TDK_TooFewArguments: break; - + case Sema::TDK_Incomplete: case Sema::TDK_InvalidExplicitArguments: Result.Data = Info.Param.getOpaqueValue(); break; - + case Sema::TDK_Inconsistent: case Sema::TDK_Underqualified: { // FIXME: Should allocate from normal heap so that we can free this later. @@ -355,16 +372,16 @@ static MakeDeductionFailureInfo(ASTContext &Context, Result.Data = Saved; break; } - + case Sema::TDK_SubstitutionFailure: Result.Data = Info.take(); break; - + case Sema::TDK_NonDeducedMismatch: case Sema::TDK_FailedOverloadResolution: - break; + break; } - + return Result; } @@ -377,7 +394,7 @@ void OverloadCandidate::DeductionFailureInfo::Destroy() { case Sema::TDK_TooFewArguments: case Sema::TDK_InvalidExplicitArguments: break; - + case Sema::TDK_Inconsistent: case Sema::TDK_Underqualified: // FIXME: Destroy the data? @@ -388,15 +405,15 @@ void OverloadCandidate::DeductionFailureInfo::Destroy() { // FIXME: Destroy the template arugment list? Data = 0; break; - + // Unhandled case Sema::TDK_NonDeducedMismatch: case Sema::TDK_FailedOverloadResolution: break; } } - -TemplateParameter + +TemplateParameter OverloadCandidate::DeductionFailureInfo::getTemplateParameter() { switch (static_cast<Sema::TemplateDeductionResult>(Result)) { case Sema::TDK_Success: @@ -405,24 +422,24 @@ OverloadCandidate::DeductionFailureInfo::getTemplateParameter() { case Sema::TDK_TooFewArguments: case Sema::TDK_SubstitutionFailure: return TemplateParameter(); - + case Sema::TDK_Incomplete: case Sema::TDK_InvalidExplicitArguments: - return TemplateParameter::getFromOpaqueValue(Data); + return TemplateParameter::getFromOpaqueValue(Data); case Sema::TDK_Inconsistent: case Sema::TDK_Underqualified: return static_cast<DFIParamWithArguments*>(Data)->Param; - + // Unhandled case Sema::TDK_NonDeducedMismatch: case Sema::TDK_FailedOverloadResolution: break; } - + return TemplateParameter(); } - + TemplateArgumentList * OverloadCandidate::DeductionFailureInfo::getTemplateArgumentList() { switch (static_cast<Sema::TemplateDeductionResult>(Result)) { @@ -438,7 +455,7 @@ OverloadCandidate::DeductionFailureInfo::getTemplateArgumentList() { case Sema::TDK_SubstitutionFailure: return static_cast<TemplateArgumentList*>(Data); - + // Unhandled case Sema::TDK_NonDeducedMismatch: case Sema::TDK_FailedOverloadResolution: @@ -461,16 +478,16 @@ const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() { case Sema::TDK_Inconsistent: case Sema::TDK_Underqualified: - return &static_cast<DFIParamWithArguments*>(Data)->FirstArg; + return &static_cast<DFIParamWithArguments*>(Data)->FirstArg; // Unhandled case Sema::TDK_NonDeducedMismatch: case Sema::TDK_FailedOverloadResolution: break; } - + return 0; -} +} const TemplateArgument * OverloadCandidate::DeductionFailureInfo::getSecondArg() { @@ -493,7 +510,7 @@ OverloadCandidate::DeductionFailureInfo::getSecondArg() { case Sema::TDK_FailedOverloadResolution: break; } - + return 0; } @@ -501,7 +518,7 @@ void OverloadCandidateSet::clear() { inherited::clear(); Functions.clear(); } - + // IsOverload - Determine whether the given New declaration is an // overload of the declarations in Old. This routine returns false if // New and Old cannot be overloaded, e.g., if New has the same @@ -582,10 +599,12 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old, Match = *I; return Ovl_Match; } - } else if (isa<UsingDecl>(OldD) || isa<TagDecl>(OldD)) { + } else if (isa<UsingDecl>(OldD)) { // We can overload with these, which can show up when doing // redeclaration checks for UsingDecls. assert(Old.getLookupKind() == LookupUsingDeclName); + } else if (isa<TagDecl>(OldD)) { + // We can always overload with tags by hiding them. } else if (isa<UnresolvedUsingValueDecl>(OldD)) { // Optimistically assume that an unresolved using decl will // overload; if it doesn't, we'll have to diagnose during @@ -632,8 +651,8 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, isa<FunctionNoProtoType>(NewQType.getTypePtr())) return false; - FunctionProtoType* OldType = cast<FunctionProtoType>(OldQType); - FunctionProtoType* NewType = cast<FunctionProtoType>(NewQType); + const FunctionProtoType* OldType = cast<FunctionProtoType>(OldQType); + const FunctionProtoType* NewType = cast<FunctionProtoType>(NewQType); // The signature of a function includes the types of its // parameters (C++ 1.3.10), which includes the presence or absence @@ -664,7 +683,7 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, return true; // If the function is a class member, its signature includes the - // cv-qualifiers (if any) on the function itself. + // cv-qualifiers (if any) and ref-qualifier (if any) on the function itself. // // As part of this, also check whether one of the member functions // is static, in which case they are not overloads (C++ @@ -675,9 +694,26 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New); if (OldMethod && NewMethod && !OldMethod->isStatic() && !NewMethod->isStatic() && - OldMethod->getTypeQualifiers() != NewMethod->getTypeQualifiers()) + (OldMethod->getTypeQualifiers() != NewMethod->getTypeQualifiers() || + OldMethod->getRefQualifier() != NewMethod->getRefQualifier())) { + if (!UseUsingDeclRules && + OldMethod->getRefQualifier() != NewMethod->getRefQualifier() && + (OldMethod->getRefQualifier() == RQ_None || + NewMethod->getRefQualifier() == RQ_None)) { + // C++0x [over.load]p2: + // - Member function declarations with the same name and the same + // parameter-type-list as well as member function template + // declarations with the same name, the same parameter-type-list, and + // the same template parameter lists cannot be overloaded if any of + // them, but not all, have a ref-qualifier (8.3.5). + Diag(NewMethod->getLocation(), diag::err_ref_qualifier_overload) + << NewMethod->getRefQualifier() << OldMethod->getRefQualifier(); + Diag(OldMethod->getLocation(), diag::note_previous_declaration); + } + return true; - + } + // The signatures match; this is not an overload. return false; } @@ -708,11 +744,12 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, static ImplicitConversionSequence TryImplicitConversion(Sema &S, Expr *From, QualType ToType, bool SuppressUserConversions, - bool AllowExplicit, - bool InOverloadResolution) { + bool AllowExplicit, + bool InOverloadResolution, + bool CStyle) { ImplicitConversionSequence ICS; if (IsStandardConversion(S, From, ToType, InOverloadResolution, - ICS.Standard)) { + ICS.Standard, CStyle)) { ICS.setStandard(); return ICS; } @@ -737,20 +774,20 @@ TryImplicitConversion(Sema &S, Expr *From, QualType ToType, 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 (!S.Context.hasSameUnqualifiedType(FromType, ToType)) ICS.Standard.Second = ICK_Derived_To_Base; - + return ICS; } - + if (SuppressUserConversions) { // We're not in the case above, so there is no conversion that // we can perform. @@ -823,12 +860,14 @@ bool Sema::TryImplicitConversion(InitializationSequence &Sequence, Expr *Initializer, bool SuppressUserConversions, bool AllowExplicitConversions, - bool InOverloadResolution) { + bool InOverloadResolution, + bool CStyle) { ImplicitConversionSequence ICS = clang::TryImplicitConversion(*this, Initializer, Entity.getType(), SuppressUserConversions, - AllowExplicitConversions, - InOverloadResolution); + AllowExplicitConversions, + InOverloadResolution, + CStyle); if (ICS.isBad()) return true; // Perform the actual conversion. @@ -856,34 +895,66 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, ICS = clang::TryImplicitConversion(*this, From, ToType, /*SuppressUserConversions=*/false, AllowExplicit, - /*InOverloadResolution=*/false); + /*InOverloadResolution=*/false, + /*CStyle=*/false); return PerformImplicitConversion(From, ToType, ICS, Action); } - -/// \brief Determine whether the conversion from FromType to ToType is a valid + +/// \brief Determine whether the conversion from FromType to ToType is a valid /// conversion that strips "noreturn" off the nested function type. -static bool IsNoReturnConversion(ASTContext &Context, QualType FromType, +static bool IsNoReturnConversion(ASTContext &Context, QualType FromType, QualType ToType, QualType &ResultTy) { if (Context.hasSameUnqualifiedType(FromType, ToType)) return false; - - // Strip the noreturn off the type we're converting from; noreturn can - // safely be removed. - FromType = Context.getNoReturnType(FromType, false); - if (!Context.hasSameUnqualifiedType(FromType, ToType)) - return false; - ResultTy = FromType; + // Permit the conversion F(t __attribute__((noreturn))) -> F(t) + // where F adds one of the following at most once: + // - a pointer + // - a member pointer + // - a block pointer + CanQualType CanTo = Context.getCanonicalType(ToType); + CanQualType CanFrom = Context.getCanonicalType(FromType); + Type::TypeClass TyClass = CanTo->getTypeClass(); + if (TyClass != CanFrom->getTypeClass()) return false; + if (TyClass != Type::FunctionProto && TyClass != Type::FunctionNoProto) { + if (TyClass == Type::Pointer) { + CanTo = CanTo.getAs<PointerType>()->getPointeeType(); + CanFrom = CanFrom.getAs<PointerType>()->getPointeeType(); + } else if (TyClass == Type::BlockPointer) { + CanTo = CanTo.getAs<BlockPointerType>()->getPointeeType(); + CanFrom = CanFrom.getAs<BlockPointerType>()->getPointeeType(); + } else if (TyClass == Type::MemberPointer) { + CanTo = CanTo.getAs<MemberPointerType>()->getPointeeType(); + CanFrom = CanFrom.getAs<MemberPointerType>()->getPointeeType(); + } else { + return false; + } + + TyClass = CanTo->getTypeClass(); + if (TyClass != CanFrom->getTypeClass()) return false; + if (TyClass != Type::FunctionProto && TyClass != Type::FunctionNoProto) + return false; + } + + const FunctionType *FromFn = cast<FunctionType>(CanFrom); + FunctionType::ExtInfo EInfo = FromFn->getExtInfo(); + if (!EInfo.getNoReturn()) return false; + + FromFn = Context.adjustFunctionType(FromFn, EInfo.withNoReturn(false)); + assert(QualType(FromFn, 0).isCanonical()); + if (QualType(FromFn, 0) != CanTo) return false; + + ResultTy = ToType; return true; } - + /// \brief Determine whether the conversion from FromType to ToType is a valid /// vector conversion. /// /// \param ICK Will be set to the vector conversion kind, if this is a vector /// conversion. -static bool IsVectorConversion(ASTContext &Context, QualType FromType, - QualType ToType, ImplicitConversionKind &ICK) { +static bool IsVectorConversion(ASTContext &Context, QualType FromType, + QualType ToType, ImplicitConversionKind &ICK) { // We need at least one of these types to be a vector type to have a vector // conversion. if (!ToType->isVectorType() && !FromType->isVectorType()) @@ -899,7 +970,7 @@ static bool IsVectorConversion(ASTContext &Context, QualType FromType, // identity conversion. if (FromType->isExtVectorType()) return false; - + // Vector splat from any arithmetic type to a vector. if (FromType->isArithmeticType()) { ICK = ICK_Vector_Splat; @@ -922,7 +993,7 @@ static bool IsVectorConversion(ASTContext &Context, QualType FromType, return false; } - + /// IsStandardConversion - Determines whether there is a standard /// conversion sequence (C++ [conv], C++ [over.ics.scs]) from the /// expression From to the type ToType. Standard conversion sequences @@ -933,9 +1004,10 @@ static bool IsVectorConversion(ASTContext &Context, QualType FromType, /// routine will return false and the value of SCS is unspecified. static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, bool InOverloadResolution, - StandardConversionSequence &SCS) { + StandardConversionSequence &SCS, + bool CStyle) { QualType FromType = From->getType(); - + // Standard conversions (C++ [conv]) SCS.setAsIdentityConversion(); SCS.DeprecatedStringLiteralToCharPtr = false; @@ -959,38 +1031,53 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, if (FromType == S.Context.OverloadTy) { DeclAccessPair AccessPair; if (FunctionDecl *Fn - = S.ResolveAddressOfOverloadedFunction(From, ToType, false, + = S.ResolveAddressOfOverloadedFunction(From, ToType, false, AccessPair)) { // We were able to resolve the address of the overloaded function, // so we can convert to the type of that function. FromType = Fn->getType(); + + // we can sometimes resolve &foo<int> regardless of ToType, so check + // if the type matches (identity) or we are converting to bool + if (!S.Context.hasSameUnqualifiedType( + S.ExtractUnqualifiedFunctionType(ToType), FromType)) { + QualType resultTy; + // if the function type matches except for [[noreturn]], it's ok + if (!IsNoReturnConversion(S.Context, FromType, + S.ExtractUnqualifiedFunctionType(ToType), resultTy)) + // otherwise, only a boolean conversion is standard + if (!ToType->isBooleanType()) + return false; + + } + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) { if (!Method->isStatic()) { - Type *ClassType + const Type *ClassType = S.Context.getTypeDeclType(Method->getParent()).getTypePtr(); FromType = S.Context.getMemberPointerType(FromType, ClassType); } } - + // If the "from" expression takes the address of the overloaded // function, update the type of the resulting expression accordingly. if (FromType->getAs<FunctionType>()) if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(From->IgnoreParens())) if (UnOp->getOpcode() == UO_AddrOf) FromType = S.Context.getPointerType(FromType); - + // Check that we've computed the proper type after overload resolution. assert(S.Context.hasSameType(FromType, S.FixOverloadedFunctionReference(From, AccessPair, Fn)->getType())); } else { return false; } - } + } // Lvalue-to-rvalue conversion (C++ 4.1): // An lvalue (3.10) of a non-function, non-array type T can be // converted to an rvalue. - Expr::isLvalueResult argIsLvalue = From->isLvalue(S.Context); - if (argIsLvalue == Expr::LV_Valid && + bool argIsLValue = From->isLValue(); + if (argIsLValue && !FromType->isFunctionType() && !FromType->isArrayType() && S.Context.getCanonicalType(FromType) != S.Context.OverloadTy) { SCS.First = ICK_Lvalue_To_Rvalue; @@ -1022,7 +1109,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, SCS.setAllToTypes(FromType); return true; } - } else if (FromType->isFunctionType() && argIsLvalue == Expr::LV_Valid) { + } else if (FromType->isFunctionType() && argIsLValue) { // Function-to-pointer conversion (C++ 4.3). SCS.First = ICK_Function_To_Pointer; @@ -1060,17 +1147,26 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // Complex promotion (Clang extension) SCS.Second = ICK_Complex_Promotion; FromType = ToType.getUnqualifiedType(); - } else if (FromType->isIntegralOrEnumerationType() && + } else if (ToType->isBooleanType() && + (FromType->isArithmeticType() || + FromType->isAnyPointerType() || + FromType->isBlockPointerType() || + FromType->isMemberPointerType() || + FromType->isNullPtrType())) { + // Boolean conversions (C++ 4.12). + SCS.Second = ICK_Boolean_Conversion; + FromType = S.Context.BoolTy; + } else if (FromType->isIntegralOrUnscopedEnumerationType() && ToType->isIntegralType(S.Context)) { // Integral conversions (C++ 4.7). SCS.Second = ICK_Integral_Conversion; FromType = ToType.getUnqualifiedType(); - } else if (FromType->isComplexType() && ToType->isComplexType()) { + } else if (FromType->isAnyComplexType() && ToType->isComplexType()) { // Complex conversions (C99 6.3.1.6) SCS.Second = ICK_Complex_Conversion; FromType = ToType.getUnqualifiedType(); - } else if ((FromType->isComplexType() && ToType->isArithmeticType()) || - (ToType->isComplexType() && FromType->isArithmeticType())) { + } else if ((FromType->isAnyComplexType() && ToType->isArithmeticType()) || + (ToType->isAnyComplexType() && FromType->isArithmeticType())) { // Complex-real conversions (C99 6.3.1.7) SCS.Second = ICK_Complex_Real; FromType = ToType.getUnqualifiedType(); @@ -1078,32 +1174,24 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // Floating point conversions (C++ 4.8). SCS.Second = ICK_Floating_Conversion; FromType = ToType.getUnqualifiedType(); - } else if ((FromType->isRealFloatingType() && - ToType->isIntegralType(S.Context) && !ToType->isBooleanType()) || - (FromType->isIntegralOrEnumerationType() && + } else if ((FromType->isRealFloatingType() && + ToType->isIntegralType(S.Context)) || + (FromType->isIntegralOrUnscopedEnumerationType() && ToType->isRealFloatingType())) { // Floating-integral conversions (C++ 4.9). SCS.Second = ICK_Floating_Integral; FromType = ToType.getUnqualifiedType(); + } else if (S.IsBlockPointerConversion(FromType, ToType, FromType)) { + SCS.Second = ICK_Block_Pointer_Conversion; } else if (S.IsPointerConversion(From, FromType, ToType, InOverloadResolution, FromType, IncompatibleObjC)) { // Pointer conversions (C++ 4.10). SCS.Second = ICK_Pointer_Conversion; SCS.IncompatibleObjC = IncompatibleObjC; - } else if (S.IsMemberPointerConversion(From, FromType, ToType, + } else if (S.IsMemberPointerConversion(From, FromType, ToType, InOverloadResolution, FromType)) { // Pointer to member conversions (4.11). SCS.Second = ICK_Pointer_Member; - } else if (ToType->isBooleanType() && - (FromType->isArithmeticType() || - FromType->isEnumeralType() || - FromType->isAnyPointerType() || - FromType->isBlockPointerType() || - FromType->isMemberPointerType() || - FromType->isNullPtrType())) { - // Boolean conversions (C++ 4.12). - SCS.Second = ICK_Boolean_Conversion; - FromType = S.Context.BoolTy; } else if (IsVectorConversion(S.Context, FromType, ToType, SecondICK)) { SCS.Second = SecondICK; FromType = ToType.getUnqualifiedType(); @@ -1124,7 +1212,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, QualType CanonFrom; QualType CanonTo; // The third conversion can be a qualification conversion (C++ 4p1). - if (S.IsQualificationConversion(FromType, ToType)) { + if (S.IsQualificationConversion(FromType, ToType, CStyle)) { SCS.Third = ICK_Qualification; FromType = ToType; CanonFrom = S.Context.getCanonicalType(FromType); @@ -1139,7 +1227,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // a conversion. [...] CanonFrom = S.Context.getCanonicalType(FromType); CanonTo = S.Context.getCanonicalType(ToType); - if (CanonFrom.getLocalUnqualifiedType() + if (CanonFrom.getLocalUnqualifiedType() == CanonTo.getLocalUnqualifiedType() && (CanonFrom.getLocalCVRQualifiers() != CanonTo.getLocalCVRQualifiers() || CanonFrom.getObjCGCAttr() != CanonTo.getObjCGCAttr())) { @@ -1187,23 +1275,47 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) { return To->getKind() == BuiltinType::UInt; } - // An rvalue of type wchar_t (3.9.1) or an enumeration type (7.2) - // can be converted to an rvalue of the first of the following types - // that can represent all the values of its underlying type: int, - // unsigned int, long, or unsigned long (C++ 4.5p2). + // C++0x [conv.prom]p3: + // A prvalue of an unscoped enumeration type whose underlying type is not + // fixed (7.2) can be converted to an rvalue a prvalue of the first of the + // following types that can represent all the values of the enumeration + // (i.e., the values in the range bmin to bmax as described in 7.2): int, + // unsigned int, long int, unsigned long int, long long int, or unsigned + // long long int. If none of the types in that list can represent all the + // values of the enumeration, an rvalue a prvalue of an unscoped enumeration + // type can be converted to an rvalue a prvalue of the extended integer type + // with lowest integer conversion rank (4.13) greater than the rank of long + // long in which all the values of the enumeration can be represented. If + // there are two such extended types, the signed one is chosen. + if (const EnumType *FromEnumType = FromType->getAs<EnumType>()) { + // C++0x 7.2p9: Note that this implicit enum to int conversion is not + // provided for a scoped enumeration. + if (FromEnumType->getDecl()->isScoped()) + return false; - // We pre-calculate the promotion type for enum types. - if (const EnumType *FromEnumType = FromType->getAs<EnumType>()) - if (ToType->isIntegerType()) + // We have already pre-calculated the promotion type, so this is trivial. + if (ToType->isIntegerType() && + !RequireCompleteType(From->getLocStart(), FromType, PDiag())) return Context.hasSameUnqualifiedType(ToType, FromEnumType->getDecl()->getPromotionType()); + } - if (FromType->isWideCharType() && ToType->isIntegerType()) { + // C++0x [conv.prom]p2: + // A prvalue of type char16_t, char32_t, or wchar_t (3.9.1) can be converted + // to an rvalue a prvalue of the first of the following types that can + // represent all the values of its underlying type: int, unsigned int, + // long int, unsigned long int, long long int, or unsigned long long int. + // If none of the types in that list can represent all the values of its + // underlying type, an rvalue a prvalue of type char16_t, char32_t, + // or wchar_t can be converted to an rvalue a prvalue of its underlying + // type. + if (FromType->isAnyCharacterType() && !FromType->isCharType() && + ToType->isIntegerType()) { // Determine whether the type we're converting from is signed or // unsigned. bool FromIsSigned; uint64_t FromSize = Context.getTypeSize(FromType); - + // FIXME: Is wchar_t signed or unsigned? We assume it's signed for now. FromIsSigned = true; @@ -1321,10 +1433,19 @@ bool Sema::IsComplexPromotion(QualType FromType, QualType ToType) { /// if non-empty, will be a pointer to ToType that may or may not have /// the right set of qualifiers on its pointee. static QualType -BuildSimilarlyQualifiedPointerType(const PointerType *FromPtr, +BuildSimilarlyQualifiedPointerType(const Type *FromPtr, QualType ToPointee, QualType ToType, ASTContext &Context) { - QualType CanonFromPointee = Context.getCanonicalType(FromPtr->getPointeeType()); + assert((FromPtr->getTypeClass() == Type::Pointer || + FromPtr->getTypeClass() == Type::ObjCObjectPointer) && + "Invalid similarly-qualified pointer type"); + + /// \brief Conversions to 'id' subsume cv-qualifier conversions. + if (ToType->isObjCIdType() || ToType->isObjCQualifiedIdType()) + return ToType.getUnqualifiedType(); + + QualType CanonFromPointee + = Context.getCanonicalType(FromPtr->getPointeeType()); QualType CanonToPointee = Context.getCanonicalType(ToPointee); Qualifiers Quals = CanonFromPointee.getQualifiers(); @@ -1336,34 +1457,20 @@ BuildSimilarlyQualifiedPointerType(const PointerType *FromPtr, // Build a pointer to ToPointee. It has the right qualifiers // already. + if (isa<ObjCObjectPointerType>(ToType)) + return Context.getObjCObjectPointerType(ToPointee); return Context.getPointerType(ToPointee); } // Just build a canonical type that has the right qualifiers. - return Context.getPointerType( - Context.getQualifiedType(CanonToPointee.getLocalUnqualifiedType(), - Quals)); -} + QualType QualifiedCanonToPointee + = Context.getQualifiedType(CanonToPointee.getLocalUnqualifiedType(), Quals); -/// BuildSimilarlyQualifiedObjCObjectPointerType - In a pointer conversion from -/// the FromType, which is an objective-c pointer, to ToType, which may or may -/// not have the right set of qualifiers. -static QualType -BuildSimilarlyQualifiedObjCObjectPointerType(QualType FromType, - QualType ToType, - ASTContext &Context) { - QualType CanonFromType = Context.getCanonicalType(FromType); - QualType CanonToType = Context.getCanonicalType(ToType); - Qualifiers Quals = CanonFromType.getQualifiers(); - - // Exact qualifier match -> return the pointer type we're converting to. - if (CanonToType.getLocalQualifiers() == Quals) - return ToType; - - // Just build a canonical type that has the right qualifiers. - return Context.getQualifiedType(CanonToType.getLocalUnqualifiedType(), Quals); + if (isa<ObjCObjectPointerType>(ToType)) + return Context.getObjCObjectPointerType(QualifiedCanonToPointee); + return Context.getPointerType(QualifiedCanonToPointee); } - + static bool isNullPointerConstantForConversion(Expr *Expr, bool InOverloadResolution, ASTContext &Context) { @@ -1399,7 +1506,8 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType, QualType& ConvertedType, bool &IncompatibleObjC) { IncompatibleObjC = false; - if (isObjCPointerConversion(FromType, ToType, ConvertedType, IncompatibleObjC)) + if (isObjCPointerConversion(FromType, ToType, ConvertedType, + IncompatibleObjC)) return true; // Conversion from a null pointer constant to any Objective-C pointer type. @@ -1441,14 +1549,15 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType, return true; } - // Beyond this point, both types need to be pointers + // Beyond this point, both types need to be pointers // , including objective-c pointers. QualType ToPointeeType = ToTypePtr->getPointeeType(); if (FromType->isObjCObjectPointerType() && ToPointeeType->isVoidType()) { - ConvertedType = BuildSimilarlyQualifiedObjCObjectPointerType(FromType, + ConvertedType = BuildSimilarlyQualifiedPointerType( + FromType->getAs<ObjCObjectPointerType>(), + ToPointeeType, ToType, Context); return true; - } const PointerType *FromTypePtr = FromType->getAs<PointerType>(); if (!FromTypePtr) @@ -1456,7 +1565,7 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType, QualType FromPointeeType = FromTypePtr->getPointeeType(); - // If the unqualified pointee types are the same, this can't be a + // If the unqualified pointee types are the same, this can't be a // pointer conversion, so don't do all of the work below. if (Context.hasSameUnqualifiedType(FromPointeeType, ToPointeeType)) return false; @@ -1517,13 +1626,20 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, bool &IncompatibleObjC) { if (!getLangOptions().ObjC1) return false; - + // First, we handle all conversions on ObjC object pointer types. - const ObjCObjectPointerType* ToObjCPtr = ToType->getAs<ObjCObjectPointerType>(); + const ObjCObjectPointerType* ToObjCPtr = + ToType->getAs<ObjCObjectPointerType>(); const ObjCObjectPointerType *FromObjCPtr = FromType->getAs<ObjCObjectPointerType>(); if (ToObjCPtr && FromObjCPtr) { + // If the pointee types are the same (ignoring qualifications), + // then this is not a pointer conversion. + if (Context.hasSameUnqualifiedType(ToObjCPtr->getPointeeType(), + FromObjCPtr->getPointeeType())) + return false; + // Objective C++: We're able to convert between "id" or "Class" and a // pointer to any interface (in both directions). if (ToObjCPtr->isObjCBuiltinType() && FromObjCPtr->isObjCBuiltinType()) { @@ -1547,7 +1663,9 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, !ToObjCPtr->getPointeeType().isAtLeastAsQualifiedAs( FromObjCPtr->getPointeeType())) return false; - ConvertedType = ToType; + ConvertedType = BuildSimilarlyQualifiedPointerType(FromObjCPtr, + ToObjCPtr->getPointeeType(), + ToType, Context); return true; } @@ -1556,7 +1674,9 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, // interfaces, which is permitted. However, we're going to // complain about it. IncompatibleObjC = true; - ConvertedType = FromType; + ConvertedType = BuildSimilarlyQualifiedPointerType(FromObjCPtr, + ToObjCPtr->getPointeeType(), + ToType, Context); return true; } } @@ -1564,7 +1684,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, QualType ToPointeeType; if (const PointerType *ToCPtr = ToType->getAs<PointerType>()) ToPointeeType = ToCPtr->getPointeeType(); - else if (const BlockPointerType *ToBlockPtr = + else if (const BlockPointerType *ToBlockPtr = ToType->getAs<BlockPointerType>()) { // Objective C++: We're able to convert from a pointer to any object // to a block pointer type. @@ -1574,9 +1694,9 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, } ToPointeeType = ToBlockPtr->getPointeeType(); } - else if (FromType->getAs<BlockPointerType>() && + else if (FromType->getAs<BlockPointerType>() && ToObjCPtr && ToObjCPtr->isObjCBuiltinType()) { - // Objective C++: We're able to convert from a block pointer type to a + // Objective C++: We're able to convert from a block pointer type to a // pointer to any object. ConvertedType = ToType; return true; @@ -1587,7 +1707,8 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, QualType FromPointeeType; if (const PointerType *FromCPtr = FromType->getAs<PointerType>()) FromPointeeType = FromCPtr->getPointeeType(); - else if (const BlockPointerType *FromBlockPtr = FromType->getAs<BlockPointerType>()) + else if (const BlockPointerType *FromBlockPtr = + FromType->getAs<BlockPointerType>()) FromPointeeType = FromBlockPtr->getPointeeType(); else return false; @@ -1599,7 +1720,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, IncompatibleObjC)) { // We always complain about this conversion. IncompatibleObjC = true; - ConvertedType = ToType; + ConvertedType = Context.getPointerType(ConvertedType); return true; } // Allow conversion of pointee being objective-c pointer to another one; @@ -1608,10 +1729,10 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, ToPointeeType->getAs<ObjCObjectPointerType>() && isObjCPointerConversion(FromPointeeType, ToPointeeType, ConvertedType, IncompatibleObjC)) { - ConvertedType = ToType; + ConvertedType = Context.getPointerType(ConvertedType); return true; } - + // If we have pointers to functions or blocks, check whether the only // differences in the argument and result types are in Objective-C // pointer conversions. If so, we permit the conversion (but @@ -1677,17 +1798,102 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, return false; } - + +bool Sema::IsBlockPointerConversion(QualType FromType, QualType ToType, + QualType& ConvertedType) { + QualType ToPointeeType; + if (const BlockPointerType *ToBlockPtr = + ToType->getAs<BlockPointerType>()) + ToPointeeType = ToBlockPtr->getPointeeType(); + else + return false; + + QualType FromPointeeType; + if (const BlockPointerType *FromBlockPtr = + FromType->getAs<BlockPointerType>()) + FromPointeeType = FromBlockPtr->getPointeeType(); + else + return false; + // We have pointer to blocks, check whether the only + // differences in the argument and result types are in Objective-C + // pointer conversions. If so, we permit the conversion. + + const FunctionProtoType *FromFunctionType + = FromPointeeType->getAs<FunctionProtoType>(); + const FunctionProtoType *ToFunctionType + = ToPointeeType->getAs<FunctionProtoType>(); + + if (!FromFunctionType || !ToFunctionType) + return false; + + if (Context.hasSameType(FromPointeeType, ToPointeeType)) + return true; + + // Perform the quick checks that will tell us whether these + // function types are obviously different. + if (FromFunctionType->getNumArgs() != ToFunctionType->getNumArgs() || + FromFunctionType->isVariadic() != ToFunctionType->isVariadic()) + return false; + + FunctionType::ExtInfo FromEInfo = FromFunctionType->getExtInfo(); + FunctionType::ExtInfo ToEInfo = ToFunctionType->getExtInfo(); + if (FromEInfo != ToEInfo) + return false; + + bool IncompatibleObjC = false; + if (Context.hasSameType(FromFunctionType->getResultType(), + ToFunctionType->getResultType())) { + // Okay, the types match exactly. Nothing to do. + } else { + QualType RHS = FromFunctionType->getResultType(); + QualType LHS = ToFunctionType->getResultType(); + if ((!getLangOptions().CPlusPlus || !RHS->isRecordType()) && + !RHS.hasQualifiers() && LHS.hasQualifiers()) + LHS = LHS.getUnqualifiedType(); + + if (Context.hasSameType(RHS,LHS)) { + // OK exact match. + } else if (isObjCPointerConversion(RHS, LHS, + ConvertedType, IncompatibleObjC)) { + if (IncompatibleObjC) + return false; + // Okay, we have an Objective-C pointer conversion. + } + else + return false; + } + + // Check argument types. + for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumArgs(); + ArgIdx != NumArgs; ++ArgIdx) { + IncompatibleObjC = false; + QualType FromArgType = FromFunctionType->getArgType(ArgIdx); + QualType ToArgType = ToFunctionType->getArgType(ArgIdx); + if (Context.hasSameType(FromArgType, ToArgType)) { + // Okay, the types match exactly. Nothing to do. + } else if (isObjCPointerConversion(ToArgType, FromArgType, + ConvertedType, IncompatibleObjC)) { + if (IncompatibleObjC) + return false; + // Okay, we have an Objective-C pointer conversion. + } else + // Argument types are too different. Abort. + return false; + } + ConvertedType = ToType; + return true; +} + /// FunctionArgTypesAreEqual - This routine checks two function proto types /// for equlity of their argument types. Caller has already checked that /// they have same number of arguments. This routine assumes that Objective-C /// pointer types which only differ in their protocol qualifiers are equal. -bool Sema::FunctionArgTypesAreEqual(FunctionProtoType* OldType, - FunctionProtoType* NewType){ +bool Sema::FunctionArgTypesAreEqual(const FunctionProtoType *OldType, + const FunctionProtoType *NewType) { if (!getLangOptions().ObjC1) return std::equal(OldType->arg_type_begin(), OldType->arg_type_end(), NewType->arg_type_begin()); - + for (FunctionProtoType::arg_type_iterator O = OldType->arg_type_begin(), N = NewType->arg_type_begin(), E = OldType->arg_type_end(); O && (O != E); ++O, ++N) { @@ -1704,12 +1910,12 @@ bool Sema::FunctionArgTypesAreEqual(FunctionProtoType* OldType, } else if (const ObjCObjectPointerType *PTTo = ToType->getAs<ObjCObjectPointerType>()) { - if (const ObjCObjectPointerType *PTFr = + if (const ObjCObjectPointerType *PTFr = FromType->getAs<ObjCObjectPointerType>()) if (PTTo->getInterfaceDecl() == PTFr->getInterfaceDecl()) continue; } - return false; + return false; } } return true; @@ -1726,10 +1932,13 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType, CXXCastPath& BasePath, bool IgnoreBaseAccess) { QualType FromType = From->getType(); + bool IsCStyleOrFunctionalCast = IgnoreBaseAccess; + + Kind = CK_BitCast; if (CXXBoolLiteralExpr* LitBool = dyn_cast<CXXBoolLiteralExpr>(From->IgnoreParens())) - if (LitBool->getValue() == false) + if (!IsCStyleOrFunctionalCast && LitBool->getValue() == false) Diag(LitBool->getExprLoc(), diag::warn_init_pointer_from_false) << ToType; @@ -1747,13 +1956,13 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType, From->getSourceRange(), &BasePath, IgnoreBaseAccess)) return true; - + // The conversion was successful. Kind = CK_DerivedToBase; } } if (const ObjCObjectPointerType *FromPtrType = - FromType->getAs<ObjCObjectPointerType>()) + FromType->getAs<ObjCObjectPointerType>()) { if (const ObjCObjectPointerType *ToPtrType = ToType->getAs<ObjCObjectPointerType>()) { // Objective-C++ conversions are always okay. @@ -1761,8 +1970,14 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType, // Objective-C++ implicit conversions. if (FromPtrType->isObjCBuiltinType() || ToPtrType->isObjCBuiltinType()) return false; - + } } + + // We shouldn't fall into this case unless it's valid for other + // reasons. + if (From->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) + Kind = CK_NullToPointer; + return false; } @@ -1772,7 +1987,7 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType, /// If so, returns true and places the converted type (that might differ from /// ToType in its cv-qualifiers at some level) into ConvertedType. bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType, - QualType ToType, + QualType ToType, bool InOverloadResolution, QualType &ConvertedType) { const MemberPointerType *ToTypePtr = ToType->getAs<MemberPointerType>(); @@ -1796,9 +2011,10 @@ bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType, // where D is derived from B (C++ 4.11p2). QualType FromClass(FromTypePtr->getClass(), 0); QualType ToClass(ToTypePtr->getClass(), 0); - // FIXME: What happens when these are dependent? Is this function even called? - if (IsDerivedFrom(ToClass, FromClass)) { + if (!Context.hasSameUnqualifiedType(FromClass, ToClass) && + !RequireCompleteType(From->getLocStart(), ToClass, PDiag()) && + IsDerivedFrom(ToClass, FromClass)) { ConvertedType = Context.getMemberPointerType(FromTypePtr->getPointeeType(), ToClass.getTypePtr()); return true; @@ -1806,7 +2022,7 @@ bool Sema::IsMemberPointerConversion(Expr *From, QualType FromType, return false; } - + /// CheckMemberPointerConversion - Check the member pointer conversion from the /// expression From to the type ToType. This routine checks for ambiguous or /// virtual or inaccessible base-to-derived member pointer conversions @@ -1821,7 +2037,7 @@ bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType, const MemberPointerType *FromPtrType = FromType->getAs<MemberPointerType>(); if (!FromPtrType) { // This must be a null pointer to member pointer conversion - assert(From->isNullPointerConstant(Context, + assert(From->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull) && "Expr must be null pointer constant!"); Kind = CK_NullToMemberPointer; @@ -1876,7 +2092,8 @@ bool Sema::CheckMemberPointerConversion(Expr *From, QualType ToType, /// an rvalue of type FromType to ToType is a qualification conversion /// (C++ 4.4). bool -Sema::IsQualificationConversion(QualType FromType, QualType ToType) { +Sema::IsQualificationConversion(QualType FromType, QualType ToType, + bool CStyle) { FromType = Context.getCanonicalType(FromType); ToType = Context.getCanonicalType(ToType); @@ -1901,12 +2118,12 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType) { // -- for every j > 0, if const is in cv 1,j then const is in cv // 2,j, and similarly for volatile. - if (!ToType.isAtLeastAsQualifiedAs(FromType)) + if (!CStyle && !ToType.isAtLeastAsQualifiedAs(FromType)) return false; // -- if the cv 1,j and cv 2,j are different, then const is in // every cv for 0 < k < j. - if (FromType.getCVRQualifiers() != ToType.getCVRQualifiers() + if (!CStyle && FromType.getCVRQualifiers() != ToType.getCVRQualifiers() && !PreviousToQualsIncludeConst) return false; @@ -1977,13 +2194,13 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, = cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl()); else Constructor = cast<CXXConstructorDecl>(D); - + if (!Constructor->isInvalidDecl() && Constructor->isConvertingConstructor(AllowExplicit)) { if (ConstructorTmpl) S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, /*ExplicitArgs*/ 0, - &From, 1, CandidateSet, + &From, 1, CandidateSet, /*SuppressUserConversions=*/ !ConstructorsOnly); else @@ -2039,7 +2256,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, } OverloadCandidateSet::iterator Best; - switch (CandidateSet.BestViableFunction(S, From->getLocStart(), Best)) { + switch (CandidateSet.BestViableFunction(S, From->getLocStart(), Best, true)) { case OR_Success: // Record the standard conversion we used and the conversion function. if (CXXConstructorDecl *Constructor @@ -2058,6 +2275,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, User.EllipsisConversion = false; } User.ConversionFunction = Constructor; + User.FoundConversionFunction = Best->FoundDecl.getDecl(); User.After.setAsIdentityConversion(); User.After.setFromType(ThisType->getAs<PointerType>()->getPointeeType()); User.After.setAllToTypes(ToType); @@ -2072,6 +2290,7 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, // implicit object parameter of the conversion function. User.Before = Best->Conversions[0].Standard; User.ConversionFunction = Conversion; + User.FoundConversionFunction = Best->FoundDecl.getDecl(); User.EllipsisConversion = false; // C++ [over.ics.user]p2: @@ -2095,19 +2314,19 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType, case OR_Deleted: // No conversion here! We're done. return OR_Deleted; - + case OR_Ambiguous: return OR_Ambiguous; } return OR_No_Viable_Function; } - + bool Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) { ImplicitConversionSequence ICS; OverloadCandidateSet CandidateSet(From->getExprLoc()); - OverloadingResult OvResult = + OverloadingResult OvResult = IsUserDefinedConversion(*this, From, ToType, ICS.UserDefined, CandidateSet, false); if (OvResult == OR_Ambiguous) @@ -2121,7 +2340,7 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) { else return false; CandidateSet.NoteCandidates(*this, OCD_AllCandidates, &From, 1); - return true; + return true; } /// CompareImplicitConversionSequences - Compare two implicit @@ -2182,12 +2401,12 @@ static bool hasSimilarType(ASTContext &Context, QualType T1, QualType T2) { while (Context.UnwrapSimilarPointerTypes(T1, T2)) { Qualifiers Quals; T1 = Context.getUnqualifiedArrayType(T1, Quals); - T2 = Context.getUnqualifiedArrayType(T2, Quals); + T2 = Context.getUnqualifiedArrayType(T2, Quals); } - + return Context.hasSameUnqualifiedType(T1, T2); } - + // Per 13.3.3.2p3, compare the given standard conversion sequences to // determine if one is a proper subset of the other. static ImplicitConversionSequence::CompareKind @@ -2197,7 +2416,7 @@ compareStandardConversionSubsets(ASTContext &Context, ImplicitConversionSequence::CompareKind Result = ImplicitConversionSequence::Indistinguishable; - // the identity conversion sequence is considered to be a subsequence of + // the identity conversion sequence is considered to be a subsequence of // any non-identity conversion sequence if (SCS1.ReferenceBinding == SCS2.ReferenceBinding) { if (SCS1.isIdentityConversion() && !SCS2.isIdentityConversion()) @@ -2205,7 +2424,7 @@ compareStandardConversionSubsets(ASTContext &Context, else if (!SCS1.isIdentityConversion() && SCS2.isIdentityConversion()) return ImplicitConversionSequence::Worse; } - + if (SCS1.Second != SCS2.Second) { if (SCS1.Second == ICK_Identity) Result = ImplicitConversionSequence::Better; @@ -2230,10 +2449,37 @@ compareStandardConversionSubsets(ASTContext &Context, return Result == ImplicitConversionSequence::Better ? ImplicitConversionSequence::Indistinguishable : ImplicitConversionSequence::Worse; - + return ImplicitConversionSequence::Indistinguishable; } +/// \brief Determine whether one of the given reference bindings is better +/// than the other based on what kind of bindings they are. +static bool isBetterReferenceBindingKind(const StandardConversionSequence &SCS1, + const StandardConversionSequence &SCS2) { + // C++0x [over.ics.rank]p3b4: + // -- S1 and S2 are reference bindings (8.5.3) and neither refers to an + // implicit object parameter of a non-static member function declared + // without a ref-qualifier, and *either* S1 binds an rvalue reference + // to an rvalue and S2 binds an lvalue reference *or S1 binds an + // lvalue reference to a function lvalue and S2 binds an rvalue + // reference*. + // + // FIXME: Rvalue references. We're going rogue with the above edits, + // because the semantics in the current C++0x working paper (N3225 at the + // time of this writing) break the standard definition of std::forward + // and std::reference_wrapper when dealing with references to functions. + // Proposed wording changes submitted to CWG for consideration. + if (SCS1.BindsImplicitObjectArgumentWithoutRefQualifier || + SCS2.BindsImplicitObjectArgumentWithoutRefQualifier) + return false; + + return (!SCS1.IsLvalueReference && SCS1.BindsToRvalue && + SCS2.IsLvalueReference) || + (SCS1.IsLvalueReference && SCS1.BindsToFunctionLvalue && + !SCS2.IsLvalueReference); +} + /// CompareStandardConversionSequences - Compare two standard /// conversion sequences to determine whether one is better than the /// other or if they are indistinguishable (C++ 13.3.3.2p3). @@ -2339,17 +2585,11 @@ CompareStandardConversionSequences(Sema &S, return QualCK; if (SCS1.ReferenceBinding && SCS2.ReferenceBinding) { - // C++0x [over.ics.rank]p3b4: - // -- S1 and S2 are reference bindings (8.5.3) and neither refers to an - // implicit object parameter of a non-static member function declared - // without a ref-qualifier, and S1 binds an rvalue reference to an - // rvalue and S2 binds an lvalue reference. - // FIXME: We don't know if we're dealing with the implicit object parameter, - // or if the member function in this case has a ref qualifier. - // (Of course, we don't have ref qualifiers yet.) - if (SCS1.RRefBinding != SCS2.RRefBinding) - return SCS1.RRefBinding ? ImplicitConversionSequence::Better - : ImplicitConversionSequence::Worse; + // Check for a better reference binding based on the kind of bindings. + if (isBetterReferenceBindingKind(SCS1, SCS2)) + return ImplicitConversionSequence::Better; + else if (isBetterReferenceBindingKind(SCS2, SCS1)) + return ImplicitConversionSequence::Worse; // C++ [over.ics.rank]p3b4: // -- S1 and S2 are reference bindings (8.5.3), and the types to @@ -2365,8 +2605,8 @@ CompareStandardConversionSequences(Sema &S, QualType UnqualT1 = S.Context.getUnqualifiedArrayType(T1, T1Quals); QualType UnqualT2 = S.Context.getUnqualifiedArrayType(T2, T2Quals); if (UnqualT1 == UnqualT2) { - // If the type is an array type, promote the element qualifiers to the type - // for comparison. + // If the type is an array type, promote the element qualifiers to the + // type for comparison. if (isa<ArrayType>(T1) && T1Quals) T1 = S.Context.getQualifiedType(UnqualT1, T1Quals); if (isa<ArrayType>(T2) && T2Quals) @@ -2513,9 +2753,6 @@ CompareDerivedToBaseConversions(Sema &S, // If class B is derived directly or indirectly from class A and // class C is derived directly or indirectly from B, // - // For Objective-C, we let A, B, and C also be Objective-C - // interfaces. - // Compare based on pointer conversions. if (SCS1.Second == ICK_Pointer_Conversion && SCS2.Second == ICK_Pointer_Conversion && @@ -2531,24 +2768,12 @@ CompareDerivedToBaseConversions(Sema &S, QualType ToPointee2 = ToType2->getAs<PointerType>()->getPointeeType().getUnqualifiedType(); - const ObjCObjectType* FromIface1 = FromPointee1->getAs<ObjCObjectType>(); - const ObjCObjectType* FromIface2 = FromPointee2->getAs<ObjCObjectType>(); - const ObjCObjectType* ToIface1 = ToPointee1->getAs<ObjCObjectType>(); - const ObjCObjectType* ToIface2 = ToPointee2->getAs<ObjCObjectType>(); - // -- conversion of C* to B* is better than conversion of C* to A*, if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) { if (S.IsDerivedFrom(ToPointee1, ToPointee2)) return ImplicitConversionSequence::Better; else if (S.IsDerivedFrom(ToPointee2, ToPointee1)) return ImplicitConversionSequence::Worse; - - if (ToIface1 && ToIface2) { - if (S.Context.canAssignObjCInterfaces(ToIface2, ToIface1)) - return ImplicitConversionSequence::Better; - else if (S.Context.canAssignObjCInterfaces(ToIface1, ToIface2)) - return ImplicitConversionSequence::Worse; - } } // -- conversion of B* to A* is better than conversion of C* to A*, @@ -2557,27 +2782,90 @@ CompareDerivedToBaseConversions(Sema &S, return ImplicitConversionSequence::Better; else if (S.IsDerivedFrom(FromPointee1, FromPointee2)) return ImplicitConversionSequence::Worse; + } + } else if (SCS1.Second == ICK_Pointer_Conversion && + SCS2.Second == ICK_Pointer_Conversion) { + const ObjCObjectPointerType *FromPtr1 + = FromType1->getAs<ObjCObjectPointerType>(); + const ObjCObjectPointerType *FromPtr2 + = FromType2->getAs<ObjCObjectPointerType>(); + const ObjCObjectPointerType *ToPtr1 + = ToType1->getAs<ObjCObjectPointerType>(); + const ObjCObjectPointerType *ToPtr2 + = ToType2->getAs<ObjCObjectPointerType>(); + + if (FromPtr1 && FromPtr2 && ToPtr1 && ToPtr2) { + // Apply the same conversion ranking rules for Objective-C pointer types + // that we do for C++ pointers to class types. However, we employ the + // Objective-C pseudo-subtyping relationship used for assignment of + // Objective-C pointer types. + bool FromAssignLeft + = S.Context.canAssignObjCInterfaces(FromPtr1, FromPtr2); + bool FromAssignRight + = S.Context.canAssignObjCInterfaces(FromPtr2, FromPtr1); + bool ToAssignLeft + = S.Context.canAssignObjCInterfaces(ToPtr1, ToPtr2); + bool ToAssignRight + = S.Context.canAssignObjCInterfaces(ToPtr2, ToPtr1); + + // A conversion to an a non-id object pointer type or qualified 'id' + // type is better than a conversion to 'id'. + if (ToPtr1->isObjCIdType() && + (ToPtr2->isObjCQualifiedIdType() || ToPtr2->getInterfaceDecl())) + return ImplicitConversionSequence::Worse; + if (ToPtr2->isObjCIdType() && + (ToPtr1->isObjCQualifiedIdType() || ToPtr1->getInterfaceDecl())) + return ImplicitConversionSequence::Better; + + // A conversion to a non-id object pointer type is better than a + // conversion to a qualified 'id' type + if (ToPtr1->isObjCQualifiedIdType() && ToPtr2->getInterfaceDecl()) + return ImplicitConversionSequence::Worse; + if (ToPtr2->isObjCQualifiedIdType() && ToPtr1->getInterfaceDecl()) + return ImplicitConversionSequence::Better; + + // A conversion to an a non-Class object pointer type or qualified 'Class' + // type is better than a conversion to 'Class'. + if (ToPtr1->isObjCClassType() && + (ToPtr2->isObjCQualifiedClassType() || ToPtr2->getInterfaceDecl())) + return ImplicitConversionSequence::Worse; + if (ToPtr2->isObjCClassType() && + (ToPtr1->isObjCQualifiedClassType() || ToPtr1->getInterfaceDecl())) + return ImplicitConversionSequence::Better; + + // A conversion to a non-Class object pointer type is better than a + // conversion to a qualified 'Class' type. + if (ToPtr1->isObjCQualifiedClassType() && ToPtr2->getInterfaceDecl()) + return ImplicitConversionSequence::Worse; + if (ToPtr2->isObjCQualifiedClassType() && ToPtr1->getInterfaceDecl()) + return ImplicitConversionSequence::Better; - if (FromIface1 && FromIface2) { - if (S.Context.canAssignObjCInterfaces(FromIface1, FromIface2)) - return ImplicitConversionSequence::Better; - else if (S.Context.canAssignObjCInterfaces(FromIface2, FromIface1)) - return ImplicitConversionSequence::Worse; - } + // -- "conversion of C* to B* is better than conversion of C* to A*," + if (S.Context.hasSameType(FromType1, FromType2) && + !FromPtr1->isObjCIdType() && !FromPtr1->isObjCClassType() && + (ToAssignLeft != ToAssignRight)) + return ToAssignLeft? ImplicitConversionSequence::Worse + : ImplicitConversionSequence::Better; + + // -- "conversion of B* to A* is better than conversion of C* to A*," + if (S.Context.hasSameUnqualifiedType(ToType1, ToType2) && + (FromAssignLeft != FromAssignRight)) + return FromAssignLeft? ImplicitConversionSequence::Better + : ImplicitConversionSequence::Worse; } } - + // Ranking of member-pointer types. if (SCS1.Second == ICK_Pointer_Member && SCS2.Second == ICK_Pointer_Member && FromType1->isMemberPointerType() && FromType2->isMemberPointerType() && ToType1->isMemberPointerType() && ToType2->isMemberPointerType()) { - const MemberPointerType * FromMemPointer1 = + const MemberPointerType * FromMemPointer1 = FromType1->getAs<MemberPointerType>(); - const MemberPointerType * ToMemPointer1 = + const MemberPointerType * ToMemPointer1 = ToType1->getAs<MemberPointerType>(); - const MemberPointerType * FromMemPointer2 = + const MemberPointerType * FromMemPointer2 = FromType2->getAs<MemberPointerType>(); - const MemberPointerType * ToMemPointer2 = + const MemberPointerType * ToMemPointer2 = ToType2->getAs<MemberPointerType>(); const Type *FromPointeeType1 = FromMemPointer1->getClass(); const Type *ToPointeeType1 = ToMemPointer1->getClass(); @@ -2602,7 +2890,7 @@ CompareDerivedToBaseConversions(Sema &S, return ImplicitConversionSequence::Worse; } } - + 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 @@ -2708,10 +2996,6 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, CXXRecordDecl *T2RecordDecl = dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl()); - QualType ToType - = AllowRvalues? DeclType->getAs<ReferenceType>()->getPointeeType() - : DeclType; - OverloadCandidateSet CandidateSet(DeclLoc); const UnresolvedSetImpl *Conversions = T2RecordDecl->getVisibleConversionFunctions(); @@ -2730,20 +3014,22 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, else Conv = cast<CXXConversionDecl>(D); - // If this is an explicit conversion, and we're not allowed to consider + // If this is an explicit conversion, and we're not allowed to consider // explicit conversions, skip it. if (!AllowExplicit && Conv->isExplicit()) continue; - + if (AllowRvalues) { bool DerivedToBase = false; bool ObjCConversion = false; if (!ConvTemplate && - S.CompareReferenceRelationship(DeclLoc, - Conv->getConversionType().getNonReferenceType().getUnqualifiedType(), - DeclType.getNonReferenceType().getUnqualifiedType(), - DerivedToBase, ObjCConversion) - == Sema::Ref_Incompatible) + S.CompareReferenceRelationship( + DeclLoc, + Conv->getConversionType().getNonReferenceType() + .getUnqualifiedType(), + DeclType.getNonReferenceType().getUnqualifiedType(), + DerivedToBase, ObjCConversion) == + Sema::Ref_Incompatible) continue; } else { // If the conversion function doesn't return a reference type, @@ -2757,17 +3043,17 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, !RefType->getPointeeType()->isFunctionType())) continue; } - + if (ConvTemplate) S.AddTemplateConversionCandidate(ConvTemplate, I.getPair(), ActingDC, - Init, ToType, CandidateSet); + Init, DeclType, CandidateSet); else S.AddConversionCandidate(Conv, I.getPair(), ActingDC, Init, - ToType, CandidateSet); + DeclType, CandidateSet); } OverloadCandidateSet::iterator Best; - switch (CandidateSet.BestViableFunction(S, DeclLoc, Best)) { + switch (CandidateSet.BestViableFunction(S, DeclLoc, Best, true)) { case OR_Success: // C++ [over.ics.ref]p1: // @@ -2786,6 +3072,7 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, ICS.UserDefined.Before = Best->Conversions[0].Standard; ICS.UserDefined.After = Best->FinalConversion; ICS.UserDefined.ConversionFunction = Best->Function; + ICS.UserDefined.FoundConversionFunction = Best->FoundDecl.getDecl(); ICS.UserDefined.EllipsisConversion = false; assert(ICS.UserDefined.After.ReferenceBinding && ICS.UserDefined.After.DirectBinding && @@ -2806,7 +3093,7 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, // conversion; continue with other checks. return false; } - + return false; } @@ -2851,9 +3138,7 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, // of type "cv2 T2" as follows: // -- If reference is an lvalue reference and the initializer expression - // The next bullet point (T1 is a function) is pretty much equivalent to this - // one, so it's handled here. - if (!isRValRef || T1->isFunctionType()) { + if (!isRValRef) { // -- is an lvalue (but is not a bit-field), and "cv1 T1" is // reference-compatible with "cv2 T2," or // @@ -2879,7 +3164,10 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, ICS.Standard.setToType(2, T1); ICS.Standard.ReferenceBinding = true; ICS.Standard.DirectBinding = true; - ICS.Standard.RRefBinding = isRValRef; + ICS.Standard.IsLvalueReference = !isRValRef; + ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType(); + ICS.Standard.BindsToRvalue = false; + ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false; ICS.Standard.CopyConstructor = 0; // Nothing more to do: the inaccessibility/ambiguity check for @@ -2897,7 +3185,7 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, // conversion functions (13.3.1.6) and choosing the best // one through overload resolution (13.3)), if (!SuppressUserConversions && T2->isRecordType() && - !S.RequireCompleteType(DeclLoc, T2, 0) && + !S.RequireCompleteType(DeclLoc, T2, 0) && RefRelationship == Sema::Ref_Incompatible) { if (FindConversionForRefInit(S, ICS, DeclType, DeclLoc, Init, T2, /*AllowRvalues=*/false, @@ -2908,9 +3196,8 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, // -- Otherwise, the reference shall be an lvalue reference to a // non-volatile const type (i.e., cv1 shall be const), or the reference - // shall be an rvalue reference and the initializer expression shall be - // an rvalue or have a function type. - // + // shall be an rvalue reference. + // // We actually handle one oddity of C++ [over.ics.ref] at this // point, which is that, due to p2 (which short-circuits reference // binding by only attempting a simple conversion for non-direct @@ -2920,70 +3207,70 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, // qualifier. // This is also the point where rvalue references and lvalue inits no longer // go together. - if ((!isRValRef && !T1.isConstQualified()) || - (isRValRef && InitCategory.isLValue())) + if (!isRValRef && !T1.isConstQualified()) return ICS; - // -- If T1 is a function type, then - // -- if T2 is the same type as T1, the reference is bound to the - // initializer expression lvalue; - // -- if T2 is a class type and the initializer expression can be - // implicitly converted to an lvalue of type T1 [...], the - // reference is bound to the function lvalue that is the result - // of the conversion; - // This is the same as for the lvalue case above, so it was handled there. - // -- otherwise, the program is ill-formed. - // This is the one difference to the lvalue case. - if (T1->isFunctionType()) + // -- If the initializer expression + // + // -- is an xvalue, class prvalue, array prvalue or function + // lvalue and "cv1T1" is reference-compatible with "cv2 T2", or + if (RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification && + (InitCategory.isXValue() || + (InitCategory.isPRValue() && (T2->isRecordType() || T2->isArrayType())) || + (InitCategory.isLValue() && T2->isFunctionType()))) { + ICS.setStandard(); + ICS.Standard.First = ICK_Identity; + ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base + : ObjCConversion? ICK_Compatible_Conversion + : ICK_Identity; + ICS.Standard.Third = ICK_Identity; + ICS.Standard.FromTypePtr = T2.getAsOpaquePtr(); + ICS.Standard.setToType(0, T2); + ICS.Standard.setToType(1, T1); + ICS.Standard.setToType(2, T1); + ICS.Standard.ReferenceBinding = true; + // In C++0x, this is always a direct binding. In C++98/03, it's a direct + // binding unless we're binding to a class prvalue. + // Note: Although xvalues wouldn't normally show up in C++98/03 code, we + // allow the use of rvalue references in C++98/03 for the benefit of + // standard library implementors; therefore, we need the xvalue check here. + ICS.Standard.DirectBinding = + S.getLangOptions().CPlusPlus0x || + (InitCategory.isPRValue() && !T2->isRecordType()); + ICS.Standard.IsLvalueReference = !isRValRef; + ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType(); + ICS.Standard.BindsToRvalue = InitCategory.isRValue(); + ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false; + ICS.Standard.CopyConstructor = 0; return ICS; + } - // -- Otherwise, if T2 is a class type and - // -- the initializer expression is an rvalue and "cv1 T1" - // is reference-compatible with "cv2 T2," or - // - // -- T1 is not reference-related to T2 and the initializer - // expression can be implicitly converted to an rvalue - // of type "cv3 T3" (this conversion is selected by - // enumerating the applicable conversion functions - // (13.3.1.6) and choosing the best one through overload - // resolution (13.3)), + // -- has a class type (i.e., T2 is a class type), where T1 is not + // reference-related to T2, and can be implicitly converted to + // an xvalue, class prvalue, or function lvalue of type + // "cv3 T3", where "cv1 T1" is reference-compatible with + // "cv3 T3", // - // then the reference is bound to the initializer - // expression rvalue in the first case and to the object - // that is the result of the conversion in the second case - // (or, in either case, to the appropriate base class - // subobject of the object). - if (T2->isRecordType()) { - // First case: "cv1 T1" is reference-compatible with "cv2 T2". This is a - // direct binding in C++0x but not in C++03. - if (InitCategory.isRValue() && - RefRelationship >= Sema::Ref_Compatible_With_Added_Qualification) { - ICS.setStandard(); - ICS.Standard.First = ICK_Identity; - ICS.Standard.Second = DerivedToBase? ICK_Derived_To_Base - : ObjCConversion? ICK_Compatible_Conversion - : ICK_Identity; - ICS.Standard.Third = ICK_Identity; - ICS.Standard.FromTypePtr = T2.getAsOpaquePtr(); - ICS.Standard.setToType(0, T2); - ICS.Standard.setToType(1, T1); - ICS.Standard.setToType(2, T1); - ICS.Standard.ReferenceBinding = true; - ICS.Standard.DirectBinding = S.getLangOptions().CPlusPlus0x; - ICS.Standard.RRefBinding = isRValRef; - ICS.Standard.CopyConstructor = 0; - return ICS; - } - - // Second case: not reference-related. - if (RefRelationship == Sema::Ref_Incompatible && - !S.RequireCompleteType(DeclLoc, T2, 0) && - FindConversionForRefInit(S, ICS, DeclType, DeclLoc, - Init, T2, /*AllowRvalues=*/true, - AllowExplicit)) - return ICS; + // then the reference is bound to the value of the initializer + // expression in the first case and to the result of the conversion + // in the second case (or, in either case, to an appropriate base + // class subobject). + if (!SuppressUserConversions && RefRelationship == Sema::Ref_Incompatible && + T2->isRecordType() && !S.RequireCompleteType(DeclLoc, T2, 0) && + FindConversionForRefInit(S, ICS, DeclType, DeclLoc, + Init, T2, /*AllowRvalues=*/true, + AllowExplicit)) { + // In the second case, if the reference is an rvalue reference + // and the second standard conversion sequence of the + // user-defined conversion sequence includes an lvalue-to-rvalue + // conversion, the program is ill-formed. + if (ICS.isUserDefined() && isRValRef && + ICS.UserDefined.After.First == ICK_Lvalue_To_Rvalue) + ICS.setBad(BadConversionSequence::no_conversion, Init, DeclType); + + return ICS; } - + // -- Otherwise, a temporary of type "cv1 T1" is created and // initialized from the initializer expression using the // rules for a non-reference copy initialization (8.5). The @@ -3008,6 +3295,12 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, (T1->isRecordType() || T2->isRecordType())) return ICS; + // If T1 is reference-related to T2 and the reference is an rvalue + // reference, the initializer expression shall not be an lvalue. + if (RefRelationship >= Sema::Ref_Related && + isRValRef && Init->Classify(S.Context).isLValue()) + return ICS; + // C++ [over.ics.ref]p2: // When a parameter of reference type is not bound directly to // an argument expression, the conversion sequence is the one @@ -3020,16 +3313,24 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, // and does not constitute a conversion. ICS = TryImplicitConversion(S, Init, T1, SuppressUserConversions, /*AllowExplicit=*/false, - /*InOverloadResolution=*/false); + /*InOverloadResolution=*/false, + /*CStyle=*/false); // Of course, that's still a reference binding. if (ICS.isStandard()) { ICS.Standard.ReferenceBinding = true; - ICS.Standard.RRefBinding = isRValRef; + ICS.Standard.IsLvalueReference = !isRValRef; + ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType(); + ICS.Standard.BindsToRvalue = true; + ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false; } else if (ICS.isUserDefined()) { ICS.UserDefined.After.ReferenceBinding = true; - ICS.UserDefined.After.RRefBinding = isRValRef; + ICS.Standard.IsLvalueReference = !isRValRef; + ICS.Standard.BindsToFunctionLvalue = T2->isFunctionType(); + ICS.Standard.BindsToRvalue = true; + ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier = false; } + return ICS; } @@ -3041,7 +3342,7 @@ TryReferenceInit(Sema &S, Expr *&Init, QualType DeclType, /// do not permit any user-defined conversion sequences. static ImplicitConversionSequence TryCopyInitialization(Sema &S, Expr *From, QualType ToType, - bool SuppressUserConversions, + bool SuppressUserConversions, bool InOverloadResolution) { if (ToType->isReferenceType()) return TryReferenceInit(S, From, ToType, @@ -3052,7 +3353,8 @@ TryCopyInitialization(Sema &S, Expr *From, QualType ToType, return TryImplicitConversion(S, From, ToType, SuppressUserConversions, /*AllowExplicit=*/false, - InOverloadResolution); + InOverloadResolution, + /*CStyle=*/false); } /// TryObjectArgumentInitialization - Try to initialize the object @@ -3060,6 +3362,7 @@ TryCopyInitialization(Sema &S, Expr *From, QualType ToType, /// expression @p From. static ImplicitConversionSequence TryObjectArgumentInitialization(Sema &S, QualType OrigFromType, + Expr::Classification FromClassification, CXXMethodDecl *Method, CXXRecordDecl *ActingContext) { QualType ClassType = S.Context.getTypeDeclType(ActingContext); @@ -3075,24 +3378,37 @@ TryObjectArgumentInitialization(Sema &S, QualType OrigFromType, // We need to have an object of class type. QualType FromType = OrigFromType; - if (const PointerType *PT = FromType->getAs<PointerType>()) + if (const PointerType *PT = FromType->getAs<PointerType>()) { FromType = PT->getPointeeType(); + // When we had a pointer, it's implicitly dereferenced, so we + // better have an lvalue. + assert(FromClassification.isLValue()); + } + assert(FromType->isRecordType()); - // The implicit object parameter is has the type "reference to cv X", - // where X is the class of which the function is a member - // (C++ [over.match.funcs]p4). However, when finding an implicit - // conversion sequence for the argument, we are not allowed to - // create temporaries or perform user-defined conversions + // C++0x [over.match.funcs]p4: + // For non-static member functions, the type of the implicit object + // parameter is + // + // - "lvalue reference to cv X" for functions declared without a + // ref-qualifier or with the & ref-qualifier + // - "rvalue reference to cv X" for functions declared with the && + // ref-qualifier + // + // where X is the class of which the function is a member and cv is the + // cv-qualification on the member function declaration. + // + // However, when finding an implicit conversion sequence for the argument, we + // are not allowed to create temporaries or perform user-defined conversions // (C++ [over.match.funcs]p5). We perform a simplified version of // reference binding here, that allows class rvalues to bind to // non-constant references. - // First check the qualifiers. We don't care about lvalue-vs-rvalue - // with the implicit object parameter (C++ [over.match.funcs]p5). + // First check the qualifiers. QualType FromTypeCanon = S.Context.getCanonicalType(FromType); - if (ImplicitParamType.getCVRQualifiers() + if (ImplicitParamType.getCVRQualifiers() != FromTypeCanon.getLocalCVRQualifiers() && !ImplicitParamType.isAtLeastAsQualifiedAs(FromTypeCanon)) { ICS.setBad(BadConversionSequence::bad_qualifiers, @@ -3114,6 +3430,31 @@ TryObjectArgumentInitialization(Sema &S, QualType OrigFromType, return ICS; } + // Check the ref-qualifier. + switch (Method->getRefQualifier()) { + case RQ_None: + // Do nothing; we don't care about lvalueness or rvalueness. + break; + + case RQ_LValue: + if (!FromClassification.isLValue() && Quals != Qualifiers::Const) { + // non-const lvalue reference cannot bind to an rvalue + ICS.setBad(BadConversionSequence::lvalue_ref_to_rvalue, FromType, + ImplicitParamType); + return ICS; + } + break; + + case RQ_RValue: + if (!FromClassification.isRValue()) { + // rvalue reference cannot bind to an lvalue + ICS.setBad(BadConversionSequence::rvalue_ref_to_lvalue, FromType, + ImplicitParamType); + return ICS; + } + break; + } + // Success. Mark this as a reference binding. ICS.setStandard(); ICS.Standard.setAsIdentityConversion(); @@ -3122,7 +3463,11 @@ TryObjectArgumentInitialization(Sema &S, QualType OrigFromType, ICS.Standard.setAllToTypes(ImplicitParamType); ICS.Standard.ReferenceBinding = true; ICS.Standard.DirectBinding = true; - ICS.Standard.RRefBinding = false; + ICS.Standard.IsLvalueReference = Method->getRefQualifier() != RQ_RValue; + ICS.Standard.BindsToFunctionLvalue = false; + ICS.Standard.BindsToRvalue = FromClassification.isRValue(); + ICS.Standard.BindsImplicitObjectArgumentWithoutRefQualifier + = (Method->getRefQualifier() == RQ_None); return ICS; } @@ -3130,31 +3475,50 @@ TryObjectArgumentInitialization(Sema &S, QualType OrigFromType, /// the implicit object parameter for the given Method with the given /// expression. bool -Sema::PerformObjectArgumentInitialization(Expr *&From, - NestedNameSpecifier *Qualifier, +Sema::PerformObjectArgumentInitialization(Expr *&From, + NestedNameSpecifier *Qualifier, NamedDecl *FoundDecl, CXXMethodDecl *Method) { QualType FromRecordType, DestType; QualType ImplicitParamRecordType = Method->getThisType(Context)->getAs<PointerType>()->getPointeeType(); + Expr::Classification FromClassification; if (const PointerType *PT = From->getType()->getAs<PointerType>()) { FromRecordType = PT->getPointeeType(); DestType = Method->getThisType(Context); + FromClassification = Expr::Classification::makeSimpleLValue(); } else { FromRecordType = From->getType(); DestType = ImplicitParamRecordType; + FromClassification = From->Classify(Context); } // Note that we always use the true parent context when performing // the actual argument initialization. ImplicitConversionSequence ICS - = TryObjectArgumentInitialization(*this, From->getType(), Method, - Method->getParent()); - if (ICS.isBad()) + = TryObjectArgumentInitialization(*this, From->getType(), FromClassification, + Method, Method->getParent()); + if (ICS.isBad()) { + if (ICS.Bad.Kind == BadConversionSequence::bad_qualifiers) { + Qualifiers FromQs = FromRecordType.getQualifiers(); + Qualifiers ToQs = DestType.getQualifiers(); + unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers(); + if (CVR) { + Diag(From->getSourceRange().getBegin(), + diag::err_member_function_call_bad_cvr) + << Method->getDeclName() << FromRecordType << (CVR - 1) + << From->getSourceRange(); + Diag(Method->getLocation(), diag::note_previous_decl) + << Method->getDeclName(); + return true; + } + } + return Diag(From->getSourceRange().getBegin(), diag::err_implicit_object_parameter_init) << ImplicitParamRecordType << FromRecordType << From->getSourceRange(); + } if (ICS.Standard.Second == ICK_Derived_To_Base) return PerformObjectMemberConversion(From, Qualifier, FoundDecl, Method); @@ -3174,7 +3538,8 @@ TryContextuallyConvertToBool(Sema &S, Expr *From) { // FIXME: Are these flags correct? /*SuppressUserConversions=*/false, /*AllowExplicit=*/true, - /*InOverloadResolution=*/false); + /*InOverloadResolution=*/false, + /*CStyle=*/false); } /// PerformContextuallyConvertToBool - Perform a contextual conversion @@ -3183,14 +3548,14 @@ bool Sema::PerformContextuallyConvertToBool(Expr *&From) { ImplicitConversionSequence ICS = TryContextuallyConvertToBool(*this, From); if (!ICS.isBad()) return PerformImplicitConversion(From, Context.BoolTy, ICS, AA_Converting); - + if (!DiagnoseMultipleUserDefinedConversion(From, Context.BoolTy)) return Diag(From->getSourceRange().getBegin(), diag::err_typecheck_bool_condition) << From->getType() << From->getSourceRange(); return true; } - + /// TryContextuallyConvertToObjCId - Attempt to contextually convert the /// expression From to 'id'. static ImplicitConversionSequence @@ -3200,7 +3565,8 @@ TryContextuallyConvertToObjCId(Sema &S, Expr *From) { // FIXME: Are these flags correct? /*SuppressUserConversions=*/false, /*AllowExplicit=*/true, - /*InOverloadResolution=*/false); + /*InOverloadResolution=*/false, + /*CStyle=*/false); } /// PerformContextuallyConvertToObjCId - Perform a contextual conversion @@ -3213,7 +3579,7 @@ bool Sema::PerformContextuallyConvertToObjCId(Expr *&From) { return true; } -/// \brief Attempt to convert the given expression to an integral or +/// \brief Attempt to convert the given expression to an integral or /// enumeration type. /// /// This routine will attempt to convert an expression of class type to an @@ -3241,7 +3607,7 @@ bool Sema::PerformContextuallyConvertToObjCId(Expr *&From) { /// \param AmbigDiag The diagnostic to be emitted if there is more than one /// conversion function that could convert to integral or enumeration type. /// -/// \param AmbigNote The note to be emitted with \p AmbigDiag for each +/// \param AmbigNote The note to be emitted with \p AmbigDiag for each /// usable conversion function. /// /// \param ConvDiag The diagnostic to be emitted if we are calling a conversion @@ -3249,7 +3615,7 @@ bool Sema::PerformContextuallyConvertToObjCId(Expr *&From) { /// /// \returns The expression, converted to an integral or enumeration type if /// successful. -ExprResult +ExprResult Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, const PartialDiagnostic &NotIntDiag, const PartialDiagnostic &IncompleteDiag, @@ -3261,7 +3627,7 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, // We can't perform any more checking for type-dependent expressions. if (From->isTypeDependent()) return Owned(From); - + // If the expression already has integral or enumeration type, we're golden. QualType T = From->getType(); if (T->isIntegralOrEnumerationType()) @@ -3269,7 +3635,7 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, // FIXME: Check for missing '()' if T is a function type? - // If we don't have a class type in C++, there's no way we can get an + // If we don't have a class type in C++, there's no way we can get an // expression of integral or enumeration type. const RecordType *RecordTy = T->getAs<RecordType>(); if (!RecordTy || !getLangOptions().CPlusPlus) { @@ -3277,20 +3643,20 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, << T << From->getSourceRange(); return Owned(From); } - + // We must have a complete class type. if (RequireCompleteType(Loc, T, IncompleteDiag)) return Owned(From); - + // Look for a conversion to an integral or enumeration type. UnresolvedSet<4> ViableConversions; UnresolvedSet<4> ExplicitConversions; const UnresolvedSetImpl *Conversions = cast<CXXRecordDecl>(RecordTy->getDecl())->getVisibleConversionFunctions(); - + for (UnresolvedSetImpl::iterator I = Conversions->begin(), - E = Conversions->end(); - I != E; + E = Conversions->end(); + I != E; ++I) { if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>((*I)->getUnderlyingDecl())) @@ -3302,21 +3668,21 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, ViableConversions.addDecl(I.getDecl(), I.getAccess()); } } - + switch (ViableConversions.size()) { case 0: if (ExplicitConversions.size() == 1) { DeclAccessPair Found = ExplicitConversions[0]; CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Found->getUnderlyingDecl()); - + // The user probably meant to invoke the given explicit // conversion; use it. QualType ConvTy = Conversion->getConversionType().getNonReferenceType(); std::string TypeStr; ConvTy.getAsStringInternal(TypeStr, Context.PrintingPolicy); - + Diag(Loc, ExplicitConvDiag) << T << ConvTy << FixItHint::CreateInsertion(From->getLocStart(), @@ -3325,41 +3691,49 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, ")"); Diag(Conversion->getLocation(), ExplicitConvNote) << ConvTy->isEnumeralType() << ConvTy; - - // If we aren't in a SFINAE context, build a call to the + + // If we aren't in a SFINAE context, build a call to the // explicit conversion function. if (isSFINAEContext()) return ExprError(); - + CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found); - From = BuildCXXMemberCallExpr(From, Found, Conversion); + ExprResult Result = BuildCXXMemberCallExpr(From, Found, Conversion); + if (Result.isInvalid()) + return ExprError(); + + From = Result.get(); } - + // We'll complain below about a non-integral condition type. break; - + case 1: { // Apply this conversion. DeclAccessPair Found = ViableConversions[0]; CheckMemberOperatorAccess(From->getExprLoc(), From, 0, Found); - + CXXConversionDecl *Conversion = cast<CXXConversionDecl>(Found->getUnderlyingDecl()); QualType ConvTy - = Conversion->getConversionType().getNonReferenceType(); + = Conversion->getConversionType().getNonReferenceType(); if (ConvDiag.getDiagID()) { if (isSFINAEContext()) return ExprError(); - + Diag(Loc, ConvDiag) << T << ConvTy->isEnumeralType() << ConvTy << From->getSourceRange(); } - - From = BuildCXXMemberCallExpr(From, Found, + + ExprResult Result = BuildCXXMemberCallExpr(From, Found, cast<CXXConversionDecl>(Found->getUnderlyingDecl())); + if (Result.isInvalid()) + return ExprError(); + + From = Result.get(); break; } - + default: Diag(Loc, AmbigDiag) << T << From->getSourceRange(); @@ -3372,7 +3746,7 @@ Sema::ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *From, } return Owned(From); } - + if (!From->getType()->isIntegralOrEnumerationType()) Diag(Loc, NotIntDiag) << From->getType() << From->getSourceRange(); @@ -3411,7 +3785,8 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, // object argument (C++ [over.call.func]p3), and the acting context // is irrelevant. AddMethodCandidate(Method, FoundDecl, Method->getParent(), - QualType(), Args, NumArgs, CandidateSet, + QualType(), Expr::Classification::makeSimpleLValue(), + Args, NumArgs, CandidateSet, SuppressUserConversions); return; } @@ -3430,13 +3805,13 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, // A member function template is never instantiated to perform the copy // of a class object to an object of its class type. QualType ClassType = Context.getTypeDeclType(Constructor->getParent()); - if (NumArgs == 1 && - Constructor->isCopyConstructorLikeSpecialization() && + if (NumArgs == 1 && + Constructor->isSpecializationCopyingObject() && (Context.hasSameUnqualifiedType(ClassType, Args[0]->getType()) || IsDerivedFrom(Args[0]->getType(), ClassType))) return; } - + // Add this candidate CandidateSet.push_back(OverloadCandidate()); OverloadCandidate& Candidate = CandidateSet.back(); @@ -3445,13 +3820,14 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, Candidate.Viable = true; Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = false; + Candidate.ExplicitCallArguments = NumArgs; unsigned NumArgsInProto = Proto->getNumArgs(); // (C++ 13.3.2p2): A candidate function having fewer than m // parameters is viable only if it has an ellipsis in its parameter // list (8.3.5). - if ((NumArgs + (PartialOverloading && NumArgs)) > NumArgsInProto && + if ((NumArgs + (PartialOverloading && NumArgs)) > NumArgsInProto && !Proto->isVariadic()) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_too_many_arguments; @@ -3483,7 +3859,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, QualType ParamType = Proto->getArgType(ArgIdx); Candidate.Conversions[ArgIdx] = TryCopyInitialization(*this, Args[ArgIdx], ParamType, - SuppressUserConversions, + SuppressUserConversions, /*InOverloadResolution=*/true); if (Candidate.Conversions[ArgIdx].isBad()) { Candidate.Viable = false; @@ -3511,7 +3887,8 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic()) AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(), cast<CXXMethodDecl>(FD)->getParent(), - Args[0]->getType(), Args + 1, NumArgs - 1, + Args[0]->getType(), Args[0]->Classify(Context), + Args + 1, NumArgs - 1, CandidateSet, SuppressUserConversions); else AddOverloadCandidate(FD, F.getPair(), Args, NumArgs, CandidateSet, @@ -3523,7 +3900,9 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, AddMethodTemplateCandidate(FunTmpl, F.getPair(), cast<CXXRecordDecl>(FunTmpl->getDeclContext()), /*FIXME: explicit args */ 0, - Args[0]->getType(), Args + 1, NumArgs - 1, + Args[0]->getType(), + Args[0]->Classify(Context), + Args + 1, NumArgs - 1, CandidateSet, SuppressUserConversions); else @@ -3539,6 +3918,7 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, /// method) as a method candidate to the given overload set. void Sema::AddMethodCandidate(DeclAccessPair FoundDecl, QualType ObjectType, + Expr::Classification ObjectClassification, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions) { @@ -3547,18 +3927,18 @@ void Sema::AddMethodCandidate(DeclAccessPair FoundDecl, if (isa<UsingShadowDecl>(Decl)) Decl = cast<UsingShadowDecl>(Decl)->getTargetDecl(); - + if (FunctionTemplateDecl *TD = dyn_cast<FunctionTemplateDecl>(Decl)) { assert(isa<CXXMethodDecl>(TD->getTemplatedDecl()) && "Expected a member function template"); AddMethodTemplateCandidate(TD, FoundDecl, ActingContext, /*ExplicitArgs*/ 0, - ObjectType, Args, NumArgs, + ObjectType, ObjectClassification, Args, NumArgs, CandidateSet, SuppressUserConversions); } else { AddMethodCandidate(cast<CXXMethodDecl>(Decl), FoundDecl, ActingContext, - ObjectType, Args, NumArgs, + ObjectType, ObjectClassification, Args, NumArgs, CandidateSet, SuppressUserConversions); } } @@ -3573,6 +3953,7 @@ void Sema::AddMethodCandidate(DeclAccessPair FoundDecl, void Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, QualType ObjectType, + Expr::Classification ObjectClassification, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions) { @@ -3595,6 +3976,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, Candidate.Function = Method; Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = false; + Candidate.ExplicitCallArguments = NumArgs; unsigned NumArgsInProto = Proto->getNumArgs(); @@ -3630,8 +4012,8 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, // Determine the implicit conversion sequence for the object // parameter. Candidate.Conversions[0] - = TryObjectArgumentInitialization(*this, ObjectType, Method, - ActingContext); + = TryObjectArgumentInitialization(*this, ObjectType, ObjectClassification, + Method, ActingContext); if (Candidate.Conversions[0].isBad()) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_conversion; @@ -3650,7 +4032,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, QualType ParamType = Proto->getArgType(ArgIdx); Candidate.Conversions[ArgIdx + 1] = TryCopyInitialization(*this, Args[ArgIdx], ParamType, - SuppressUserConversions, + SuppressUserConversions, /*InOverloadResolution=*/true); if (Candidate.Conversions[ArgIdx + 1].isBad()) { Candidate.Viable = false; @@ -3665,7 +4047,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, } } } - + /// \brief Add a C++ member function template as a candidate to the candidate /// set, using template argument deduction to produce an appropriate member /// function template specialization. @@ -3675,6 +4057,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, CXXRecordDecl *ActingContext, const TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ObjectType, + Expr::Classification ObjectClassification, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions) { @@ -3703,7 +4086,8 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, Candidate.FailureKind = ovl_fail_bad_deduction; Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = false; - Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, + Candidate.ExplicitCallArguments = NumArgs; + Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, Info); return; } @@ -3714,8 +4098,8 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, assert(isa<CXXMethodDecl>(Specialization) && "Specialization is not a member function?"); AddMethodCandidate(cast<CXXMethodDecl>(Specialization), FoundDecl, - ActingContext, ObjectType, Args, NumArgs, - CandidateSet, SuppressUserConversions); + ActingContext, ObjectType, ObjectClassification, + Args, NumArgs, CandidateSet, SuppressUserConversions); } /// \brief Add a C++ function template specialization as a candidate @@ -3753,7 +4137,8 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, Candidate.FailureKind = ovl_fail_bad_deduction; Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = false; - Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, + Candidate.ExplicitCallArguments = NumArgs; + Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, Info); return; } @@ -3798,10 +4183,11 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, Candidate.FinalConversion.setAllToTypes(ToType); Candidate.Viable = true; Candidate.Conversions.resize(1); + Candidate.ExplicitCallArguments = 1; // 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 + // 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. // // Determine the implicit conversion sequence for the implicit @@ -3811,18 +4197,19 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, ImplicitParamType = FromPtrType->getPointeeType(); CXXRecordDecl *ConversionContext = cast<CXXRecordDecl>(ImplicitParamType->getAs<RecordType>()->getDecl()); - + Candidate.Conversions[0] - = TryObjectArgumentInitialization(*this, From->getType(), Conversion, - ConversionContext); - + = TryObjectArgumentInitialization(*this, From->getType(), + From->Classify(Context), + Conversion, ConversionContext); + if (Candidate.Conversions[0].isBad()) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_conversion; return; } - // We won't go through a user-define type conversion function to convert a + // 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 // go through a copy constructor. 13.3.3.1.2-p4 [over.ics.user] QualType FromCanon @@ -3833,7 +4220,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, Candidate.FailureKind = ovl_fail_trivial_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 @@ -3843,17 +4230,26 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, // call on the stack and we don't need its arguments to be // well-formed. DeclRefExpr ConversionRef(Conversion, Conversion->getType(), - From->getLocStart()); + VK_LValue, From->getLocStart()); ImplicitCastExpr ConversionFn(ImplicitCastExpr::OnStack, Context.getPointerType(Conversion->getType()), CK_FunctionToPointerDecay, &ConversionRef, VK_RValue); + QualType CallResultType + = Conversion->getConversionType().getNonLValueExprType(Context); + if (RequireCompleteType(From->getLocStart(), CallResultType, 0)) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_final_conversion; + return; + } + + ExprValueKind VK = Expr::getValueKindForType(Conversion->getConversionType()); + // Note that it is safe to allocate CallExpr on the stack here because // there are 0 arguments (i.e., nothing is allocated using ASTContext's // allocator). - CallExpr Call(Context, &ConversionFn, 0, 0, - Conversion->getConversionType().getNonLValueExprType(Context), + CallExpr Call(Context, &ConversionFn, 0, 0, CallResultType, VK, From->getLocStart()); ImplicitConversionSequence ICS = TryCopyInitialization(*this, &Call, ToType, @@ -3863,17 +4259,27 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, switch (ICS.getKind()) { case ImplicitConversionSequence::StandardConversion: Candidate.FinalConversion = ICS.Standard; - + // C++ [over.ics.user]p3: // If the user-defined conversion is specified by a specialization of a - // conversion function template, the second standard conversion sequence + // conversion function template, the second standard conversion sequence // shall have exact match rank. if (Conversion->getPrimaryTemplate() && GetConversionRank(ICS.Standard.Second) != ICR_Exact_Match) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_final_conversion_not_exact; } - + + // C++0x [dcl.init.ref]p5: + // In the second case, if the reference is an rvalue reference and + // the second standard conversion sequence of the user-defined + // conversion sequence includes an lvalue-to-rvalue conversion, the + // program is ill-formed. + if (ToType->isRValueReferenceType() && + ICS.Standard.First == ICK_Lvalue_To_Rvalue) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_bad_final_conversion; + } break; case ImplicitConversionSequence::BadConversion: @@ -3917,7 +4323,8 @@ Sema::AddTemplateConversionCandidate(FunctionTemplateDecl *FunctionTemplate, Candidate.FailureKind = ovl_fail_bad_deduction; Candidate.IsSurrogate = false; Candidate.IgnoreObjectArgument = false; - Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, + Candidate.ExplicitCallArguments = 1; + Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result, Info); return; } @@ -3938,7 +4345,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, const FunctionProtoType *Proto, - QualType ObjectType, + Expr *Object, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet) { if (!CandidateSet.isNewCandidate(Conversion)) @@ -3956,12 +4363,14 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, Candidate.IsSurrogate = true; Candidate.IgnoreObjectArgument = false; Candidate.Conversions.resize(NumArgs + 1); + Candidate.ExplicitCallArguments = NumArgs; // Determine the implicit conversion sequence for the implicit // object parameter. ImplicitConversionSequence ObjectInit - = TryObjectArgumentInitialization(*this, ObjectType, Conversion, - ActingContext); + = TryObjectArgumentInitialization(*this, Object->getType(), + Object->Classify(Context), + Conversion, ActingContext); if (ObjectInit.isBad()) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_bad_conversion; @@ -3976,6 +4385,8 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, Candidate.Conversions[0].UserDefined.Before = ObjectInit.Standard; Candidate.Conversions[0].UserDefined.EllipsisConversion = false; Candidate.Conversions[0].UserDefined.ConversionFunction = Conversion; + Candidate.Conversions[0].UserDefined.FoundConversionFunction + = FoundDecl.getDecl(); Candidate.Conversions[0].UserDefined.After = Candidate.Conversions[0].UserDefined.Before; Candidate.Conversions[0].UserDefined.After.setAsIdentityConversion(); @@ -4071,7 +4482,8 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op, Oper != OperEnd; ++Oper) AddMethodCandidate(Oper.getPair(), Args[0]->getType(), - Args + 1, NumArgs - 1, CandidateSet, + Args[0]->Classify(Context), Args + 1, NumArgs - 1, + CandidateSet, /* SuppressUserConversions = */ false); } } @@ -4107,6 +4519,7 @@ void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys, // arguments. Candidate.Viable = true; Candidate.Conversions.resize(NumArgs); + Candidate.ExplicitCallArguments = NumArgs; for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) { // C++ [over.match.oper]p4: // For the built-in assignment operators, conversions of the @@ -4159,10 +4572,17 @@ class BuiltinCandidateTypeSet { /// used in the built-in candidates. TypeSet EnumerationTypes; - /// \brief The set of vector types that will be used in the built-in + /// \brief The set of vector types that will be used in the built-in /// candidates. TypeSet VectorTypes; - + + /// \brief A flag indicating non-record types are viable candidates + bool HasNonRecordTypes; + + /// \brief A flag indicating whether either arithmetic or enumeration types + /// were present in the candidate set. + bool HasArithmeticOrEnumeralTypes; + /// Sema - The semantic analysis instance where we are building the /// candidate type set. Sema &SemaRef; @@ -4179,9 +4599,12 @@ public: typedef TypeSet::iterator iterator; BuiltinCandidateTypeSet(Sema &SemaRef) - : SemaRef(SemaRef), Context(SemaRef.Context) { } + : HasNonRecordTypes(false), + HasArithmeticOrEnumeralTypes(false), + SemaRef(SemaRef), + Context(SemaRef.Context) { } - void AddTypesConvertedFrom(QualType Ty, + void AddTypesConvertedFrom(QualType Ty, SourceLocation Loc, bool AllowUserConversions, bool AllowExplicitConversions, @@ -4204,9 +4627,12 @@ public: /// enumeration_end - Past the last enumeration type found; iterator enumeration_end() { return EnumerationTypes.end(); } - + iterator vector_begin() { return VectorTypes.begin(); } iterator vector_end() { return VectorTypes.end(); } + + bool hasNonRecordTypes() { return HasNonRecordTypes; } + bool hasArithmeticOrEnumeralTypes() { return HasArithmeticOrEnumeralTypes; } }; /// AddPointerWithMoreQualifiedTypeVariants - Add the pointer type @p Ty to @@ -4225,7 +4651,7 @@ BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty, // Insert this type. if (!PointerTypes.insert(Ty)) return false; - + QualType PointeeTy; const PointerType *PointerTy = Ty->getAs<PointerType>(); bool buildObjCPtr = false; @@ -4239,7 +4665,7 @@ BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty, } else PointeeTy = PointerTy->getPointeeType(); - + // Don't add qualified variants of arrays. For one, they're not allowed // (the qualifier would sink to the element type), and for another, the // only overload situation where it matters is subscript or pointer +- int, @@ -4251,7 +4677,7 @@ BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty, BaseCVR = Array->getElementType().getCVRQualifiers(); bool hasVolatile = VisibleQuals.hasVolatile(); bool hasRestrict = VisibleQuals.hasRestrict(); - + // Iterate through all strict supersets of BaseCVR. for (unsigned CVR = BaseCVR+1; CVR <= Qualifiers::CVRMask; ++CVR) { if ((CVR | BaseCVR) != CVR) continue; @@ -4302,9 +4728,10 @@ BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants( unsigned BaseCVR = PointeeTy.getCVRQualifiers(); for (unsigned CVR = BaseCVR+1; CVR <= Qualifiers::CVRMask; ++CVR) { if ((CVR | BaseCVR) != CVR) continue; - + QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR); - MemberPointerTypes.insert(Context.getMemberPointerType(QPointeeTy, ClassTy)); + MemberPointerTypes.insert( + Context.getMemberPointerType(QPointeeTy, ClassTy)); } return true; @@ -4332,12 +4759,21 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty, if (const ReferenceType *RefTy = Ty->getAs<ReferenceType>()) Ty = RefTy->getPointeeType(); - // We don't care about qualifiers on the type. - Ty = Ty.getLocalUnqualifiedType(); - // If we're dealing with an array type, decay to the pointer. if (Ty->isArrayType()) Ty = SemaRef.Context.getArrayDecayedType(Ty); + + // Otherwise, we don't care about qualifiers on the type. + Ty = Ty.getLocalUnqualifiedType(); + + // Flag if we ever add a non-record type. + const RecordType *TyRec = Ty->getAs<RecordType>(); + HasNonRecordTypes = HasNonRecordTypes || !TyRec; + + // Flag if we encounter an arithmetic type. + HasArithmeticOrEnumeralTypes = + HasArithmeticOrEnumeralTypes || Ty->isArithmeticType(); + if (Ty->isObjCIdType() || Ty->isObjCClassType()) PointerTypes.insert(Ty); else if (Ty->getAs<PointerType>() || Ty->getAs<ObjCObjectPointerType>()) { @@ -4350,35 +4786,36 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty, if (!AddMemberPointerWithMoreQualifiedTypeVariants(Ty)) return; } else if (Ty->isEnumeralType()) { + HasArithmeticOrEnumeralTypes = true; EnumerationTypes.insert(Ty); } else if (Ty->isVectorType()) { + // We treat vector types as arithmetic types in many contexts as an + // extension. + HasArithmeticOrEnumeralTypes = true; VectorTypes.insert(Ty); - } else if (AllowUserConversions) { - if (const RecordType *TyRec = Ty->getAs<RecordType>()) { - if (SemaRef.RequireCompleteType(Loc, Ty, 0)) { - // No conversion functions in incomplete types. - return; - } + } else if (AllowUserConversions && TyRec) { + // No conversion functions in incomplete types. + if (SemaRef.RequireCompleteType(Loc, Ty, 0)) + return; - CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl()); - const UnresolvedSetImpl *Conversions - = ClassDecl->getVisibleConversionFunctions(); - for (UnresolvedSetImpl::iterator I = Conversions->begin(), - E = Conversions->end(); I != E; ++I) { - NamedDecl *D = I.getDecl(); - if (isa<UsingShadowDecl>(D)) - D = cast<UsingShadowDecl>(D)->getTargetDecl(); + CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl()); + const UnresolvedSetImpl *Conversions + = ClassDecl->getVisibleConversionFunctions(); + for (UnresolvedSetImpl::iterator I = Conversions->begin(), + E = Conversions->end(); I != E; ++I) { + NamedDecl *D = I.getDecl(); + if (isa<UsingShadowDecl>(D)) + D = cast<UsingShadowDecl>(D)->getTargetDecl(); - // Skip conversion function templates; they don't tell us anything - // about which builtin types we can convert to. - if (isa<FunctionTemplateDecl>(D)) - continue; + // Skip conversion function templates; they don't tell us anything + // about which builtin types we can convert to. + if (isa<FunctionTemplateDecl>(D)) + continue; - CXXConversionDecl *Conv = cast<CXXConversionDecl>(D); - if (AllowExplicitConversions || !Conv->isExplicit()) { - AddTypesConvertedFrom(Conv->getConversionType(), Loc, false, false, - VisibleQuals); - } + CXXConversionDecl *Conv = cast<CXXConversionDecl>(D); + if (AllowExplicitConversions || !Conv->isExplicit()) { + AddTypesConvertedFrom(Conv->getConversionType(), Loc, false, false, + VisibleQuals); } } } @@ -4426,14 +4863,14 @@ static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) { VRQuals.addRestrict(); return VRQuals; } - + CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl()); if (!ClassDecl->hasDefinition()) return VRQuals; const UnresolvedSetImpl *Conversions = ClassDecl->getVisibleConversionFunctions(); - + for (UnresolvedSetImpl::iterator I = Conversions->begin(), E = Conversions->end(); I != E; ++I) { NamedDecl *D = I.getDecl(); @@ -4449,7 +4886,7 @@ static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) { while (!done) { if (const PointerType *ResTypePtr = CanTy->getAs<PointerType>()) CanTy = ResTypePtr->getPointeeType(); - else if (const MemberPointerType *ResTypeMPtr = + else if (const MemberPointerType *ResTypeMPtr = CanTy->getAs<MemberPointerType>()) CanTy = ResTypeMPtr->getPointeeType(); else @@ -4465,765 +4902,1174 @@ static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) { } return VRQuals; } - -/// AddBuiltinOperatorCandidates - Add the appropriate built-in -/// operator overloads to the candidate set (C++ [over.built]), based -/// on the operator @p Op and the arguments given. For example, if the -/// operator is a binary '+', this routine might add "int -/// operator+(int, int)" to cover integer addition. -void -Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, - SourceLocation OpLoc, - Expr **Args, unsigned NumArgs, - OverloadCandidateSet& CandidateSet) { - // The set of "promoted arithmetic types", which are the arithmetic - // types are that preserved by promotion (C++ [over.built]p2). Note - // that the first few of these types are the promoted integral - // types; these types need to be first. - // FIXME: What about complex? - const unsigned FirstIntegralType = 0; - const unsigned LastIntegralType = 13; - const unsigned FirstPromotedIntegralType = 7, - LastPromotedIntegralType = 13; - const unsigned FirstPromotedArithmeticType = 7, - LastPromotedArithmeticType = 16; - const unsigned NumArithmeticTypes = 16; - QualType ArithmeticTypes[NumArithmeticTypes] = { - Context.BoolTy, Context.CharTy, Context.WCharTy, -// FIXME: Context.Char16Ty, Context.Char32Ty, - Context.SignedCharTy, Context.ShortTy, - Context.UnsignedCharTy, Context.UnsignedShortTy, - Context.IntTy, Context.LongTy, Context.LongLongTy, - Context.UnsignedIntTy, Context.UnsignedLongTy, Context.UnsignedLongLongTy, - Context.FloatTy, Context.DoubleTy, Context.LongDoubleTy - }; - assert(ArithmeticTypes[FirstPromotedIntegralType] == Context.IntTy && - "Invalid first promoted integral type"); - assert(ArithmeticTypes[LastPromotedIntegralType - 1] - == Context.UnsignedLongLongTy && - "Invalid last promoted integral type"); - assert(ArithmeticTypes[FirstPromotedArithmeticType] == Context.IntTy && - "Invalid first promoted arithmetic type"); - assert(ArithmeticTypes[LastPromotedArithmeticType - 1] - == Context.LongDoubleTy && - "Invalid last promoted arithmetic type"); - - // Find all of the types that the arguments can convert to, but only - // if the operator we're looking at has built-in operator candidates - // that make use of these types. - Qualifiers VisibleTypeConversionsQuals; - VisibleTypeConversionsQuals.addConst(); - for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) - VisibleTypeConversionsQuals += CollectVRQualifiers(Context, Args[ArgIdx]); - - BuiltinCandidateTypeSet CandidateTypes(*this); - for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) - CandidateTypes.AddTypesConvertedFrom(Args[ArgIdx]->getType(), - OpLoc, - true, - (Op == OO_Exclaim || - Op == OO_AmpAmp || - Op == OO_PipePipe), - VisibleTypeConversionsQuals); - - bool isComparison = false; - switch (Op) { - case OO_None: - case NUM_OVERLOADED_OPERATORS: - assert(false && "Expected an overloaded operator"); - break; - case OO_Star: // '*' is either unary or binary - if (NumArgs == 1) - goto UnaryStar; - else - goto BinaryStar; - break; +namespace { - case OO_Plus: // '+' is either unary or binary - if (NumArgs == 1) - goto UnaryPlus; - else - goto BinaryPlus; - break; +/// \brief Helper class to manage the addition of builtin operator overload +/// candidates. It provides shared state and utility methods used throughout +/// the process, as well as a helper method to add each group of builtin +/// operator overloads from the standard to a candidate set. +class BuiltinOperatorOverloadBuilder { + // Common instance state available to all overload candidate addition methods. + Sema &S; + Expr **Args; + unsigned NumArgs; + Qualifiers VisibleTypeConversionsQuals; + bool HasArithmeticOrEnumeralCandidateType; + llvm::SmallVectorImpl<BuiltinCandidateTypeSet> &CandidateTypes; + OverloadCandidateSet &CandidateSet; + + // Define some constants used to index and iterate over the arithemetic types + // provided via the getArithmeticType() method below. + // The "promoted arithmetic types" are the arithmetic + // types are that preserved by promotion (C++ [over.built]p2). + static const unsigned FirstIntegralType = 3; + static const unsigned LastIntegralType = 18; + static const unsigned FirstPromotedIntegralType = 3, + LastPromotedIntegralType = 9; + static const unsigned FirstPromotedArithmeticType = 0, + LastPromotedArithmeticType = 9; + static const unsigned NumArithmeticTypes = 18; + + /// \brief Get the canonical type for a given arithmetic type index. + CanQualType getArithmeticType(unsigned index) { + assert(index < NumArithmeticTypes); + static CanQualType ASTContext::* const + ArithmeticTypes[NumArithmeticTypes] = { + // Start of promoted types. + &ASTContext::FloatTy, + &ASTContext::DoubleTy, + &ASTContext::LongDoubleTy, + + // Start of integral types. + &ASTContext::IntTy, + &ASTContext::LongTy, + &ASTContext::LongLongTy, + &ASTContext::UnsignedIntTy, + &ASTContext::UnsignedLongTy, + &ASTContext::UnsignedLongLongTy, + // End of promoted types. + + &ASTContext::BoolTy, + &ASTContext::CharTy, + &ASTContext::WCharTy, + &ASTContext::Char16Ty, + &ASTContext::Char32Ty, + &ASTContext::SignedCharTy, + &ASTContext::ShortTy, + &ASTContext::UnsignedCharTy, + &ASTContext::UnsignedShortTy, + // End of integral types. + // FIXME: What about complex? + }; + return S.Context.*ArithmeticTypes[index]; + } + + /// \brief Gets the canonical type resulting from the usual arithemetic + /// converions for the given arithmetic types. + CanQualType getUsualArithmeticConversions(unsigned L, unsigned R) { + // Accelerator table for performing the usual arithmetic conversions. + // The rules are basically: + // - if either is floating-point, use the wider floating-point + // - if same signedness, use the higher rank + // - if same size, use unsigned of the higher rank + // - use the larger type + // These rules, together with the axiom that higher ranks are + // never smaller, are sufficient to precompute all of these results + // *except* when dealing with signed types of higher rank. + // (we could precompute SLL x UI for all known platforms, but it's + // better not to make any assumptions). + enum PromotedType { + Flt, Dbl, LDbl, SI, SL, SLL, UI, UL, ULL, Dep=-1 + }; + static PromotedType ConversionsTable[LastPromotedArithmeticType] + [LastPromotedArithmeticType] = { + /* Flt*/ { Flt, Dbl, LDbl, Flt, Flt, Flt, Flt, Flt, Flt }, + /* Dbl*/ { Dbl, Dbl, LDbl, Dbl, Dbl, Dbl, Dbl, Dbl, Dbl }, + /*LDbl*/ { LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl, LDbl }, + /* SI*/ { Flt, Dbl, LDbl, SI, SL, SLL, UI, UL, ULL }, + /* SL*/ { Flt, Dbl, LDbl, SL, SL, SLL, Dep, UL, ULL }, + /* SLL*/ { Flt, Dbl, LDbl, SLL, SLL, SLL, Dep, Dep, ULL }, + /* UI*/ { Flt, Dbl, LDbl, UI, Dep, Dep, UI, UL, ULL }, + /* UL*/ { Flt, Dbl, LDbl, UL, UL, Dep, UL, UL, ULL }, + /* ULL*/ { Flt, Dbl, LDbl, ULL, ULL, ULL, ULL, ULL, ULL }, + }; - case OO_Minus: // '-' is either unary or binary - if (NumArgs == 1) - goto UnaryMinus; - else - goto BinaryMinus; - break; + assert(L < LastPromotedArithmeticType); + assert(R < LastPromotedArithmeticType); + int Idx = ConversionsTable[L][R]; + + // Fast path: the table gives us a concrete answer. + if (Idx != Dep) return getArithmeticType(Idx); + + // Slow path: we need to compare widths. + // An invariant is that the signed type has higher rank. + CanQualType LT = getArithmeticType(L), + RT = getArithmeticType(R); + unsigned LW = S.Context.getIntWidth(LT), + RW = S.Context.getIntWidth(RT); + + // If they're different widths, use the signed type. + if (LW > RW) return LT; + else if (LW < RW) return RT; + + // Otherwise, use the unsigned type of the signed type's rank. + if (L == SL || R == SL) return S.Context.UnsignedLongTy; + assert(L == SLL || R == SLL); + return S.Context.UnsignedLongLongTy; + } + + /// \brief Helper method to factor out the common pattern of adding overloads + /// for '++' and '--' builtin operators. + void addPlusPlusMinusMinusStyleOverloads(QualType CandidateTy, + bool HasVolatile) { + QualType ParamTypes[2] = { + S.Context.getLValueReferenceType(CandidateTy), + S.Context.IntTy + }; - case OO_Amp: // '&' is either unary or binary + // Non-volatile version. if (NumArgs == 1) - goto UnaryAmp; + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet); else - goto BinaryAmp; + S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, 2, CandidateSet); + + // Use a heuristic to reduce number of builtin candidates in the set: + // add volatile version only if there are conversions to a volatile type. + if (HasVolatile) { + ParamTypes[0] = + S.Context.getLValueReferenceType( + S.Context.getVolatileType(CandidateTy)); + if (NumArgs == 1) + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet); + else + S.AddBuiltinCandidate(CandidateTy, ParamTypes, Args, 2, CandidateSet); + } + } + +public: + BuiltinOperatorOverloadBuilder( + Sema &S, Expr **Args, unsigned NumArgs, + Qualifiers VisibleTypeConversionsQuals, + bool HasArithmeticOrEnumeralCandidateType, + llvm::SmallVectorImpl<BuiltinCandidateTypeSet> &CandidateTypes, + OverloadCandidateSet &CandidateSet) + : S(S), Args(Args), NumArgs(NumArgs), + VisibleTypeConversionsQuals(VisibleTypeConversionsQuals), + HasArithmeticOrEnumeralCandidateType( + HasArithmeticOrEnumeralCandidateType), + CandidateTypes(CandidateTypes), + CandidateSet(CandidateSet) { + // Validate some of our static helper constants in debug builds. + assert(getArithmeticType(FirstPromotedIntegralType) == S.Context.IntTy && + "Invalid first promoted integral type"); + assert(getArithmeticType(LastPromotedIntegralType - 1) + == S.Context.UnsignedLongLongTy && + "Invalid last promoted integral type"); + assert(getArithmeticType(FirstPromotedArithmeticType) + == S.Context.FloatTy && + "Invalid first promoted arithmetic type"); + assert(getArithmeticType(LastPromotedArithmeticType - 1) + == S.Context.UnsignedLongLongTy && + "Invalid last promoted arithmetic type"); + } + + // C++ [over.built]p3: + // + // For every pair (T, VQ), where T is an arithmetic type, and VQ + // is either volatile or empty, there exist candidate operator + // functions of the form + // + // VQ T& operator++(VQ T&); + // T operator++(VQ T&, int); + // + // C++ [over.built]p4: + // + // For every pair (T, VQ), where T is an arithmetic type other + // than bool, and VQ is either volatile or empty, there exist + // candidate operator functions of the form + // + // VQ T& operator--(VQ T&); + // T operator--(VQ T&, int); + void addPlusPlusMinusMinusArithmeticOverloads(OverloadedOperatorKind Op) { + if (!HasArithmeticOrEnumeralCandidateType) + return; - case OO_PlusPlus: - case OO_MinusMinus: - // C++ [over.built]p3: - // - // For every pair (T, VQ), where T is an arithmetic type, and VQ - // is either volatile or empty, there exist candidate operator - // functions of the form - // - // VQ T& operator++(VQ T&); - // T operator++(VQ T&, int); - // - // C++ [over.built]p4: - // - // For every pair (T, VQ), where T is an arithmetic type other - // than bool, and VQ is either volatile or empty, there exist - // candidate operator functions of the form - // - // VQ T& operator--(VQ T&); - // T operator--(VQ T&, int); for (unsigned Arith = (Op == OO_PlusPlus? 0 : 1); Arith < NumArithmeticTypes; ++Arith) { - QualType ArithTy = ArithmeticTypes[Arith]; - QualType ParamTypes[2] - = { Context.getLValueReferenceType(ArithTy), Context.IntTy }; - - // Non-volatile version. - if (NumArgs == 1) - AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet); - else - AddBuiltinCandidate(ArithTy, ParamTypes, Args, 2, CandidateSet); - // heuristic to reduce number of builtin candidates in the set. - // Add volatile version only if there are conversions to a volatile type. - if (VisibleTypeConversionsQuals.hasVolatile()) { - // Volatile version - ParamTypes[0] - = Context.getLValueReferenceType(Context.getVolatileType(ArithTy)); - if (NumArgs == 1) - AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet); - else - AddBuiltinCandidate(ArithTy, ParamTypes, Args, 2, CandidateSet); - } + addPlusPlusMinusMinusStyleOverloads( + getArithmeticType(Arith), + VisibleTypeConversionsQuals.hasVolatile()); } + } - // C++ [over.built]p5: - // - // For every pair (T, VQ), where T is a cv-qualified or - // cv-unqualified object type, and VQ is either volatile or - // empty, there exist candidate operator functions of the form - // - // T*VQ& operator++(T*VQ&); - // T*VQ& operator--(T*VQ&); - // T* operator++(T*VQ&, int); - // T* operator--(T*VQ&, int); - for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin(); - Ptr != CandidateTypes.pointer_end(); ++Ptr) { + // C++ [over.built]p5: + // + // For every pair (T, VQ), where T is a cv-qualified or + // cv-unqualified object type, and VQ is either volatile or + // empty, there exist candidate operator functions of the form + // + // T*VQ& operator++(T*VQ&); + // T*VQ& operator--(T*VQ&); + // T* operator++(T*VQ&, int); + // T* operator--(T*VQ&, int); + void addPlusPlusMinusMinusPointerOverloads() { + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[0].pointer_begin(), + PtrEnd = CandidateTypes[0].pointer_end(); + Ptr != PtrEnd; ++Ptr) { // Skip pointer types that aren't pointers to object types. - if (!(*Ptr)->getPointeeType()->isIncompleteOrObjectType()) + if (!(*Ptr)->getPointeeType()->isObjectType()) continue; - QualType ParamTypes[2] = { - Context.getLValueReferenceType(*Ptr), Context.IntTy - }; - - // Without volatile - if (NumArgs == 1) - AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet); - else - AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet); - - if (!Context.getCanonicalType(*Ptr).isVolatileQualified() && - VisibleTypeConversionsQuals.hasVolatile()) { - // With volatile - ParamTypes[0] - = Context.getLValueReferenceType(Context.getVolatileType(*Ptr)); - if (NumArgs == 1) - AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet); - else - AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet); - } + addPlusPlusMinusMinusStyleOverloads(*Ptr, + (!S.Context.getCanonicalType(*Ptr).isVolatileQualified() && + VisibleTypeConversionsQuals.hasVolatile())); } - break; + } - UnaryStar: - // C++ [over.built]p6: - // For every cv-qualified or cv-unqualified object type T, there - // exist candidate operator functions of the form - // - // T& operator*(T*); - // - // C++ [over.built]p7: - // For every function type T, there exist candidate operator - // functions of the form - // T& operator*(T*); - for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin(); - Ptr != CandidateTypes.pointer_end(); ++Ptr) { + // C++ [over.built]p6: + // For every cv-qualified or cv-unqualified object type T, there + // exist candidate operator functions of the form + // + // T& operator*(T*); + // + // C++ [over.built]p7: + // For every function type T that does not have cv-qualifiers or a + // ref-qualifier, there exist candidate operator functions of the form + // T& operator*(T*); + void addUnaryStarPointerOverloads() { + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[0].pointer_begin(), + PtrEnd = CandidateTypes[0].pointer_end(); + Ptr != PtrEnd; ++Ptr) { QualType ParamTy = *Ptr; QualType PointeeTy = ParamTy->getPointeeType(); - AddBuiltinCandidate(Context.getLValueReferenceType(PointeeTy), - &ParamTy, Args, 1, CandidateSet); - } - break; + if (!PointeeTy->isObjectType() && !PointeeTy->isFunctionType()) + continue; - UnaryPlus: - // C++ [over.built]p8: - // For every type T, there exist candidate operator functions of - // the form - // - // T* operator+(T*); - for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin(); - Ptr != CandidateTypes.pointer_end(); ++Ptr) { - QualType ParamTy = *Ptr; - AddBuiltinCandidate(ParamTy, &ParamTy, Args, 1, CandidateSet); + if (const FunctionProtoType *Proto =PointeeTy->getAs<FunctionProtoType>()) + if (Proto->getTypeQuals() || Proto->getRefQualifier()) + continue; + + S.AddBuiltinCandidate(S.Context.getLValueReferenceType(PointeeTy), + &ParamTy, Args, 1, CandidateSet); } + } - // Fall through + // C++ [over.built]p9: + // For every promoted arithmetic type T, there exist candidate + // operator functions of the form + // + // T operator+(T); + // T operator-(T); + void addUnaryPlusOrMinusArithmeticOverloads() { + if (!HasArithmeticOrEnumeralCandidateType) + return; - UnaryMinus: - // C++ [over.built]p9: - // For every promoted arithmetic type T, there exist candidate - // operator functions of the form - // - // T operator+(T); - // T operator-(T); for (unsigned Arith = FirstPromotedArithmeticType; Arith < LastPromotedArithmeticType; ++Arith) { - QualType ArithTy = ArithmeticTypes[Arith]; - AddBuiltinCandidate(ArithTy, &ArithTy, Args, 1, CandidateSet); + QualType ArithTy = getArithmeticType(Arith); + S.AddBuiltinCandidate(ArithTy, &ArithTy, Args, 1, CandidateSet); } - + // Extension: We also add these operators for vector types. - for (BuiltinCandidateTypeSet::iterator Vec = CandidateTypes.vector_begin(), - VecEnd = CandidateTypes.vector_end(); + for (BuiltinCandidateTypeSet::iterator + Vec = CandidateTypes[0].vector_begin(), + VecEnd = CandidateTypes[0].vector_end(); Vec != VecEnd; ++Vec) { QualType VecTy = *Vec; - AddBuiltinCandidate(VecTy, &VecTy, Args, 1, CandidateSet); + S.AddBuiltinCandidate(VecTy, &VecTy, Args, 1, CandidateSet); } - break; + } + + // C++ [over.built]p8: + // For every type T, there exist candidate operator functions of + // the form + // + // T* operator+(T*); + void addUnaryPlusPointerOverloads() { + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[0].pointer_begin(), + PtrEnd = CandidateTypes[0].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + QualType ParamTy = *Ptr; + S.AddBuiltinCandidate(ParamTy, &ParamTy, Args, 1, CandidateSet); + } + } + + // C++ [over.built]p10: + // For every promoted integral type T, there exist candidate + // operator functions of the form + // + // T operator~(T); + void addUnaryTildePromotedIntegralOverloads() { + if (!HasArithmeticOrEnumeralCandidateType) + return; - case OO_Tilde: - // C++ [over.built]p10: - // For every promoted integral type T, there exist candidate - // operator functions of the form - // - // T operator~(T); for (unsigned Int = FirstPromotedIntegralType; Int < LastPromotedIntegralType; ++Int) { - QualType IntTy = ArithmeticTypes[Int]; - AddBuiltinCandidate(IntTy, &IntTy, Args, 1, CandidateSet); + QualType IntTy = getArithmeticType(Int); + S.AddBuiltinCandidate(IntTy, &IntTy, Args, 1, CandidateSet); } - + // Extension: We also add this operator for vector types. - for (BuiltinCandidateTypeSet::iterator Vec = CandidateTypes.vector_begin(), - VecEnd = CandidateTypes.vector_end(); + for (BuiltinCandidateTypeSet::iterator + Vec = CandidateTypes[0].vector_begin(), + VecEnd = CandidateTypes[0].vector_end(); Vec != VecEnd; ++Vec) { QualType VecTy = *Vec; - AddBuiltinCandidate(VecTy, &VecTy, Args, 1, CandidateSet); - } - break; + S.AddBuiltinCandidate(VecTy, &VecTy, Args, 1, CandidateSet); + } + } - case OO_New: - case OO_Delete: - case OO_Array_New: - case OO_Array_Delete: - case OO_Call: - assert(false && "Special operators don't use AddBuiltinOperatorCandidates"); - break; + // C++ [over.match.oper]p16: + // For every pointer to member type T, there exist candidate operator + // functions of the form + // + // bool operator==(T,T); + // bool operator!=(T,T); + void addEqualEqualOrNotEqualMemberPointerOverloads() { + /// Set of (canonical) types that we've already handled. + llvm::SmallPtrSet<QualType, 8> AddedTypes; + + for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) { + for (BuiltinCandidateTypeSet::iterator + MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(), + MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end(); + MemPtr != MemPtrEnd; + ++MemPtr) { + // Don't add the same builtin candidate twice. + if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr))) + continue; - case OO_Comma: - UnaryAmp: - case OO_Arrow: - // C++ [over.match.oper]p3: - // -- For the operator ',', the unary operator '&', or the - // operator '->', the built-in candidates set is empty. - break; + QualType ParamTypes[2] = { *MemPtr, *MemPtr }; + S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, 2, + CandidateSet); + } + } + } - case OO_EqualEqual: - case OO_ExclaimEqual: - // C++ [over.match.oper]p16: - // For every pointer to member type T, there exist candidate operator - // functions of the form + // C++ [over.built]p15: + // + // For every pointer or enumeration type T, there exist + // candidate operator functions of the form + // + // bool operator<(T, T); + // bool operator>(T, T); + // bool operator<=(T, T); + // bool operator>=(T, T); + // bool operator==(T, T); + // bool operator!=(T, T); + void addRelationalPointerOrEnumeralOverloads() { + // C++ [over.built]p1: + // If there is a user-written candidate with the same name and parameter + // types as a built-in candidate operator function, the built-in operator + // function is hidden and is not included in the set of candidate + // functions. // - // bool operator==(T,T); - // bool operator!=(T,T); - for (BuiltinCandidateTypeSet::iterator - MemPtr = CandidateTypes.member_pointer_begin(), - MemPtrEnd = CandidateTypes.member_pointer_end(); - MemPtr != MemPtrEnd; - ++MemPtr) { - QualType ParamTypes[2] = { *MemPtr, *MemPtr }; - AddBuiltinCandidate(Context.BoolTy, ParamTypes, Args, 2, CandidateSet); - } + // The text is actually in a note, but if we don't implement it then we end + // up with ambiguities when the user provides an overloaded operator for + // an enumeration type. Note that only enumeration types have this problem, + // so we track which enumeration types we've seen operators for. Also, the + // only other overloaded operator with enumeration argumenst, operator=, + // cannot be overloaded for enumeration types, so this is the only place + // where we must suppress candidates like this. + llvm::DenseSet<std::pair<CanQualType, CanQualType> > + UserDefinedBinaryOperators; + + for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) { + if (CandidateTypes[ArgIdx].enumeration_begin() != + CandidateTypes[ArgIdx].enumeration_end()) { + for (OverloadCandidateSet::iterator C = CandidateSet.begin(), + CEnd = CandidateSet.end(); + C != CEnd; ++C) { + if (!C->Viable || !C->Function || C->Function->getNumParams() != 2) + continue; - // Fall through + QualType FirstParamType = + C->Function->getParamDecl(0)->getType().getUnqualifiedType(); + QualType SecondParamType = + C->Function->getParamDecl(1)->getType().getUnqualifiedType(); - case OO_Less: - case OO_Greater: - case OO_LessEqual: - case OO_GreaterEqual: - // C++ [over.built]p15: - // - // For every pointer or enumeration type T, there exist - // candidate operator functions of the form - // - // bool operator<(T, T); - // bool operator>(T, T); - // bool operator<=(T, T); - // bool operator>=(T, T); - // bool operator==(T, T); - // bool operator!=(T, T); - for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin(); - Ptr != CandidateTypes.pointer_end(); ++Ptr) { - QualType ParamTypes[2] = { *Ptr, *Ptr }; - AddBuiltinCandidate(Context.BoolTy, ParamTypes, Args, 2, CandidateSet); - } - for (BuiltinCandidateTypeSet::iterator Enum - = CandidateTypes.enumeration_begin(); - Enum != CandidateTypes.enumeration_end(); ++Enum) { - QualType ParamTypes[2] = { *Enum, *Enum }; - AddBuiltinCandidate(Context.BoolTy, ParamTypes, Args, 2, CandidateSet); + // Skip if either parameter isn't of enumeral type. + if (!FirstParamType->isEnumeralType() || + !SecondParamType->isEnumeralType()) + continue; + + // Add this operator to the set of known user-defined operators. + UserDefinedBinaryOperators.insert( + std::make_pair(S.Context.getCanonicalType(FirstParamType), + S.Context.getCanonicalType(SecondParamType))); + } + } } - // Fall through. - isComparison = true; + /// Set of (canonical) types that we've already handled. + llvm::SmallPtrSet<QualType, 8> AddedTypes; - BinaryPlus: - BinaryMinus: - if (!isComparison) { - // We didn't fall through, so we must have OO_Plus or OO_Minus. + for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) { + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[ArgIdx].pointer_begin(), + PtrEnd = CandidateTypes[ArgIdx].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + // Don't add the same builtin candidate twice. + if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr))) + continue; - // C++ [over.built]p13: - // - // For every cv-qualified or cv-unqualified object type T - // there exist candidate operator functions of the form - // - // T* operator+(T*, ptrdiff_t); - // T& operator[](T*, ptrdiff_t); [BELOW] - // T* operator-(T*, ptrdiff_t); - // T* operator+(ptrdiff_t, T*); - // T& operator[](ptrdiff_t, T*); [BELOW] - // - // C++ [over.built]p14: - // - // For every T, where T is a pointer to object type, there - // exist candidate operator functions of the form - // - // ptrdiff_t operator-(T, T); - for (BuiltinCandidateTypeSet::iterator Ptr - = CandidateTypes.pointer_begin(); - Ptr != CandidateTypes.pointer_end(); ++Ptr) { - QualType ParamTypes[2] = { *Ptr, Context.getPointerDiffType() }; + QualType ParamTypes[2] = { *Ptr, *Ptr }; + S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, 2, + CandidateSet); + } + for (BuiltinCandidateTypeSet::iterator + Enum = CandidateTypes[ArgIdx].enumeration_begin(), + EnumEnd = CandidateTypes[ArgIdx].enumeration_end(); + Enum != EnumEnd; ++Enum) { + CanQualType CanonType = S.Context.getCanonicalType(*Enum); + + // Don't add the same builtin candidate twice, or if a user defined + // candidate exists. + if (!AddedTypes.insert(CanonType) || + UserDefinedBinaryOperators.count(std::make_pair(CanonType, + CanonType))) + continue; - // operator+(T*, ptrdiff_t) or operator-(T*, ptrdiff_t) - AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet); + QualType ParamTypes[2] = { *Enum, *Enum }; + S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, 2, + CandidateSet); + } + } + } - if (Op == OO_Plus) { + // C++ [over.built]p13: + // + // For every cv-qualified or cv-unqualified object type T + // there exist candidate operator functions of the form + // + // T* operator+(T*, ptrdiff_t); + // T& operator[](T*, ptrdiff_t); [BELOW] + // T* operator-(T*, ptrdiff_t); + // T* operator+(ptrdiff_t, T*); + // T& operator[](ptrdiff_t, T*); [BELOW] + // + // C++ [over.built]p14: + // + // For every T, where T is a pointer to object type, there + // exist candidate operator functions of the form + // + // ptrdiff_t operator-(T, T); + void addBinaryPlusOrMinusPointerOverloads(OverloadedOperatorKind Op) { + /// Set of (canonical) types that we've already handled. + llvm::SmallPtrSet<QualType, 8> AddedTypes; + + for (int Arg = 0; Arg < 2; ++Arg) { + QualType AsymetricParamTypes[2] = { + S.Context.getPointerDiffType(), + S.Context.getPointerDiffType(), + }; + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[Arg].pointer_begin(), + PtrEnd = CandidateTypes[Arg].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + QualType PointeeTy = (*Ptr)->getPointeeType(); + if (!PointeeTy->isObjectType()) + continue; + + AsymetricParamTypes[Arg] = *Ptr; + if (Arg == 0 || Op == OO_Plus) { + // operator+(T*, ptrdiff_t) or operator-(T*, ptrdiff_t) // T* operator+(ptrdiff_t, T*); - ParamTypes[0] = ParamTypes[1]; - ParamTypes[1] = *Ptr; - AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet); - } else { + S.AddBuiltinCandidate(*Ptr, AsymetricParamTypes, Args, 2, + CandidateSet); + } + if (Op == OO_Minus) { // ptrdiff_t operator-(T, T); - ParamTypes[1] = *Ptr; - AddBuiltinCandidate(Context.getPointerDiffType(), ParamTypes, - Args, 2, CandidateSet); + if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr))) + continue; + + QualType ParamTypes[2] = { *Ptr, *Ptr }; + S.AddBuiltinCandidate(S.Context.getPointerDiffType(), ParamTypes, + Args, 2, CandidateSet); } } } - // Fall through + } + + // C++ [over.built]p12: + // + // For every pair of promoted arithmetic types L and R, there + // exist candidate operator functions of the form + // + // LR operator*(L, R); + // LR operator/(L, R); + // LR operator+(L, R); + // LR operator-(L, R); + // bool operator<(L, R); + // bool operator>(L, R); + // bool operator<=(L, R); + // bool operator>=(L, R); + // bool operator==(L, R); + // bool operator!=(L, R); + // + // where LR is the result of the usual arithmetic conversions + // between types L and R. + // + // C++ [over.built]p24: + // + // For every pair of promoted arithmetic types L and R, there exist + // candidate operator functions of the form + // + // LR operator?(bool, L, R); + // + // where LR is the result of the usual arithmetic conversions + // between types L and R. + // Our candidates ignore the first parameter. + void addGenericBinaryArithmeticOverloads(bool isComparison) { + if (!HasArithmeticOrEnumeralCandidateType) + return; - case OO_Slash: - BinaryStar: - Conditional: - // C++ [over.built]p12: - // - // For every pair of promoted arithmetic types L and R, there - // exist candidate operator functions of the form - // - // LR operator*(L, R); - // LR operator/(L, R); - // LR operator+(L, R); - // LR operator-(L, R); - // bool operator<(L, R); - // bool operator>(L, R); - // bool operator<=(L, R); - // bool operator>=(L, R); - // bool operator==(L, R); - // bool operator!=(L, R); - // - // where LR is the result of the usual arithmetic conversions - // between types L and R. - // - // C++ [over.built]p24: - // - // For every pair of promoted arithmetic types L and R, there exist - // candidate operator functions of the form - // - // LR operator?(bool, L, R); - // - // where LR is the result of the usual arithmetic conversions - // between types L and R. - // Our candidates ignore the first parameter. for (unsigned Left = FirstPromotedArithmeticType; Left < LastPromotedArithmeticType; ++Left) { for (unsigned Right = FirstPromotedArithmeticType; Right < LastPromotedArithmeticType; ++Right) { - QualType LandR[2] = { ArithmeticTypes[Left], ArithmeticTypes[Right] }; - QualType Result - = isComparison - ? Context.BoolTy - : Context.UsualArithmeticConversionsType(LandR[0], LandR[1]); - AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet); + QualType LandR[2] = { getArithmeticType(Left), + getArithmeticType(Right) }; + QualType Result = + isComparison ? S.Context.BoolTy + : getUsualArithmeticConversions(Left, Right); + S.AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet); } } // Extension: Add the binary operators ==, !=, <, <=, >=, >, *, /, and the // conditional operator for vector types. - for (BuiltinCandidateTypeSet::iterator Vec1 = CandidateTypes.vector_begin(), - Vec1End = CandidateTypes.vector_end(); - Vec1 != Vec1End; ++Vec1) - for (BuiltinCandidateTypeSet::iterator - Vec2 = CandidateTypes.vector_begin(), - Vec2End = CandidateTypes.vector_end(); + for (BuiltinCandidateTypeSet::iterator + Vec1 = CandidateTypes[0].vector_begin(), + Vec1End = CandidateTypes[0].vector_end(); + Vec1 != Vec1End; ++Vec1) { + for (BuiltinCandidateTypeSet::iterator + Vec2 = CandidateTypes[1].vector_begin(), + Vec2End = CandidateTypes[1].vector_end(); Vec2 != Vec2End; ++Vec2) { QualType LandR[2] = { *Vec1, *Vec2 }; - QualType Result; - if (isComparison) - Result = Context.BoolTy; - else { + QualType Result = S.Context.BoolTy; + if (!isComparison) { if ((*Vec1)->isExtVectorType() || !(*Vec2)->isExtVectorType()) Result = *Vec1; else Result = *Vec2; } - - AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet); + + S.AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet); } - - break; + } + } + + // C++ [over.built]p17: + // + // For every pair of promoted integral types L and R, there + // exist candidate operator functions of the form + // + // LR operator%(L, R); + // LR operator&(L, R); + // LR operator^(L, R); + // LR operator|(L, R); + // L operator<<(L, R); + // L operator>>(L, R); + // + // where LR is the result of the usual arithmetic conversions + // between types L and R. + void addBinaryBitwiseArithmeticOverloads(OverloadedOperatorKind Op) { + if (!HasArithmeticOrEnumeralCandidateType) + return; - case OO_Percent: - BinaryAmp: - case OO_Caret: - case OO_Pipe: - case OO_LessLess: - case OO_GreaterGreater: - // C++ [over.built]p17: - // - // For every pair of promoted integral types L and R, there - // exist candidate operator functions of the form - // - // LR operator%(L, R); - // LR operator&(L, R); - // LR operator^(L, R); - // LR operator|(L, R); - // L operator<<(L, R); - // L operator>>(L, R); - // - // where LR is the result of the usual arithmetic conversions - // between types L and R. for (unsigned Left = FirstPromotedIntegralType; Left < LastPromotedIntegralType; ++Left) { for (unsigned Right = FirstPromotedIntegralType; Right < LastPromotedIntegralType; ++Right) { - QualType LandR[2] = { ArithmeticTypes[Left], ArithmeticTypes[Right] }; + QualType LandR[2] = { getArithmeticType(Left), + getArithmeticType(Right) }; QualType Result = (Op == OO_LessLess || Op == OO_GreaterGreater) ? LandR[0] - : Context.UsualArithmeticConversionsType(LandR[0], LandR[1]); - AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet); + : getUsualArithmeticConversions(Left, Right); + S.AddBuiltinCandidate(Result, LandR, Args, 2, CandidateSet); } } - break; + } - case OO_Equal: - // C++ [over.built]p20: - // - // For every pair (T, VQ), where T is an enumeration or - // pointer to member type and VQ is either volatile or - // empty, there exist candidate operator functions of the form - // - // VQ T& operator=(VQ T&, T); - for (BuiltinCandidateTypeSet::iterator - Enum = CandidateTypes.enumeration_begin(), - EnumEnd = CandidateTypes.enumeration_end(); - Enum != EnumEnd; ++Enum) - AddBuiltinAssignmentOperatorCandidates(*this, *Enum, Args, 2, - CandidateSet); - for (BuiltinCandidateTypeSet::iterator - MemPtr = CandidateTypes.member_pointer_begin(), - MemPtrEnd = CandidateTypes.member_pointer_end(); - MemPtr != MemPtrEnd; ++MemPtr) - AddBuiltinAssignmentOperatorCandidates(*this, *MemPtr, Args, 2, - CandidateSet); - - // Fall through. + // C++ [over.built]p20: + // + // For every pair (T, VQ), where T is an enumeration or + // pointer to member type and VQ is either volatile or + // empty, there exist candidate operator functions of the form + // + // VQ T& operator=(VQ T&, T); + void addAssignmentMemberPointerOrEnumeralOverloads() { + /// Set of (canonical) types that we've already handled. + llvm::SmallPtrSet<QualType, 8> AddedTypes; + + for (unsigned ArgIdx = 0; ArgIdx < 2; ++ArgIdx) { + for (BuiltinCandidateTypeSet::iterator + Enum = CandidateTypes[ArgIdx].enumeration_begin(), + EnumEnd = CandidateTypes[ArgIdx].enumeration_end(); + Enum != EnumEnd; ++Enum) { + if (!AddedTypes.insert(S.Context.getCanonicalType(*Enum))) + continue; - case OO_PlusEqual: - case OO_MinusEqual: - // C++ [over.built]p19: - // - // For every pair (T, VQ), where T is any type and VQ is either - // volatile or empty, there exist candidate operator functions - // of the form - // - // T*VQ& operator=(T*VQ&, T*); - // - // C++ [over.built]p21: - // - // For every pair (T, VQ), where T is a cv-qualified or - // cv-unqualified object type and VQ is either volatile or - // empty, there exist candidate operator functions of the form - // - // T*VQ& operator+=(T*VQ&, ptrdiff_t); - // T*VQ& operator-=(T*VQ&, ptrdiff_t); - for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin(); - Ptr != CandidateTypes.pointer_end(); ++Ptr) { - QualType ParamTypes[2]; - ParamTypes[1] = (Op == OO_Equal)? *Ptr : Context.getPointerDiffType(); + AddBuiltinAssignmentOperatorCandidates(S, *Enum, Args, 2, + CandidateSet); + } + + for (BuiltinCandidateTypeSet::iterator + MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(), + MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end(); + MemPtr != MemPtrEnd; ++MemPtr) { + if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr))) + continue; + + AddBuiltinAssignmentOperatorCandidates(S, *MemPtr, Args, 2, + CandidateSet); + } + } + } + + // C++ [over.built]p19: + // + // For every pair (T, VQ), where T is any type and VQ is either + // volatile or empty, there exist candidate operator functions + // of the form + // + // T*VQ& operator=(T*VQ&, T*); + // + // C++ [over.built]p21: + // + // For every pair (T, VQ), where T is a cv-qualified or + // cv-unqualified object type and VQ is either volatile or + // empty, there exist candidate operator functions of the form + // + // T*VQ& operator+=(T*VQ&, ptrdiff_t); + // T*VQ& operator-=(T*VQ&, ptrdiff_t); + void addAssignmentPointerOverloads(bool isEqualOp) { + /// Set of (canonical) types that we've already handled. + llvm::SmallPtrSet<QualType, 8> AddedTypes; + + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[0].pointer_begin(), + PtrEnd = CandidateTypes[0].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + // If this is operator=, keep track of the builtin candidates we added. + if (isEqualOp) + AddedTypes.insert(S.Context.getCanonicalType(*Ptr)); + else if (!(*Ptr)->getPointeeType()->isObjectType()) + continue; // non-volatile version - ParamTypes[0] = Context.getLValueReferenceType(*Ptr); - AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, - /*IsAssigmentOperator=*/Op == OO_Equal); + QualType ParamTypes[2] = { + S.Context.getLValueReferenceType(*Ptr), + isEqualOp ? *Ptr : S.Context.getPointerDiffType(), + }; + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, + /*IsAssigmentOperator=*/ isEqualOp); - if (!Context.getCanonicalType(*Ptr).isVolatileQualified() && + if (!S.Context.getCanonicalType(*Ptr).isVolatileQualified() && VisibleTypeConversionsQuals.hasVolatile()) { // volatile version - ParamTypes[0] - = Context.getLValueReferenceType(Context.getVolatileType(*Ptr)); - AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, - /*IsAssigmentOperator=*/Op == OO_Equal); + ParamTypes[0] = + S.Context.getLValueReferenceType(S.Context.getVolatileType(*Ptr)); + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, + /*IsAssigmentOperator=*/isEqualOp); } } - // Fall through. - case OO_StarEqual: - case OO_SlashEqual: - // C++ [over.built]p18: - // - // For every triple (L, VQ, R), where L is an arithmetic type, - // VQ is either volatile or empty, and R is a promoted - // arithmetic type, there exist candidate operator functions of - // the form - // - // VQ L& operator=(VQ L&, R); - // VQ L& operator*=(VQ L&, R); - // VQ L& operator/=(VQ L&, R); - // VQ L& operator+=(VQ L&, R); - // VQ L& operator-=(VQ L&, R); + if (isEqualOp) { + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[1].pointer_begin(), + PtrEnd = CandidateTypes[1].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + // Make sure we don't add the same candidate twice. + if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr))) + continue; + + QualType ParamTypes[2] = { + S.Context.getLValueReferenceType(*Ptr), + *Ptr, + }; + + // non-volatile version + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, + /*IsAssigmentOperator=*/true); + + if (!S.Context.getCanonicalType(*Ptr).isVolatileQualified() && + VisibleTypeConversionsQuals.hasVolatile()) { + // volatile version + ParamTypes[0] = + S.Context.getLValueReferenceType(S.Context.getVolatileType(*Ptr)); + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, + CandidateSet, /*IsAssigmentOperator=*/true); + } + } + } + } + + // C++ [over.built]p18: + // + // For every triple (L, VQ, R), where L is an arithmetic type, + // VQ is either volatile or empty, and R is a promoted + // arithmetic type, there exist candidate operator functions of + // the form + // + // VQ L& operator=(VQ L&, R); + // VQ L& operator*=(VQ L&, R); + // VQ L& operator/=(VQ L&, R); + // VQ L& operator+=(VQ L&, R); + // VQ L& operator-=(VQ L&, R); + void addAssignmentArithmeticOverloads(bool isEqualOp) { + if (!HasArithmeticOrEnumeralCandidateType) + return; + for (unsigned Left = 0; Left < NumArithmeticTypes; ++Left) { for (unsigned Right = FirstPromotedArithmeticType; Right < LastPromotedArithmeticType; ++Right) { QualType ParamTypes[2]; - ParamTypes[1] = ArithmeticTypes[Right]; + ParamTypes[1] = getArithmeticType(Right); // Add this built-in operator as a candidate (VQ is empty). - ParamTypes[0] = Context.getLValueReferenceType(ArithmeticTypes[Left]); - AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, - /*IsAssigmentOperator=*/Op == OO_Equal); + ParamTypes[0] = + S.Context.getLValueReferenceType(getArithmeticType(Left)); + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, + /*IsAssigmentOperator=*/isEqualOp); // Add this built-in operator as a candidate (VQ is 'volatile'). if (VisibleTypeConversionsQuals.hasVolatile()) { - ParamTypes[0] = Context.getVolatileType(ArithmeticTypes[Left]); - ParamTypes[0] = Context.getLValueReferenceType(ParamTypes[0]); - AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, - /*IsAssigmentOperator=*/Op == OO_Equal); + ParamTypes[0] = + S.Context.getVolatileType(getArithmeticType(Left)); + ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]); + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, + CandidateSet, + /*IsAssigmentOperator=*/isEqualOp); } } } - + // Extension: Add the binary operators =, +=, -=, *=, /= for vector types. - for (BuiltinCandidateTypeSet::iterator Vec1 = CandidateTypes.vector_begin(), - Vec1End = CandidateTypes.vector_end(); - Vec1 != Vec1End; ++Vec1) - for (BuiltinCandidateTypeSet::iterator - Vec2 = CandidateTypes.vector_begin(), - Vec2End = CandidateTypes.vector_end(); + for (BuiltinCandidateTypeSet::iterator + Vec1 = CandidateTypes[0].vector_begin(), + Vec1End = CandidateTypes[0].vector_end(); + Vec1 != Vec1End; ++Vec1) { + for (BuiltinCandidateTypeSet::iterator + Vec2 = CandidateTypes[1].vector_begin(), + Vec2End = CandidateTypes[1].vector_end(); Vec2 != Vec2End; ++Vec2) { QualType ParamTypes[2]; ParamTypes[1] = *Vec2; // Add this built-in operator as a candidate (VQ is empty). - ParamTypes[0] = Context.getLValueReferenceType(*Vec1); - AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, - /*IsAssigmentOperator=*/Op == OO_Equal); - + ParamTypes[0] = S.Context.getLValueReferenceType(*Vec1); + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, + /*IsAssigmentOperator=*/isEqualOp); + // Add this built-in operator as a candidate (VQ is 'volatile'). if (VisibleTypeConversionsQuals.hasVolatile()) { - ParamTypes[0] = Context.getVolatileType(*Vec1); - ParamTypes[0] = Context.getLValueReferenceType(ParamTypes[0]); - AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, - /*IsAssigmentOperator=*/Op == OO_Equal); + ParamTypes[0] = S.Context.getVolatileType(*Vec1); + ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]); + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, + CandidateSet, + /*IsAssigmentOperator=*/isEqualOp); } } - break; + } + } + + // C++ [over.built]p22: + // + // For every triple (L, VQ, R), where L is an integral type, VQ + // is either volatile or empty, and R is a promoted integral + // type, there exist candidate operator functions of the form + // + // VQ L& operator%=(VQ L&, R); + // VQ L& operator<<=(VQ L&, R); + // VQ L& operator>>=(VQ L&, R); + // VQ L& operator&=(VQ L&, R); + // VQ L& operator^=(VQ L&, R); + // VQ L& operator|=(VQ L&, R); + void addAssignmentIntegralOverloads() { + if (!HasArithmeticOrEnumeralCandidateType) + return; - case OO_PercentEqual: - case OO_LessLessEqual: - case OO_GreaterGreaterEqual: - case OO_AmpEqual: - case OO_CaretEqual: - case OO_PipeEqual: - // C++ [over.built]p22: - // - // For every triple (L, VQ, R), where L is an integral type, VQ - // is either volatile or empty, and R is a promoted integral - // type, there exist candidate operator functions of the form - // - // VQ L& operator%=(VQ L&, R); - // VQ L& operator<<=(VQ L&, R); - // VQ L& operator>>=(VQ L&, R); - // VQ L& operator&=(VQ L&, R); - // VQ L& operator^=(VQ L&, R); - // VQ L& operator|=(VQ L&, R); for (unsigned Left = FirstIntegralType; Left < LastIntegralType; ++Left) { for (unsigned Right = FirstPromotedIntegralType; Right < LastPromotedIntegralType; ++Right) { QualType ParamTypes[2]; - ParamTypes[1] = ArithmeticTypes[Right]; + ParamTypes[1] = getArithmeticType(Right); // Add this built-in operator as a candidate (VQ is empty). - ParamTypes[0] = Context.getLValueReferenceType(ArithmeticTypes[Left]); - AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet); + ParamTypes[0] = + S.Context.getLValueReferenceType(getArithmeticType(Left)); + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet); if (VisibleTypeConversionsQuals.hasVolatile()) { // Add this built-in operator as a candidate (VQ is 'volatile'). - ParamTypes[0] = ArithmeticTypes[Left]; - ParamTypes[0] = Context.getVolatileType(ParamTypes[0]); - ParamTypes[0] = Context.getLValueReferenceType(ParamTypes[0]); - AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet); + ParamTypes[0] = getArithmeticType(Left); + ParamTypes[0] = S.Context.getVolatileType(ParamTypes[0]); + ParamTypes[0] = S.Context.getLValueReferenceType(ParamTypes[0]); + S.AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, + CandidateSet); } } } - break; - - case OO_Exclaim: { - // C++ [over.operator]p23: - // - // There also exist candidate operator functions of the form - // - // bool operator!(bool); - // bool operator&&(bool, bool); [BELOW] - // bool operator||(bool, bool); [BELOW] - QualType ParamTy = Context.BoolTy; - AddBuiltinCandidate(ParamTy, &ParamTy, Args, 1, CandidateSet, - /*IsAssignmentOperator=*/false, - /*NumContextualBoolArguments=*/1); - break; - } - - case OO_AmpAmp: - case OO_PipePipe: { - // C++ [over.operator]p23: - // - // There also exist candidate operator functions of the form - // - // bool operator!(bool); [ABOVE] - // bool operator&&(bool, bool); - // bool operator||(bool, bool); - QualType ParamTypes[2] = { Context.BoolTy, Context.BoolTy }; - AddBuiltinCandidate(Context.BoolTy, ParamTypes, Args, 2, CandidateSet, - /*IsAssignmentOperator=*/false, - /*NumContextualBoolArguments=*/2); - break; } - case OO_Subscript: - // C++ [over.built]p13: - // - // For every cv-qualified or cv-unqualified object type T there - // exist candidate operator functions of the form - // - // T* operator+(T*, ptrdiff_t); [ABOVE] - // T& operator[](T*, ptrdiff_t); - // T* operator-(T*, ptrdiff_t); [ABOVE] - // T* operator+(ptrdiff_t, T*); [ABOVE] - // T& operator[](ptrdiff_t, T*); - for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin(); - Ptr != CandidateTypes.pointer_end(); ++Ptr) { - QualType ParamTypes[2] = { *Ptr, Context.getPointerDiffType() }; + // C++ [over.operator]p23: + // + // There also exist candidate operator functions of the form + // + // bool operator!(bool); + // bool operator&&(bool, bool); + // bool operator||(bool, bool); + void addExclaimOverload() { + QualType ParamTy = S.Context.BoolTy; + S.AddBuiltinCandidate(ParamTy, &ParamTy, Args, 1, CandidateSet, + /*IsAssignmentOperator=*/false, + /*NumContextualBoolArguments=*/1); + } + void addAmpAmpOrPipePipeOverload() { + QualType ParamTypes[2] = { S.Context.BoolTy, S.Context.BoolTy }; + S.AddBuiltinCandidate(S.Context.BoolTy, ParamTypes, Args, 2, CandidateSet, + /*IsAssignmentOperator=*/false, + /*NumContextualBoolArguments=*/2); + } + + // C++ [over.built]p13: + // + // For every cv-qualified or cv-unqualified object type T there + // exist candidate operator functions of the form + // + // T* operator+(T*, ptrdiff_t); [ABOVE] + // T& operator[](T*, ptrdiff_t); + // T* operator-(T*, ptrdiff_t); [ABOVE] + // T* operator+(ptrdiff_t, T*); [ABOVE] + // T& operator[](ptrdiff_t, T*); + void addSubscriptOverloads() { + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[0].pointer_begin(), + PtrEnd = CandidateTypes[0].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + QualType ParamTypes[2] = { *Ptr, S.Context.getPointerDiffType() }; QualType PointeeType = (*Ptr)->getPointeeType(); - QualType ResultTy = Context.getLValueReferenceType(PointeeType); + if (!PointeeType->isObjectType()) + continue; + + QualType ResultTy = S.Context.getLValueReferenceType(PointeeType); // T& operator[](T*, ptrdiff_t) - AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet); + S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet); + } - // T& operator[](ptrdiff_t, T*); - ParamTypes[0] = ParamTypes[1]; - ParamTypes[1] = *Ptr; - AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet); - } - break; + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[1].pointer_begin(), + PtrEnd = CandidateTypes[1].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + QualType ParamTypes[2] = { S.Context.getPointerDiffType(), *Ptr }; + QualType PointeeType = (*Ptr)->getPointeeType(); + if (!PointeeType->isObjectType()) + continue; - case OO_ArrowStar: - // C++ [over.built]p11: - // For every quintuple (C1, C2, T, CV1, CV2), where C2 is a class type, - // C1 is the same type as C2 or is a derived class of C2, T is an object - // type or a function type, and CV1 and CV2 are cv-qualifier-seqs, - // there exist candidate operator functions of the form - // CV12 T& operator->*(CV1 C1*, CV2 T C2::*); - // where CV12 is the union of CV1 and CV2. - { - for (BuiltinCandidateTypeSet::iterator Ptr = - CandidateTypes.pointer_begin(); - Ptr != CandidateTypes.pointer_end(); ++Ptr) { - QualType C1Ty = (*Ptr); - QualType C1; - QualifierCollector Q1; - C1 = QualType(Q1.strip(C1Ty->getPointeeType()), 0); - if (!isa<RecordType>(C1)) + QualType ResultTy = S.Context.getLValueReferenceType(PointeeType); + + // T& operator[](ptrdiff_t, T*) + S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet); + } + } + + // C++ [over.built]p11: + // For every quintuple (C1, C2, T, CV1, CV2), where C2 is a class type, + // C1 is the same type as C2 or is a derived class of C2, T is an object + // type or a function type, and CV1 and CV2 are cv-qualifier-seqs, + // there exist candidate operator functions of the form + // + // CV12 T& operator->*(CV1 C1*, CV2 T C2::*); + // + // where CV12 is the union of CV1 and CV2. + void addArrowStarOverloads() { + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[0].pointer_begin(), + PtrEnd = CandidateTypes[0].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + QualType C1Ty = (*Ptr); + QualType C1; + QualifierCollector Q1; + C1 = QualType(Q1.strip(C1Ty->getPointeeType()), 0); + if (!isa<RecordType>(C1)) + continue; + // heuristic to reduce number of builtin candidates in the set. + // Add volatile/restrict version only if there are conversions to a + // volatile/restrict type. + if (!VisibleTypeConversionsQuals.hasVolatile() && Q1.hasVolatile()) + continue; + if (!VisibleTypeConversionsQuals.hasRestrict() && Q1.hasRestrict()) + continue; + for (BuiltinCandidateTypeSet::iterator + MemPtr = CandidateTypes[1].member_pointer_begin(), + MemPtrEnd = CandidateTypes[1].member_pointer_end(); + MemPtr != MemPtrEnd; ++MemPtr) { + const MemberPointerType *mptr = cast<MemberPointerType>(*MemPtr); + QualType C2 = QualType(mptr->getClass(), 0); + C2 = C2.getUnqualifiedType(); + if (C1 != C2 && !S.IsDerivedFrom(C1, C2)) + break; + QualType ParamTypes[2] = { *Ptr, *MemPtr }; + // build CV12 T& + QualType T = mptr->getPointeeType(); + if (!VisibleTypeConversionsQuals.hasVolatile() && + T.isVolatileQualified()) + continue; + if (!VisibleTypeConversionsQuals.hasRestrict() && + T.isRestrictQualified()) continue; - // heuristic to reduce number of builtin candidates in the set. - // Add volatile/restrict version only if there are conversions to a - // volatile/restrict type. - if (!VisibleTypeConversionsQuals.hasVolatile() && Q1.hasVolatile()) + T = Q1.apply(S.Context, T); + QualType ResultTy = S.Context.getLValueReferenceType(T); + S.AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet); + } + } + } + + // Note that we don't consider the first argument, since it has been + // contextually converted to bool long ago. The candidates below are + // therefore added as binary. + // + // C++ [over.built]p25: + // For every type T, where T is a pointer, pointer-to-member, or scoped + // enumeration type, there exist candidate operator functions of the form + // + // T operator?(bool, T, T); + // + void addConditionalOperatorOverloads() { + /// Set of (canonical) types that we've already handled. + llvm::SmallPtrSet<QualType, 8> AddedTypes; + + for (unsigned ArgIdx = 0; ArgIdx < 2; ++ArgIdx) { + for (BuiltinCandidateTypeSet::iterator + Ptr = CandidateTypes[ArgIdx].pointer_begin(), + PtrEnd = CandidateTypes[ArgIdx].pointer_end(); + Ptr != PtrEnd; ++Ptr) { + if (!AddedTypes.insert(S.Context.getCanonicalType(*Ptr))) continue; - if (!VisibleTypeConversionsQuals.hasRestrict() && Q1.hasRestrict()) + + QualType ParamTypes[2] = { *Ptr, *Ptr }; + S.AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet); + } + + for (BuiltinCandidateTypeSet::iterator + MemPtr = CandidateTypes[ArgIdx].member_pointer_begin(), + MemPtrEnd = CandidateTypes[ArgIdx].member_pointer_end(); + MemPtr != MemPtrEnd; ++MemPtr) { + if (!AddedTypes.insert(S.Context.getCanonicalType(*MemPtr))) continue; + + QualType ParamTypes[2] = { *MemPtr, *MemPtr }; + S.AddBuiltinCandidate(*MemPtr, ParamTypes, Args, 2, CandidateSet); + } + + if (S.getLangOptions().CPlusPlus0x) { for (BuiltinCandidateTypeSet::iterator - MemPtr = CandidateTypes.member_pointer_begin(), - MemPtrEnd = CandidateTypes.member_pointer_end(); - MemPtr != MemPtrEnd; ++MemPtr) { - const MemberPointerType *mptr = cast<MemberPointerType>(*MemPtr); - QualType C2 = QualType(mptr->getClass(), 0); - C2 = C2.getUnqualifiedType(); - if (C1 != C2 && !IsDerivedFrom(C1, C2)) - break; - QualType ParamTypes[2] = { *Ptr, *MemPtr }; - // build CV12 T& - QualType T = mptr->getPointeeType(); - if (!VisibleTypeConversionsQuals.hasVolatile() && - T.isVolatileQualified()) + Enum = CandidateTypes[ArgIdx].enumeration_begin(), + EnumEnd = CandidateTypes[ArgIdx].enumeration_end(); + Enum != EnumEnd; ++Enum) { + if (!(*Enum)->getAs<EnumType>()->getDecl()->isScoped()) continue; - if (!VisibleTypeConversionsQuals.hasRestrict() && - T.isRestrictQualified()) + + if (!AddedTypes.insert(S.Context.getCanonicalType(*Enum))) continue; - T = Q1.apply(T); - QualType ResultTy = Context.getLValueReferenceType(T); - AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet); + + QualType ParamTypes[2] = { *Enum, *Enum }; + S.AddBuiltinCandidate(*Enum, ParamTypes, Args, 2, CandidateSet); } } } + } +}; + +} // end anonymous namespace + +/// AddBuiltinOperatorCandidates - Add the appropriate built-in +/// operator overloads to the candidate set (C++ [over.built]), based +/// on the operator @p Op and the arguments given. For example, if the +/// operator is a binary '+', this routine might add "int +/// operator+(int, int)" to cover integer addition. +void +Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, + SourceLocation OpLoc, + Expr **Args, unsigned NumArgs, + OverloadCandidateSet& CandidateSet) { + // Find all of the types that the arguments can convert to, but only + // if the operator we're looking at has built-in operator candidates + // that make use of these types. Also record whether we encounter non-record + // candidate types or either arithmetic or enumeral candidate types. + Qualifiers VisibleTypeConversionsQuals; + VisibleTypeConversionsQuals.addConst(); + for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) + VisibleTypeConversionsQuals += CollectVRQualifiers(Context, Args[ArgIdx]); + + bool HasNonRecordCandidateType = false; + bool HasArithmeticOrEnumeralCandidateType = false; + llvm::SmallVector<BuiltinCandidateTypeSet, 2> CandidateTypes; + for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) { + CandidateTypes.push_back(BuiltinCandidateTypeSet(*this)); + CandidateTypes[ArgIdx].AddTypesConvertedFrom(Args[ArgIdx]->getType(), + OpLoc, + true, + (Op == OO_Exclaim || + Op == OO_AmpAmp || + Op == OO_PipePipe), + VisibleTypeConversionsQuals); + HasNonRecordCandidateType = HasNonRecordCandidateType || + CandidateTypes[ArgIdx].hasNonRecordTypes(); + HasArithmeticOrEnumeralCandidateType = + HasArithmeticOrEnumeralCandidateType || + CandidateTypes[ArgIdx].hasArithmeticOrEnumeralTypes(); + } + + // Exit early when no non-record types have been added to the candidate set + // for any of the arguments to the operator. + if (!HasNonRecordCandidateType) + return; + + // Setup an object to manage the common state for building overloads. + BuiltinOperatorOverloadBuilder OpBuilder(*this, Args, NumArgs, + VisibleTypeConversionsQuals, + HasArithmeticOrEnumeralCandidateType, + CandidateTypes, CandidateSet); + + // Dispatch over the operation to add in only those overloads which apply. + switch (Op) { + case OO_None: + case NUM_OVERLOADED_OPERATORS: + assert(false && "Expected an overloaded operator"); break; - case OO_Conditional: - // Note that we don't consider the first argument, since it has been - // contextually converted to bool long ago. The candidates below are - // therefore added as binary. - // - // C++ [over.built]p24: - // For every type T, where T is a pointer or pointer-to-member type, - // there exist candidate operator functions of the form - // - // T operator?(bool, T, T); - // - for (BuiltinCandidateTypeSet::iterator Ptr = CandidateTypes.pointer_begin(), - E = CandidateTypes.pointer_end(); Ptr != E; ++Ptr) { - QualType ParamTypes[2] = { *Ptr, *Ptr }; - AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet); - } - for (BuiltinCandidateTypeSet::iterator Ptr = - CandidateTypes.member_pointer_begin(), - E = CandidateTypes.member_pointer_end(); Ptr != E; ++Ptr) { - QualType ParamTypes[2] = { *Ptr, *Ptr }; - AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet); + case OO_New: + case OO_Delete: + case OO_Array_New: + case OO_Array_Delete: + case OO_Call: + assert(false && "Special operators don't use AddBuiltinOperatorCandidates"); + break; + + case OO_Comma: + case OO_Arrow: + // C++ [over.match.oper]p3: + // -- For the operator ',', the unary operator '&', or the + // operator '->', the built-in candidates set is empty. + break; + + case OO_Plus: // '+' is either unary or binary + if (NumArgs == 1) + OpBuilder.addUnaryPlusPointerOverloads(); + // Fall through. + + case OO_Minus: // '-' is either unary or binary + if (NumArgs == 1) { + OpBuilder.addUnaryPlusOrMinusArithmeticOverloads(); + } else { + OpBuilder.addBinaryPlusOrMinusPointerOverloads(Op); + OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false); } - goto Conditional; + break; + + case OO_Star: // '*' is either unary or binary + if (NumArgs == 1) + OpBuilder.addUnaryStarPointerOverloads(); + else + OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false); + break; + + case OO_Slash: + OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false); + break; + + case OO_PlusPlus: + case OO_MinusMinus: + OpBuilder.addPlusPlusMinusMinusArithmeticOverloads(Op); + OpBuilder.addPlusPlusMinusMinusPointerOverloads(); + break; + + case OO_EqualEqual: + case OO_ExclaimEqual: + OpBuilder.addEqualEqualOrNotEqualMemberPointerOverloads(); + // Fall through. + + case OO_Less: + case OO_Greater: + case OO_LessEqual: + case OO_GreaterEqual: + OpBuilder.addRelationalPointerOrEnumeralOverloads(); + OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/true); + break; + + case OO_Percent: + case OO_Caret: + case OO_Pipe: + case OO_LessLess: + case OO_GreaterGreater: + OpBuilder.addBinaryBitwiseArithmeticOverloads(Op); + break; + + case OO_Amp: // '&' is either unary or binary + if (NumArgs == 1) + // C++ [over.match.oper]p3: + // -- For the operator ',', the unary operator '&', or the + // operator '->', the built-in candidates set is empty. + break; + + OpBuilder.addBinaryBitwiseArithmeticOverloads(Op); + break; + + case OO_Tilde: + OpBuilder.addUnaryTildePromotedIntegralOverloads(); + break; + + case OO_Equal: + OpBuilder.addAssignmentMemberPointerOrEnumeralOverloads(); + // Fall through. + + case OO_PlusEqual: + case OO_MinusEqual: + OpBuilder.addAssignmentPointerOverloads(Op == OO_Equal); + // Fall through. + + case OO_StarEqual: + case OO_SlashEqual: + OpBuilder.addAssignmentArithmeticOverloads(Op == OO_Equal); + break; + + case OO_PercentEqual: + case OO_LessLessEqual: + case OO_GreaterGreaterEqual: + case OO_AmpEqual: + case OO_CaretEqual: + case OO_PipeEqual: + OpBuilder.addAssignmentIntegralOverloads(); + break; + + case OO_Exclaim: + OpBuilder.addExclaimOverload(); + break; + + case OO_AmpAmp: + case OO_PipePipe: + OpBuilder.addAmpAmpOrPipePipeOverload(); + break; + + case OO_Subscript: + OpBuilder.addSubscriptOverloads(); + break; + + case OO_ArrowStar: + OpBuilder.addArrowStarOverloads(); + break; + + case OO_Conditional: + OpBuilder.addConditionalOperatorOverloads(); + OpBuilder.addGenericBinaryArithmeticOverloads(/*isComparison=*/false); + break; } } @@ -5270,7 +6116,7 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) { if (ExplicitTemplateArgs) continue; - + AddOverloadCandidate(FD, FoundDecl, Args, NumArgs, CandidateSet, false, PartialOverloading); } else @@ -5284,9 +6130,10 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, /// candidate is a better candidate than the second (C++ 13.3.3p1). bool isBetterOverloadCandidate(Sema &S, - const OverloadCandidate& Cand1, - const OverloadCandidate& Cand2, - SourceLocation Loc) { + const OverloadCandidate &Cand1, + const OverloadCandidate &Cand2, + SourceLocation Loc, + bool UserDefinedConversion) { // Define viable functions to be better candidates than non-viable // functions. if (!Cand2.Viable) @@ -5346,14 +6193,16 @@ isBetterOverloadCandidate(Sema &S, // according to the partial ordering rules described in 14.5.5.2, or, // if not that, if (Cand1.Function && Cand1.Function->getPrimaryTemplate() && - Cand2.Function && Cand2.Function->getPrimaryTemplate()) + Cand2.Function && Cand2.Function->getPrimaryTemplate()) { if (FunctionTemplateDecl *BetterTemplate = S.getMoreSpecializedTemplate(Cand1.Function->getPrimaryTemplate(), Cand2.Function->getPrimaryTemplate(), Loc, - isa<CXXConversionDecl>(Cand1.Function)? TPOC_Conversion - : TPOC_Call)) + isa<CXXConversionDecl>(Cand1.Function)? TPOC_Conversion + : TPOC_Call, + Cand1.ExplicitCallArguments)) return BetterTemplate == Cand1.Function->getPrimaryTemplate(); + } // -- the context is an initialization by user-defined conversion // (see 8.5, 13.3.1.5) and the standard conversion sequence @@ -5361,7 +6210,7 @@ isBetterOverloadCandidate(Sema &S, // the type of the entity being initialized) is a better // conversion sequence than the standard conversion sequence // from the return type of F2 to the destination type. - if (Cand1.Function && Cand2.Function && + if (UserDefinedConversion && Cand1.Function && Cand2.Function && isa<CXXConversionDecl>(Cand1.Function) && isa<CXXConversionDecl>(Cand2.Function)) { switch (CompareStandardConversionSequences(S, @@ -5398,12 +6247,14 @@ isBetterOverloadCandidate(Sema &S, /// \returns The result of overload resolution. OverloadingResult OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc, - iterator& Best) { + iterator &Best, + bool UserDefinedConversion) { // Find the best viable function. Best = end(); for (iterator Cand = begin(); Cand != end(); ++Cand) { if (Cand->Viable) - if (Best == end() || isBetterOverloadCandidate(S, *Cand, *Best, Loc)) + if (Best == end() || isBetterOverloadCandidate(S, *Cand, *Best, Loc, + UserDefinedConversion)) Best = Cand; } @@ -5416,7 +6267,8 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc, for (iterator Cand = begin(); Cand != end(); ++Cand) { if (Cand->Viable && Cand != Best && - !isBetterOverloadCandidate(S, *Best, *Cand, Loc)) { + !isBetterOverloadCandidate(S, *Best, *Cand, Loc, + UserDefinedConversion)) { Best = end(); return OR_Ambiguous; } @@ -5436,6 +6288,7 @@ OverloadCandidateSet::BestViableFunction(Sema &S, SourceLocation Loc, // placement new (5.3.4), as well as non-default initialization (8.5). if (Best->Function) S.MarkDeclarationReferenced(Loc, Best->Function); + return OR_Success; } @@ -5450,7 +6303,8 @@ enum OverloadCandidateKind { oc_constructor_template, oc_implicit_default_constructor, oc_implicit_copy_constructor, - oc_implicit_copy_assignment + oc_implicit_copy_assignment, + oc_implicit_inherited_constructor }; OverloadCandidateKind ClassifyOverloadCandidate(Sema &S, @@ -5468,6 +6322,9 @@ OverloadCandidateKind ClassifyOverloadCandidate(Sema &S, if (!Ctor->isImplicit()) return isTemplate ? oc_constructor_template : oc_constructor; + if (Ctor->getInheritedConstructor()) + return oc_implicit_inherited_constructor; + return Ctor->isCopyConstructor() ? oc_implicit_copy_constructor : oc_implicit_default_constructor; } @@ -5478,7 +6335,7 @@ OverloadCandidateKind ClassifyOverloadCandidate(Sema &S, if (!Meth->isImplicit()) return isTemplate ? oc_method_template : oc_method; - assert(Meth->isCopyAssignment() + assert(Meth->isCopyAssignmentOperator() && "implicit method is not copy assignment operator?"); return oc_implicit_copy_assignment; } @@ -5486,6 +6343,16 @@ OverloadCandidateKind ClassifyOverloadCandidate(Sema &S, return isTemplate ? oc_function_template : oc_function; } +void MaybeEmitInheritedConstructorNote(Sema &S, FunctionDecl *Fn) { + const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn); + if (!Ctor) return; + + Ctor = Ctor->getInheritedConstructor(); + if (!Ctor) return; + + S.Diag(Ctor->getLocation(), diag::note_ovl_candidate_inherited_constructor); +} + } // end anonymous namespace // Notes the location of an overload candidate. @@ -5494,6 +6361,28 @@ void Sema::NoteOverloadCandidate(FunctionDecl *Fn) { OverloadCandidateKind K = ClassifyOverloadCandidate(*this, Fn, FnDesc); Diag(Fn->getLocation(), diag::note_ovl_candidate) << (unsigned) K << FnDesc; + MaybeEmitInheritedConstructorNote(*this, Fn); +} + +//Notes the location of all overload candidates designated through +// OverloadedExpr +void Sema::NoteAllOverloadCandidates(Expr* OverloadedExpr) { + assert(OverloadedExpr->getType() == Context.OverloadTy); + + OverloadExpr::FindResult Ovl = OverloadExpr::find(OverloadedExpr); + OverloadExpr *OvlExpr = Ovl.Expression; + + for (UnresolvedSetIterator I = OvlExpr->decls_begin(), + IEnd = OvlExpr->decls_end(); + I != IEnd; ++I) { + if (FunctionTemplateDecl *FunTmpl = + dyn_cast<FunctionTemplateDecl>((*I)->getUnderlyingDecl()) ) { + NoteOverloadCandidate(FunTmpl->getTemplatedDecl()); + } else if (FunctionDecl *Fun + = dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl()) ) { + NoteOverloadCandidate(Fun); + } + } } /// Diagnoses an ambiguous conversion. The partial diagnostic is the @@ -5548,6 +6437,7 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) { << (unsigned) FnKind << FnDesc << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << ToTy << Name << I+1; + MaybeEmitInheritedConstructorNote(S, Fn); return; } @@ -5582,6 +6472,7 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) { << FromTy << FromQs.getAddressSpace() << ToQs.getAddressSpace() << (unsigned) isObjectArgument << I+1; + MaybeEmitInheritedConstructorNote(S, Fn); return; } @@ -5599,6 +6490,7 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) { << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy << (CVR - 1) << I+1; } + MaybeEmitInheritedConstructorNote(S, Fn); return; } @@ -5613,6 +6505,7 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) { << (unsigned) FnKind << FnDesc << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy << ToTy << (unsigned) isObjectArgument << I+1; + MaybeEmitInheritedConstructorNote(S, Fn); return; } @@ -5624,7 +6517,7 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) { FromPtrTy->getPointeeType()) && !FromPtrTy->getPointeeType()->isIncompleteType() && !ToPtrTy->getPointeeType()->isIncompleteType() && - S.IsDerivedFrom(ToPtrTy->getPointeeType(), + S.IsDerivedFrom(ToPtrTy->getPointeeType(), FromPtrTy->getPointeeType())) BaseToDerivedConversion = 1; } @@ -5645,22 +6538,24 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) { S.IsDerivedFrom(ToRefTy->getPointeeType(), FromTy)) BaseToDerivedConversion = 3; } - + if (BaseToDerivedConversion) { - S.Diag(Fn->getLocation(), + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_base_to_derived_conv) << (unsigned) FnKind << FnDesc << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << (BaseToDerivedConversion - 1) - << FromTy << ToTy << I+1; + << FromTy << ToTy << I+1; + MaybeEmitInheritedConstructorNote(S, Fn); return; } - + // TODO: specialize more based on the kind of mismatch S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_conv) << (unsigned) FnKind << FnDesc << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy << ToTy << (unsigned) isObjectArgument << I+1; + MaybeEmitInheritedConstructorNote(S, Fn); } void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand, @@ -5671,15 +6566,15 @@ void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand, const FunctionProtoType *FnTy = Fn->getType()->getAs<FunctionProtoType>(); unsigned MinParams = Fn->getMinRequiredArguments(); - + // at least / at most / exactly - // FIXME: variadic templates "at most" should account for parameter packs unsigned mode, modeCount; if (NumFormalArgs < MinParams) { assert((Cand->FailureKind == ovl_fail_too_few_arguments) || (Cand->FailureKind == ovl_fail_bad_deduction && Cand->DeductionFailure.Result == Sema::TDK_TooFewArguments)); - if (MinParams != FnTy->getNumArgs() || FnTy->isVariadic()) + if (MinParams != FnTy->getNumArgs() || + FnTy->isVariadic() || FnTy->isTemplateVariadic()) mode = 0; // "at least" else mode = 2; // "exactly" @@ -5699,8 +6594,9 @@ void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand, OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, Description); S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity) - << (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != 0) << mode + << (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != 0) << mode << modeCount << NumFormalArgs; + MaybeEmitInheritedConstructorNote(S, Fn); } /// Diagnose a failed template-argument deduction. @@ -5721,6 +6617,7 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, assert(ParamD && "no parameter found for incomplete deduction result"); S.Diag(Fn->getLocation(), diag::note_ovl_candidate_incomplete_deduction) << ParamD->getDeclName(); + MaybeEmitInheritedConstructorNote(S, Fn); return; } @@ -5732,9 +6629,9 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, // Param will have been canonicalized, but it should just be a // qualified version of ParamD, so move the qualifiers to that. - QualifierCollector Qs(S.Context); + QualifierCollector Qs; Qs.strip(Param); - QualType NonCanonParam = Qs.apply(TParam->getTypeForDecl()); + QualType NonCanonParam = Qs.apply(S.Context, TParam->getTypeForDecl()); assert(S.Context.hasSameType(Param, NonCanonParam)); // Arg has also been canonicalized, but there's nothing we can do @@ -5745,11 +6642,12 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, S.Diag(Fn->getLocation(), diag::note_ovl_candidate_underqualified) << ParamD->getDeclName() << Arg << NonCanonParam; + MaybeEmitInheritedConstructorNote(S, Fn); return; } case Sema::TDK_Inconsistent: { - assert(ParamD && "no parameter found for inconsistent deduction result"); + assert(ParamD && "no parameter found for inconsistent deduction result"); int which = 0; if (isa<TemplateTypeParmDecl>(ParamD)) which = 0; @@ -5758,18 +6656,19 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, else { which = 2; } - + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_inconsistent_deduction) - << which << ParamD->getDeclName() + << which << ParamD->getDeclName() << *Cand->DeductionFailure.getFirstArg() << *Cand->DeductionFailure.getSecondArg(); + MaybeEmitInheritedConstructorNote(S, Fn); return; } case Sema::TDK_InvalidExplicitArguments: - assert(ParamD && "no parameter found for invalid explicit arguments"); + assert(ParamD && "no parameter found for invalid explicit arguments"); if (ParamD->getDeclName()) - S.Diag(Fn->getLocation(), + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_explicit_arg_mismatch_named) << ParamD->getDeclName(); else { @@ -5781,12 +6680,13 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, index = NTTP->getIndex(); else index = cast<TemplateTemplateParmDecl>(ParamD)->getIndex(); - S.Diag(Fn->getLocation(), + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_explicit_arg_mismatch_unnamed) << (index + 1); } + MaybeEmitInheritedConstructorNote(S, Fn); return; - + case Sema::TDK_TooManyArguments: case Sema::TDK_TooFewArguments: DiagnoseArityMismatch(S, Cand, NumArgs); @@ -5794,6 +6694,7 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, case Sema::TDK_InstantiationDepth: S.Diag(Fn->getLocation(), diag::note_ovl_candidate_instantiation_depth); + MaybeEmitInheritedConstructorNote(S, Fn); return; case Sema::TDK_SubstitutionFailure: { @@ -5805,14 +6706,16 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, *Args); S.Diag(Fn->getLocation(), diag::note_ovl_candidate_substitution_failure) << ArgString; + MaybeEmitInheritedConstructorNote(S, Fn); return; } - + // TODO: diagnose these individually, then kill off // note_ovl_candidate_bad_deduction, which is uselessly vague. case Sema::TDK_NonDeducedMismatch: case Sema::TDK_FailedOverloadResolution: S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_deduction); + MaybeEmitInheritedConstructorNote(S, Fn); return; } } @@ -5841,6 +6744,7 @@ void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, S.Diag(Fn->getLocation(), diag::note_ovl_candidate_deleted) << FnKind << FnDesc << Fn->isDeleted(); + MaybeEmitInheritedConstructorNote(S, Fn); return; } @@ -5868,7 +6772,7 @@ void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, for (unsigned N = Cand->Conversions.size(); I != N; ++I) if (Cand->Conversions[I].isBad()) return DiagnoseBadConversion(S, Cand, I); - + // FIXME: this currently happens when we're called from SemaInit // when user-conversion overload fails. Figure out how to handle // those conditions and diagnose them well. @@ -5907,6 +6811,7 @@ void NoteSurrogateCandidate(Sema &S, OverloadCandidate *Cand) { S.Diag(Cand->Surrogate->getLocation(), diag::note_ovl_surrogate_cand) << FnType; + MaybeEmitInheritedConstructorNote(S, Cand->Surrogate); } void NoteBuiltinOperatorCandidate(Sema &S, @@ -6083,7 +6988,7 @@ void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, Cand->Conversions[ConvIdx] = TryCopyInitialization(S, Args[ConvIdx], Cand->BuiltinTypes.ParamTypes[ConvIdx], - SuppressUserConversions, + SuppressUserConversions, /*InOverloadResolution*/ true); return; } @@ -6094,7 +6999,7 @@ void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, if (ArgIdx < NumArgsInProto) Cand->Conversions[ConvIdx] = TryCopyInitialization(S, Args[ArgIdx], Proto->getArgType(ArgIdx), - SuppressUserConversions, + SuppressUserConversions, /*InOverloadResolution=*/true); else Cand->Conversions[ConvIdx].setEllipsis(); @@ -6129,7 +7034,7 @@ void OverloadCandidateSet::NoteCandidates(Sema &S, std::sort(Cands.begin(), Cands.end(), CompareOverloadCandidatesForDisplay(S)); - + bool ReportedAmbiguousConversions = false; llvm::SmallVectorImpl<OverloadCandidate*>::iterator I, E; @@ -6180,186 +7085,207 @@ static bool CheckUnresolvedAccess(Sema &S, OverloadExpr *E, DeclAccessPair D) { return S.CheckUnresolvedMemberAccess(cast<UnresolvedMemberExpr>(E), D); } -/// ResolveAddressOfOverloadedFunction - Try to resolve the address of -/// an overloaded function (C++ [over.over]), where @p From is an -/// expression with overloaded function type and @p ToType is the type -/// we're trying to resolve to. For example: -/// -/// @code -/// int f(double); -/// int f(int); -/// -/// int (*pfd)(double) = f; // selects f(double) -/// @endcode -/// -/// This routine returns the resulting FunctionDecl if it could be -/// resolved, and NULL otherwise. When @p Complain is true, this -/// routine will emit diagnostics if there is an error. -FunctionDecl * -Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, - bool Complain, - DeclAccessPair &FoundResult) { - QualType FunctionType = ToType; - bool IsMember = false; - if (const PointerType *ToTypePtr = ToType->getAs<PointerType>()) - FunctionType = ToTypePtr->getPointeeType(); - else if (const ReferenceType *ToTypeRef = ToType->getAs<ReferenceType>()) - FunctionType = ToTypeRef->getPointeeType(); - else if (const MemberPointerType *MemTypePtr = - ToType->getAs<MemberPointerType>()) { - FunctionType = MemTypePtr->getPointeeType(); - IsMember = true; - } - // C++ [over.over]p1: - // [...] [Note: any redundant set of parentheses surrounding the - // overloaded function name is ignored (5.1). ] - // C++ [over.over]p1: - // [...] The overloaded function name can be preceded by the & - // operator. - // However, remember whether the expression has member-pointer form: - // C++ [expr.unary.op]p4: - // A pointer to member is only formed when an explicit & is used - // and its operand is a qualified-id not enclosed in - // parentheses. - OverloadExpr::FindResult Ovl = OverloadExpr::find(From); - OverloadExpr *OvlExpr = Ovl.Expression; - - // We expect a pointer or reference to function, or a function pointer. - FunctionType = Context.getCanonicalType(FunctionType).getUnqualifiedType(); - if (!FunctionType->isFunctionType()) { - if (Complain) - Diag(From->getLocStart(), diag::err_addr_ovl_not_func_ptrref) - << OvlExpr->getName() << ToType; - - return 0; - } - // If the overload expression doesn't have the form of a pointer to - // member, don't try to convert it to a pointer-to-member type. - if (IsMember && !Ovl.HasFormOfMemberPointer) { - if (!Complain) return 0; - // TODO: Should we condition this on whether any functions might - // have matched, or is it more appropriate to do that in callers? - // TODO: a fixit wouldn't hurt. - Diag(OvlExpr->getNameLoc(), diag::err_addr_ovl_no_qualifier) - << ToType << OvlExpr->getSourceRange(); - return 0; - } +// [PossiblyAFunctionType] --> [Return] +// NonFunctionType --> NonFunctionType +// R (A) --> R(A) +// R (*)(A) --> R (A) +// R (&)(A) --> R (A) +// R (S::*)(A) --> R (A) +QualType Sema::ExtractUnqualifiedFunctionType(QualType PossiblyAFunctionType) { + QualType Ret = PossiblyAFunctionType; + if (const PointerType *ToTypePtr = + PossiblyAFunctionType->getAs<PointerType>()) + Ret = ToTypePtr->getPointeeType(); + else if (const ReferenceType *ToTypeRef = + PossiblyAFunctionType->getAs<ReferenceType>()) + Ret = ToTypeRef->getPointeeType(); + else if (const MemberPointerType *MemTypePtr = + PossiblyAFunctionType->getAs<MemberPointerType>()) + Ret = MemTypePtr->getPointeeType(); + Ret = + Context.getCanonicalType(Ret).getUnqualifiedType(); + return Ret; +} - TemplateArgumentListInfo ETABuffer, *ExplicitTemplateArgs = 0; - if (OvlExpr->hasExplicitTemplateArgs()) { - OvlExpr->getExplicitTemplateArgs().copyInto(ETABuffer); - ExplicitTemplateArgs = &ETABuffer; - } +// A helper class to help with address of function resolution +// - allows us to avoid passing around all those ugly parameters +class AddressOfFunctionResolver +{ + Sema& S; + Expr* SourceExpr; + const QualType& TargetType; + QualType TargetFunctionType; // Extracted function type from target type + + bool Complain; + //DeclAccessPair& ResultFunctionAccessPair; + ASTContext& Context; - assert(From->getType() == Context.OverloadTy); + bool TargetTypeIsNonStaticMemberFunction; + bool FoundNonTemplateFunction; - // Look through all of the overloaded functions, searching for one - // whose type matches exactly. + OverloadExpr::FindResult OvlExprInfo; + OverloadExpr *OvlExpr; + TemplateArgumentListInfo OvlExplicitTemplateArgs; llvm::SmallVector<std::pair<DeclAccessPair, FunctionDecl*>, 4> Matches; - llvm::SmallVector<FunctionDecl *, 4> NonMatches; - - bool FoundNonTemplateFunction = false; - for (UnresolvedSetIterator I = OvlExpr->decls_begin(), - E = OvlExpr->decls_end(); I != E; ++I) { - // Look through any using declarations to find the underlying function. - NamedDecl *Fn = (*I)->getUnderlyingDecl(); - - // C++ [over.over]p3: - // Non-member functions and static member functions match - // targets of type "pointer-to-function" or "reference-to-function." - // Nonstatic member functions match targets of - // type "pointer-to-member-function." - // Note that according to DR 247, the containing class does not matter. - - if (FunctionTemplateDecl *FunctionTemplate - = dyn_cast<FunctionTemplateDecl>(Fn)) { - if (CXXMethodDecl *Method - = dyn_cast<CXXMethodDecl>(FunctionTemplate->getTemplatedDecl())) { - // Skip non-static function templates when converting to pointer, and - // static when converting to member pointer. - if (Method->isStatic() == IsMember) - continue; - } else if (IsMember) - continue; - // C++ [over.over]p2: - // If the name is a function template, template argument deduction is - // done (14.8.2.2), and if the argument deduction succeeds, the - // resulting template argument list is used to generate a single - // function template specialization, which is added to the set of - // overloaded functions considered. - // FIXME: We don't really want to build the specialization here, do we? - FunctionDecl *Specialization = 0; - TemplateDeductionInfo Info(Context, OvlExpr->getNameLoc()); - if (TemplateDeductionResult Result - = DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs, - FunctionType, Specialization, Info)) { - // FIXME: make a note of the failed deduction for diagnostics. - (void)Result; - } else { - // FIXME: If the match isn't exact, shouldn't we just drop this as - // a candidate? Find a testcase before changing the code. - assert(FunctionType - == Context.getCanonicalType(Specialization->getType())); - Matches.push_back(std::make_pair(I.getPair(), - cast<FunctionDecl>(Specialization->getCanonicalDecl()))); +public: + AddressOfFunctionResolver(Sema &S, Expr* SourceExpr, + const QualType& TargetType, bool Complain) + : S(S), SourceExpr(SourceExpr), TargetType(TargetType), + Complain(Complain), Context(S.getASTContext()), + TargetTypeIsNonStaticMemberFunction( + !!TargetType->getAs<MemberPointerType>()), + FoundNonTemplateFunction(false), + OvlExprInfo(OverloadExpr::find(SourceExpr)), + OvlExpr(OvlExprInfo.Expression) + { + ExtractUnqualifiedFunctionTypeFromTargetType(); + + if (!TargetFunctionType->isFunctionType()) { + if (OvlExpr->hasExplicitTemplateArgs()) { + DeclAccessPair dap; + if( FunctionDecl* Fn = S.ResolveSingleFunctionTemplateSpecialization( + OvlExpr, false, &dap) ) { + Matches.push_back(std::make_pair(dap,Fn)); + } + } + return; + } + + if (OvlExpr->hasExplicitTemplateArgs()) + OvlExpr->getExplicitTemplateArgs().copyInto(OvlExplicitTemplateArgs); + + if (FindAllFunctionsThatMatchTargetTypeExactly()) { + // C++ [over.over]p4: + // If more than one function is selected, [...] + if (Matches.size() > 1) { + if (FoundNonTemplateFunction) + EliminateAllTemplateMatches(); + else + EliminateAllExceptMostSpecializedTemplate(); } - - continue; } + } + +private: + bool isTargetTypeAFunction() const { + return TargetFunctionType->isFunctionType(); + } + + // [ToType] [Return] + // R (*)(A) --> R (A), IsNonStaticMemberFunction = false + // R (&)(A) --> R (A), IsNonStaticMemberFunction = false + // R (S::*)(A) --> R (A), IsNonStaticMemberFunction = true + void inline ExtractUnqualifiedFunctionTypeFromTargetType() { + TargetFunctionType = S.ExtractUnqualifiedFunctionType(TargetType); + } + + // return true if any matching specializations were found + bool AddMatchingTemplateFunction(FunctionTemplateDecl* FunctionTemplate, + const DeclAccessPair& CurAccessFunPair) { + if (CXXMethodDecl *Method + = dyn_cast<CXXMethodDecl>(FunctionTemplate->getTemplatedDecl())) { + // Skip non-static function templates when converting to pointer, and + // static when converting to member pointer. + if (Method->isStatic() == TargetTypeIsNonStaticMemberFunction) + return false; + } + else if (TargetTypeIsNonStaticMemberFunction) + return false; + + // C++ [over.over]p2: + // If the name is a function template, template argument deduction is + // done (14.8.2.2), and if the argument deduction succeeds, the + // resulting template argument list is used to generate a single + // function template specialization, which is added to the set of + // overloaded functions considered. + FunctionDecl *Specialization = 0; + TemplateDeductionInfo Info(Context, OvlExpr->getNameLoc()); + if (Sema::TemplateDeductionResult Result + = S.DeduceTemplateArguments(FunctionTemplate, + &OvlExplicitTemplateArgs, + TargetFunctionType, Specialization, + Info)) { + // FIXME: make a note of the failed deduction for diagnostics. + (void)Result; + return false; + } + + // Template argument deduction ensures that we have an exact match. + // This function template specicalization works. + Specialization = cast<FunctionDecl>(Specialization->getCanonicalDecl()); + assert(TargetFunctionType + == Context.getCanonicalType(Specialization->getType())); + Matches.push_back(std::make_pair(CurAccessFunPair, Specialization)); + return true; + } + + bool AddMatchingNonTemplateFunction(NamedDecl* Fn, + const DeclAccessPair& CurAccessFunPair) { if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Fn)) { // Skip non-static functions when converting to pointer, and static // when converting to member pointer. - if (Method->isStatic() == IsMember) - continue; - - // If we have explicit template arguments, skip non-templates. - if (OvlExpr->hasExplicitTemplateArgs()) - continue; - } else if (IsMember) - continue; + if (Method->isStatic() == TargetTypeIsNonStaticMemberFunction) + return false; + } + else if (TargetTypeIsNonStaticMemberFunction) + return false; if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(Fn)) { QualType ResultTy; - if (Context.hasSameUnqualifiedType(FunctionType, FunDecl->getType()) || - IsNoReturnConversion(Context, FunDecl->getType(), FunctionType, + if (Context.hasSameUnqualifiedType(TargetFunctionType, + FunDecl->getType()) || + IsNoReturnConversion(Context, FunDecl->getType(), TargetFunctionType, ResultTy)) { - Matches.push_back(std::make_pair(I.getPair(), - cast<FunctionDecl>(FunDecl->getCanonicalDecl()))); + Matches.push_back(std::make_pair(CurAccessFunPair, + cast<FunctionDecl>(FunDecl->getCanonicalDecl()))); FoundNonTemplateFunction = true; + return true; } } + + return false; } + + bool FindAllFunctionsThatMatchTargetTypeExactly() { + bool Ret = false; + + // If the overload expression doesn't have the form of a pointer to + // member, don't try to convert it to a pointer-to-member type. + if (IsInvalidFormOfPointerToMemberFunction()) + return false; - // If there were 0 or 1 matches, we're done. - if (Matches.empty()) { - if (Complain) { - Diag(From->getLocStart(), diag::err_addr_ovl_no_viable) - << OvlExpr->getName() << FunctionType; - for (UnresolvedSetIterator I = OvlExpr->decls_begin(), - E = OvlExpr->decls_end(); - I != E; ++I) - if (FunctionDecl *F = dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl())) - NoteOverloadCandidate(F); + for (UnresolvedSetIterator I = OvlExpr->decls_begin(), + E = OvlExpr->decls_end(); + I != E; ++I) { + // Look through any using declarations to find the underlying function. + NamedDecl *Fn = (*I)->getUnderlyingDecl(); + + // C++ [over.over]p3: + // Non-member functions and static member functions match + // targets of type "pointer-to-function" or "reference-to-function." + // Nonstatic member functions match targets of + // type "pointer-to-member-function." + // Note that according to DR 247, the containing class does not matter. + if (FunctionTemplateDecl *FunctionTemplate + = dyn_cast<FunctionTemplateDecl>(Fn)) { + if (AddMatchingTemplateFunction(FunctionTemplate, I.getPair())) + Ret = true; + } + // If we have explicit template arguments supplied, skip non-templates. + else if (!OvlExpr->hasExplicitTemplateArgs() && + AddMatchingNonTemplateFunction(Fn, I.getPair())) + Ret = true; } - - return 0; - } else if (Matches.size() == 1) { - FunctionDecl *Result = Matches[0].second; - FoundResult = Matches[0].first; - MarkDeclarationReferenced(From->getLocStart(), Result); - if (Complain) - CheckAddressOfMemberAccess(OvlExpr, Matches[0].first); - return Result; + assert(Ret || Matches.empty()); + return Ret; } - // C++ [over.over]p4: - // If more than one function is selected, [...] - if (!FoundNonTemplateFunction) { + void EliminateAllExceptMostSpecializedTemplate() { // [...] and any given function template specialization F1 is // eliminated if the set contains a second function template // specialization whose function template is more specialized @@ -6374,84 +7300,159 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, UnresolvedSet<4> MatchesCopy; // TODO: avoid! for (unsigned I = 0, E = Matches.size(); I != E; ++I) MatchesCopy.addDecl(Matches[I].second, Matches[I].first.getAccess()); - + UnresolvedSetIterator Result = - getMostSpecialized(MatchesCopy.begin(), MatchesCopy.end(), - TPOC_Other, From->getLocStart(), - PDiag(), - PDiag(diag::err_addr_ovl_ambiguous) - << Matches[0].second->getDeclName(), - PDiag(diag::note_ovl_candidate) - << (unsigned) oc_function_template); - assert(Result != MatchesCopy.end() && "no most-specialized template"); - MarkDeclarationReferenced(From->getLocStart(), *Result); - FoundResult = Matches[Result - MatchesCopy.begin()].first; - if (Complain) { - CheckUnresolvedAccess(*this, OvlExpr, FoundResult); - DiagnoseUseOfDecl(FoundResult, OvlExpr->getNameLoc()); - } - return cast<FunctionDecl>(*Result); - } - - // [...] any function template specializations in the set are - // eliminated if the set also contains a non-template function, [...] - for (unsigned I = 0, N = Matches.size(); I != N; ) { - if (Matches[I].second->getPrimaryTemplate() == 0) - ++I; - else { - Matches[I] = Matches[--N]; - Matches.set_size(N); + S.getMostSpecialized(MatchesCopy.begin(), MatchesCopy.end(), + TPOC_Other, 0, SourceExpr->getLocStart(), + S.PDiag(), + S.PDiag(diag::err_addr_ovl_ambiguous) + << Matches[0].second->getDeclName(), + S.PDiag(diag::note_ovl_candidate) + << (unsigned) oc_function_template, + Complain); + + if (Result != MatchesCopy.end()) { + // Make it the first and only element + Matches[0].first = Matches[Result - MatchesCopy.begin()].first; + Matches[0].second = cast<FunctionDecl>(*Result); + Matches.resize(1); + } + } + + void EliminateAllTemplateMatches() { + // [...] any function template specializations in the set are + // eliminated if the set also contains a non-template function, [...] + for (unsigned I = 0, N = Matches.size(); I != N; ) { + if (Matches[I].second->getPrimaryTemplate() == 0) + ++I; + else { + Matches[I] = Matches[--N]; + Matches.set_size(N); + } } } + +public: + void ComplainNoMatchesFound() const { + assert(Matches.empty()); + S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_no_viable) + << OvlExpr->getName() << TargetFunctionType + << OvlExpr->getSourceRange(); + S.NoteAllOverloadCandidates(OvlExpr); + } - // [...] After such eliminations, if any, there shall remain exactly one - // selected function. - if (Matches.size() == 1) { - MarkDeclarationReferenced(From->getLocStart(), Matches[0].second); - FoundResult = Matches[0].first; - if (Complain) { - CheckUnresolvedAccess(*this, OvlExpr, Matches[0].first); - DiagnoseUseOfDecl(Matches[0].first, OvlExpr->getNameLoc()); - } - return cast<FunctionDecl>(Matches[0].second); - } - - // FIXME: We should probably return the same thing that BestViableFunction - // returns (even if we issue the diagnostics here). - Diag(From->getLocStart(), diag::err_addr_ovl_ambiguous) - << Matches[0].second->getDeclName(); - for (unsigned I = 0, E = Matches.size(); I != E; ++I) - NoteOverloadCandidate(Matches[I].second); - return 0; + bool IsInvalidFormOfPointerToMemberFunction() const { + return TargetTypeIsNonStaticMemberFunction && + !OvlExprInfo.HasFormOfMemberPointer; + } + + void ComplainIsInvalidFormOfPointerToMemberFunction() const { + // TODO: Should we condition this on whether any functions might + // have matched, or is it more appropriate to do that in callers? + // TODO: a fixit wouldn't hurt. + S.Diag(OvlExpr->getNameLoc(), diag::err_addr_ovl_no_qualifier) + << TargetType << OvlExpr->getSourceRange(); + } + + void ComplainOfInvalidConversion() const { + S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_not_func_ptrref) + << OvlExpr->getName() << TargetType; + } + + void ComplainMultipleMatchesFound() const { + assert(Matches.size() > 1); + S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_ambiguous) + << OvlExpr->getName() + << OvlExpr->getSourceRange(); + S.NoteAllOverloadCandidates(OvlExpr); + } + + int getNumMatches() const { return Matches.size(); } + + FunctionDecl* getMatchingFunctionDecl() const { + if (Matches.size() != 1) return 0; + return Matches[0].second; + } + + const DeclAccessPair* getMatchingFunctionAccessPair() const { + if (Matches.size() != 1) return 0; + return &Matches[0].first; + } +}; + +/// ResolveAddressOfOverloadedFunction - Try to resolve the address of +/// an overloaded function (C++ [over.over]), where @p From is an +/// expression with overloaded function type and @p ToType is the type +/// we're trying to resolve to. For example: +/// +/// @code +/// int f(double); +/// int f(int); +/// +/// int (*pfd)(double) = f; // selects f(double) +/// @endcode +/// +/// This routine returns the resulting FunctionDecl if it could be +/// resolved, and NULL otherwise. When @p Complain is true, this +/// routine will emit diagnostics if there is an error. +FunctionDecl * +Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, QualType TargetType, + bool Complain, + DeclAccessPair &FoundResult) { + + assert(AddressOfExpr->getType() == Context.OverloadTy); + + AddressOfFunctionResolver Resolver(*this, AddressOfExpr, TargetType, Complain); + int NumMatches = Resolver.getNumMatches(); + FunctionDecl* Fn = 0; + if ( NumMatches == 0 && Complain) { + if (Resolver.IsInvalidFormOfPointerToMemberFunction()) + Resolver.ComplainIsInvalidFormOfPointerToMemberFunction(); + else + Resolver.ComplainNoMatchesFound(); + } + else if (NumMatches > 1 && Complain) + Resolver.ComplainMultipleMatchesFound(); + else if (NumMatches == 1) { + Fn = Resolver.getMatchingFunctionDecl(); + assert(Fn); + FoundResult = *Resolver.getMatchingFunctionAccessPair(); + MarkDeclarationReferenced(AddressOfExpr->getLocStart(), Fn); + if (Complain) + CheckAddressOfMemberAccess(AddressOfExpr, FoundResult); + } + + return Fn; } -/// \brief Given an expression that refers to an overloaded function, try to +/// \brief Given an expression that refers to an overloaded function, try to /// resolve that overloaded function expression down to a single function. /// /// This routine can only resolve template-ids that refer to a single function /// template, where that template-id refers to a single template whose template -/// arguments are either provided by the template-id or have defaults, +/// arguments are either provided by the template-id or have defaults, /// as described in C++0x [temp.arg.explicit]p3. -FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From) { +FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From, + bool Complain, + DeclAccessPair* FoundResult) { // C++ [over.over]p1: // [...] [Note: any redundant set of parentheses surrounding the // overloaded function name is ignored (5.1). ] // C++ [over.over]p1: // [...] The overloaded function name can be preceded by the & // operator. - if (From->getType() != Context.OverloadTy) return 0; OverloadExpr *OvlExpr = OverloadExpr::find(From).Expression; - + // If we didn't actually find any template-ids, we're done. if (!OvlExpr->hasExplicitTemplateArgs()) return 0; TemplateArgumentListInfo ExplicitTemplateArgs; OvlExpr->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs); - + // Look through all of the overloaded functions, searching for one // whose type matches exactly. FunctionDecl *Matched = 0; @@ -6459,13 +7460,13 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From) { E = OvlExpr->decls_end(); I != E; ++I) { // C++0x [temp.arg.explicit]p3: // [...] In contexts where deduction is done and fails, or in contexts - // where deduction is not done, if a template argument list is - // specified and it, along with any default template arguments, - // identifies a single function template specialization, then the + // where deduction is not done, if a template argument list is + // specified and it, along with any default template arguments, + // identifies a single function template specialization, then the // template-id is an lvalue for the function template specialization. FunctionTemplateDecl *FunctionTemplate = cast<FunctionTemplateDecl>((*I)->getUnderlyingDecl()); - + // C++ [over.over]p2: // If the name is a function template, template argument deduction is // done (14.8.2.2), and if the argument deduction succeeds, the @@ -6480,18 +7481,28 @@ FunctionDecl *Sema::ResolveSingleFunctionTemplateSpecialization(Expr *From) { // FIXME: make a note of the failed deduction for diagnostics. (void)Result; continue; - } - + } + // Multiple matches; we can't resolve to a single declaration. - if (Matched) + if (Matched) { + if (FoundResult) + *FoundResult = DeclAccessPair(); + + if (Complain) { + Diag(From->getLocStart(), diag::err_addr_ovl_ambiguous) + << OvlExpr->getName(); + NoteAllOverloadCandidates(OvlExpr); + } return 0; - - Matched = Specialization; + } + + if ((Matched = Specialization) && FoundResult) + *FoundResult = I.getPair(); } return Matched; } - + /// \brief Add a single candidate to the overload set. static void AddOverloadedCallCandidate(Sema &S, DeclAccessPair FoundDecl, @@ -6522,7 +7533,7 @@ static void AddOverloadedCallCandidate(Sema &S, // do nothing? } - + /// \brief Add the overload candidates named by callee and/or found by argument /// dependent lookup to the given overload set. void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, @@ -6570,7 +7581,7 @@ void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, for (UnresolvedLookupExpr::decls_iterator I = ULE->decls_begin(), E = ULE->decls_end(); I != E; ++I) AddOverloadedCallCandidate(*this, I.getPair(), ExplicitTemplateArgs, - Args, NumArgs, CandidateSet, + Args, NumArgs, CandidateSet, PartialOverloading); if (ULE->requiresADL()) @@ -6578,7 +7589,7 @@ void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, Args, NumArgs, ExplicitTemplateArgs, CandidateSet, - PartialOverloading); + PartialOverloading); } /// Attempts to recover from a call where no functions were found. @@ -6589,7 +7600,6 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, - SourceLocation *CommaLocs, SourceLocation RParenLoc) { CXXScopeSpec SS; @@ -6616,7 +7626,8 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, // casts and such from the call, we don't really care. ExprResult NewFn = ExprError(); if ((*R.begin())->isCXXClassMember()) - NewFn = SemaRef.BuildPossibleImplicitMemberExpr(SS, R, ExplicitTemplateArgs); + NewFn = SemaRef.BuildPossibleImplicitMemberExpr(SS, R, + ExplicitTemplateArgs); else if (ExplicitTemplateArgs) NewFn = SemaRef.BuildTemplateIdExpr(SS, R, false, *ExplicitTemplateArgs); else @@ -6629,8 +7640,7 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, // an expression with non-empty lookup results, which should never // end up here. return SemaRef.ActOnCallExpr(/*Scope*/ 0, NewFn.take(), LParenLoc, - MultiExprArg(Args, NumArgs), - CommaLocs, RParenLoc); + MultiExprArg(Args, NumArgs), RParenLoc); } /// ResolveOverloadedCallFn - Given the call expression that calls Fn @@ -6644,8 +7654,8 @@ ExprResult Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, - SourceLocation *CommaLocs, - SourceLocation RParenLoc) { + SourceLocation RParenLoc, + Expr *ExecConfig) { #ifndef NDEBUG if (ULE->requiresADL()) { // To do ADL, we must have found an unqualified name. @@ -6658,7 +7668,7 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, (F = dyn_cast<FunctionDecl>(*ULE->decls_begin())) && F->getBuiltinID() && F->isImplicit()) assert(0 && "performing ADL for builtin"); - + // We don't perform ADL in C. assert(getLangOptions().CPlusPlus && "ADL enabled in C"); } @@ -6675,16 +7685,18 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE, // bailout out if it fails. if (CandidateSet.empty()) return BuildRecoveryCallExpr(*this, S, Fn, ULE, LParenLoc, Args, NumArgs, - CommaLocs, RParenLoc); + RParenLoc); OverloadCandidateSet::iterator Best; switch (CandidateSet.BestViableFunction(*this, Fn->getLocStart(), Best)) { case OR_Success: { FunctionDecl *FDecl = Best->Function; CheckUnresolvedLookupAccess(ULE, Best->FoundDecl); - DiagnoseUseOfDecl(Best->FoundDecl, ULE->getNameLoc()); + DiagnoseUseOfDecl(FDecl? FDecl : Best->FoundDecl.getDecl(), + ULE->getNameLoc()); Fn = FixOverloadedFunctionReference(Fn, Best->FoundDecl, FDecl); - return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, RParenLoc); + return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, RParenLoc, + ExecConfig); } case OR_No_Viable_Function: @@ -6746,6 +7758,9 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, // TODO: provide better source location info. DeclarationNameInfo OpNameInfo(OpName, OpLoc); + if (Input->getObjectKind() == OK_ObjCProperty) + ConvertPropertyForRValue(Input); + Expr *Args[2] = { Input, 0 }; unsigned NumArgs = 1; @@ -6762,19 +7777,21 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, if (Input->isTypeDependent()) { if (Fns.empty()) return Owned(new (Context) UnaryOperator(Input, - Opc, + Opc, Context.DependentTy, + VK_RValue, OK_Ordinary, OpLoc)); - + CXXRecordDecl *NamingClass = 0; // because lookup ignores member operators UnresolvedLookupExpr *Fn - = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, NamingClass, + = UnresolvedLookupExpr::Create(Context, NamingClass, 0, SourceRange(), OpNameInfo, /*ADL*/ true, IsOverloaded(Fns), Fns.begin(), Fns.end()); return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn, &Args[0], NumArgs, Context.DependentTy, + VK_RValue, OpLoc)); } @@ -6818,8 +7835,9 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, // Convert the arguments. ExprResult InputInit = PerformCopyInitialization(InitializedEntity::InitializeParameter( + Context, FnDecl->getParamDecl(0)), - SourceLocation(), + SourceLocation(), Input); if (InputInit.isInvalid()) return ExprError(); @@ -6828,20 +7846,20 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, DiagnoseUseOfDecl(Best->FoundDecl, OpLoc); - // Determine the result type - QualType ResultTy = FnDecl->getCallResultType(); + // Determine the result type. + QualType ResultTy = FnDecl->getResultType(); + ExprValueKind VK = Expr::getValueKindForType(ResultTy); + ResultTy = ResultTy.getNonLValueExprType(Context); // Build the actual expression node. - Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(), - SourceLocation()); - UsualUnaryConversions(FnExpr); + Expr *FnExpr = CreateFunctionRefExpr(*this, FnDecl); Args[0] = Input; CallExpr *TheCall = new (Context) CXXOperatorCallExpr(Context, Op, FnExpr, - Args, NumArgs, ResultTy, OpLoc); + Args, NumArgs, ResultTy, VK, OpLoc); - if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall, + if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall, FnDecl)) return ExprError(); @@ -6864,8 +7882,9 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, break; case OR_Ambiguous: - Diag(OpLoc, diag::err_ovl_ambiguous_oper) + Diag(OpLoc, diag::err_ovl_ambiguous_oper_unary) << UnaryOperator::getOpcodeStr(Opc) + << Input->getType() << Input->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, NumArgs, @@ -6920,14 +7939,18 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // expression. if (Args[0]->isTypeDependent() || Args[1]->isTypeDependent()) { if (Fns.empty()) { - // If there are no functions to store, just build a dependent + // If there are no functions to store, just build a dependent // BinaryOperator or CompoundAssignment. if (Opc <= BO_Assign || Opc > BO_OrAssign) return Owned(new (Context) BinaryOperator(Args[0], Args[1], Opc, - Context.DependentTy, OpLoc)); - + Context.DependentTy, + VK_RValue, OK_Ordinary, + OpLoc)); + return Owned(new (Context) CompoundAssignOperator(Args[0], Args[1], Opc, Context.DependentTy, + VK_LValue, + OK_Ordinary, Context.DependentTy, Context.DependentTy, OpLoc)); @@ -6938,20 +7961,48 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // TODO: provide better source location info in DNLoc component. DeclarationNameInfo OpNameInfo(OpName, OpLoc); UnresolvedLookupExpr *Fn - = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, NamingClass, - 0, SourceRange(), OpNameInfo, - /*ADL*/ true, IsOverloaded(Fns), + = UnresolvedLookupExpr::Create(Context, NamingClass, 0, SourceRange(), + OpNameInfo, /*ADL*/ true, IsOverloaded(Fns), Fns.begin(), Fns.end()); return Owned(new (Context) CXXOperatorCallExpr(Context, Op, Fn, Args, 2, Context.DependentTy, + VK_RValue, OpLoc)); } - // If this is the .* operator, which is not overloadable, just - // create a built-in binary operator. - if (Opc == BO_PtrMemD) - return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]); + // Always do property rvalue conversions on the RHS. + if (Args[1]->getObjectKind() == OK_ObjCProperty) + ConvertPropertyForRValue(Args[1]); + + // The LHS is more complicated. + if (Args[0]->getObjectKind() == OK_ObjCProperty) { + + // There's a tension for assignment operators between primitive + // property assignment and the overloaded operators. + if (BinaryOperator::isAssignmentOp(Opc)) { + const ObjCPropertyRefExpr *PRE = LHS->getObjCProperty(); + + // Is the property "logically" settable? + bool Settable = (PRE->isExplicitProperty() || + PRE->getImplicitPropertySetter()); + + // To avoid gratuitously inventing semantics, use the primitive + // unless it isn't. Thoughts in case we ever really care: + // - If the property isn't logically settable, we have to + // load and hope. + // - If the property is settable and this is simple assignment, + // we really should use the primitive. + // - If the property is settable, then we could try overloading + // on a generic lvalue of the appropriate type; if it works + // out to a builtin candidate, we would do that same operation + // on the property, and otherwise just error. + if (Settable) + return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]); + } + + ConvertPropertyForRValue(Args[0]); + } // If this is the assignment operator, we only perform overload resolution // if the left-hand side is a class or enumeration type. This is actually @@ -6962,6 +8013,11 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, if (Opc == BO_Assign && !Args[0]->getType()->isOverloadableType()) return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]); + // If this is the .* operator, which is not overloadable, just + // create a built-in binary operator. + if (Opc == BO_PtrMemD) + return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]); + // Build an empty overload set. OverloadCandidateSet CandidateSet(OpLoc); @@ -6996,37 +8052,33 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // Best->Access is only meaningful for class members. CheckMemberOperatorAccess(OpLoc, Args[0], Args[1], Best->FoundDecl); - ExprResult Arg1 - = PerformCopyInitialization( - InitializedEntity::InitializeParameter( - FnDecl->getParamDecl(0)), - SourceLocation(), - Owned(Args[1])); + ExprResult Arg1 = + PerformCopyInitialization( + InitializedEntity::InitializeParameter(Context, + FnDecl->getParamDecl(0)), + SourceLocation(), Owned(Args[1])); if (Arg1.isInvalid()) return ExprError(); - if (PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0, + if (PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0, Best->FoundDecl, Method)) return ExprError(); Args[1] = RHS = Arg1.takeAs<Expr>(); } else { // Convert the arguments. - ExprResult Arg0 - = PerformCopyInitialization( - InitializedEntity::InitializeParameter( - FnDecl->getParamDecl(0)), - SourceLocation(), - Owned(Args[0])); + ExprResult Arg0 = PerformCopyInitialization( + InitializedEntity::InitializeParameter(Context, + FnDecl->getParamDecl(0)), + SourceLocation(), Owned(Args[0])); if (Arg0.isInvalid()) return ExprError(); - ExprResult Arg1 - = PerformCopyInitialization( - InitializedEntity::InitializeParameter( - FnDecl->getParamDecl(1)), - SourceLocation(), - Owned(Args[1])); + ExprResult Arg1 = + PerformCopyInitialization( + InitializedEntity::InitializeParameter(Context, + FnDecl->getParamDecl(1)), + SourceLocation(), Owned(Args[1])); if (Arg1.isInvalid()) return ExprError(); Args[0] = LHS = Arg0.takeAs<Expr>(); @@ -7035,21 +8087,19 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, DiagnoseUseOfDecl(Best->FoundDecl, OpLoc); - // Determine the result type - QualType ResultTy - = FnDecl->getType()->getAs<FunctionType>() - ->getCallResultType(Context); + // Determine the result type. + QualType ResultTy = FnDecl->getResultType(); + ExprValueKind VK = Expr::getValueKindForType(ResultTy); + ResultTy = ResultTy.getNonLValueExprType(Context); // Build the actual expression node. - Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(), - OpLoc); - UsualUnaryConversions(FnExpr); + Expr *FnExpr = CreateFunctionRefExpr(*this, FnDecl, OpLoc); CXXOperatorCallExpr *TheCall = new (Context) CXXOperatorCallExpr(Context, Op, FnExpr, - Args, 2, ResultTy, OpLoc); - - if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall, + Args, 2, ResultTy, VK, OpLoc); + + if (CheckCallReturnType(FnDecl->getResultType(), OpLoc, TheCall, FnDecl)) return ExprError(); @@ -7076,11 +8126,11 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, if (Opc == BO_Comma) break; - // For class as left operand for assignment or compound assigment operator - // do not fall through to handling in built-in, but report that no overloaded - // assignment operator found + // For class as left operand for assignment or compound assigment + // operator do not fall through to handling in built-in, but report that + // no overloaded assignment operator found ExprResult Result = ExprError(); - if (Args[0]->getType()->isRecordType() && + if (Args[0]->getType()->isRecordType() && Opc >= BO_Assign && Opc <= BO_OrAssign) { Diag(OpLoc, diag::err_ovl_no_viable_oper) << BinaryOperator::getOpcodeStr(Opc) @@ -7090,7 +8140,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // produce an error. Then, show the non-viable candidates. Result = CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]); } - assert(Result.isInvalid() && + assert(Result.isInvalid() && "C++ binary operator overloading is missing candidates!"); if (Result.isInvalid()) CandidateSet.NoteCandidates(*this, OCD_AllCandidates, Args, 2, @@ -7099,8 +8149,9 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, } case OR_Ambiguous: - Diag(OpLoc, diag::err_ovl_ambiguous_oper) + Diag(OpLoc, diag::err_ovl_ambiguous_oper_binary) << BinaryOperator::getOpcodeStr(Opc) + << Args[0]->getType() << Args[1]->getType() << Args[0]->getSourceRange() << Args[1]->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, 2, BinaryOperator::getOpcodeStr(Opc), OpLoc); @@ -7136,7 +8187,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, DeclarationNameInfo OpNameInfo(OpName, LLoc); OpNameInfo.setCXXOperatorNameRange(SourceRange(LLoc, RLoc)); UnresolvedLookupExpr *Fn - = UnresolvedLookupExpr::Create(Context, /*Dependent*/ true, NamingClass, + = UnresolvedLookupExpr::Create(Context, NamingClass, 0, SourceRange(), OpNameInfo, /*ADL*/ true, /*Overloaded*/ false, UnresolvedSetIterator(), @@ -7146,9 +8197,15 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, return Owned(new (Context) CXXOperatorCallExpr(Context, OO_Subscript, Fn, Args, 2, Context.DependentTy, + VK_RValue, RLoc)); } + if (Args[0]->getObjectKind() == OK_ObjCProperty) + ConvertPropertyForRValue(Args[0]); + if (Args[1]->getObjectKind() == OK_ObjCProperty) + ConvertPropertyForRValue(Args[1]); + // Build an empty overload set. OverloadCandidateSet CandidateSet(LLoc); @@ -7176,15 +8233,16 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // Convert the arguments. CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl); - if (PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0, + if (PerformObjectArgumentInitialization(Args[0], /*Qualifier=*/0, Best->FoundDecl, Method)) return ExprError(); // Convert the arguments. ExprResult InputInit = PerformCopyInitialization(InitializedEntity::InitializeParameter( + Context, FnDecl->getParamDecl(0)), - SourceLocation(), + SourceLocation(), Owned(Args[1])); if (InputInit.isInvalid()) return ExprError(); @@ -7192,19 +8250,17 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, Args[1] = InputInit.takeAs<Expr>(); // Determine the result type - QualType ResultTy - = FnDecl->getType()->getAs<FunctionType>() - ->getCallResultType(Context); + QualType ResultTy = FnDecl->getResultType(); + ExprValueKind VK = Expr::getValueKindForType(ResultTy); + ResultTy = ResultTy.getNonLValueExprType(Context); // Build the actual expression node. - Expr *FnExpr = new (Context) DeclRefExpr(FnDecl, FnDecl->getType(), - LLoc); - UsualUnaryConversions(FnExpr); + Expr *FnExpr = CreateFunctionRefExpr(*this, FnDecl, LLoc); CXXOperatorCallExpr *TheCall = new (Context) CXXOperatorCallExpr(Context, OO_Subscript, FnExpr, Args, 2, - ResultTy, RLoc); + ResultTy, VK, RLoc); if (CheckCallReturnType(FnDecl->getResultType(), LLoc, TheCall, FnDecl)) @@ -7240,8 +8296,10 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, } case OR_Ambiguous: - Diag(LLoc, diag::err_ovl_ambiguous_oper) - << "[]" << Args[0]->getSourceRange() << Args[1]->getSourceRange(); + Diag(LLoc, diag::err_ovl_ambiguous_oper_binary) + << "[]" + << Args[0]->getType() << Args[1]->getType() + << Args[0]->getSourceRange() << Args[1]->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, Args, 2, "[]", LLoc); return ExprError(); @@ -7269,12 +8327,11 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, ExprResult Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, SourceLocation LParenLoc, Expr **Args, - unsigned NumArgs, SourceLocation *CommaLocs, - SourceLocation RParenLoc) { + unsigned NumArgs, SourceLocation RParenLoc) { // Dig out the member expression. This holds both the object // argument and the member function we're referring to. Expr *NakedMemExpr = MemExprE->IgnoreParens(); - + MemberExpr *MemExpr; CXXMethodDecl *Method = 0; DeclAccessPair FoundDecl = DeclAccessPair::make(0, AS_public); @@ -7287,8 +8344,11 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, } else { UnresolvedMemberExpr *UnresExpr = cast<UnresolvedMemberExpr>(NakedMemExpr); Qualifier = UnresExpr->getQualifier(); - + QualType ObjectType = UnresExpr->getBaseType(); + Expr::Classification ObjectClassification + = UnresExpr->isArrow()? Expr::Classification::makeSimpleLValue() + : UnresExpr->getBase()->Classify(Context); // Add overload candidates OverloadCandidateSet CandidateSet(UnresExpr->getMemberLoc()); @@ -7308,20 +8368,26 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, if (isa<UsingShadowDecl>(Func)) Func = cast<UsingShadowDecl>(Func)->getTargetDecl(); - if ((Method = dyn_cast<CXXMethodDecl>(Func))) { + + // Microsoft supports direct constructor calls. + if (getLangOptions().Microsoft && isa<CXXConstructorDecl>(Func)) { + AddOverloadCandidate(cast<CXXConstructorDecl>(Func), I.getPair(), Args, NumArgs, + CandidateSet); + } else if ((Method = dyn_cast<CXXMethodDecl>(Func))) { // If explicit template arguments were provided, we can't call a // non-template member function. if (TemplateArgs) continue; - + AddMethodCandidate(Method, I.getPair(), ActingDC, ObjectType, - Args, NumArgs, - CandidateSet, /*SuppressUserConversions=*/false); + ObjectClassification, + Args, NumArgs, CandidateSet, + /*SuppressUserConversions=*/false); } else { AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(Func), I.getPair(), ActingDC, TemplateArgs, - ObjectType, Args, NumArgs, - CandidateSet, + ObjectType, ObjectClassification, + Args, NumArgs, CandidateSet, /*SuppressUsedConversions=*/false); } } @@ -7330,7 +8396,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, OverloadCandidateSet::iterator Best; switch (CandidateSet.BestViableFunction(*this, UnresExpr->getLocStart(), - Best)) { + Best)) { case OR_Success: Method = cast<CXXMethodDecl>(Best->Function); FoundDecl = Best->FoundDecl; @@ -7374,17 +8440,20 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, MemExpr = cast<MemberExpr>(MemExprE->IgnoreParens()); } + QualType ResultType = Method->getResultType(); + ExprValueKind VK = Expr::getValueKindForType(ResultType); + ResultType = ResultType.getNonLValueExprType(Context); + assert(Method && "Member call to something that isn't a method?"); - CXXMemberCallExpr *TheCall = + CXXMemberCallExpr *TheCall = new (Context) CXXMemberCallExpr(Context, MemExprE, Args, NumArgs, - Method->getCallResultType(), - RParenLoc); + ResultType, VK, RParenLoc); // Check for a valid return type. - if (CheckCallReturnType(Method->getResultType(), MemExpr->getMemberLoc(), + if (CheckCallReturnType(Method->getResultType(), MemExpr->getMemberLoc(), TheCall, Method)) return ExprError(); - + // Convert the object argument (for a non-static member function call). // We only need to do this if there was actually an overload; otherwise // it was done at lookup. @@ -7396,7 +8465,8 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, MemExpr->setBase(ObjectArg); // Convert the rest of the arguments - const FunctionProtoType *Proto = Method->getType()->getAs<FunctionProtoType>(); + const FunctionProtoType *Proto = + Method->getType()->getAs<FunctionProtoType>(); if (ConvertArgumentsForCall(TheCall, MemExpr, Method, Proto, Args, NumArgs, RParenLoc)) return ExprError(); @@ -7415,8 +8485,10 @@ ExprResult Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, - SourceLocation *CommaLocs, SourceLocation RParenLoc) { + if (Object->getObjectKind() == OK_ObjCProperty) + ConvertPropertyForRValue(Object); + assert(Object->getType()->isRecordType() && "Requires object type argument"); const RecordType *Record = Object->getType()->getAs<RecordType>(); @@ -7430,11 +8502,11 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, OverloadCandidateSet CandidateSet(LParenLoc); DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call); - if (RequireCompleteType(LParenLoc, Object->getType(), + if (RequireCompleteType(LParenLoc, Object->getType(), PDiag(diag::err_incomplete_object_call) << Object->getSourceRange())) return true; - + LookupResult R(*this, OpName, LParenLoc, LookupOrdinaryName); LookupQualifiedName(R, Record->getDecl()); R.suppressDiagnostics(); @@ -7442,10 +8514,10 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end(); Oper != OperEnd; ++Oper) { AddMethodCandidate(Oper.getPair(), Object->getType(), - Args, NumArgs, CandidateSet, + Object->Classify(Context), Args, NumArgs, CandidateSet, /*SuppressUserConversions=*/ false); } - + // C++ [over.call.object]p2: // In addition, for each conversion function declared in T of the // form @@ -7471,7 +8543,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, CXXRecordDecl *ActingContext = cast<CXXRecordDecl>(D->getDeclContext()); if (isa<UsingShadowDecl>(D)) D = cast<UsingShadowDecl>(D)->getTargetDecl(); - + // Skip over templated conversion functions; they aren't // surrogates. if (isa<FunctionTemplateDecl>(D)) @@ -7487,8 +8559,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, if (const FunctionProtoType *Proto = ConvType->getAs<FunctionProtoType>()) AddSurrogateCandidate(Conv, I.getPair(), ActingContext, Proto, - Object->getType(), Args, NumArgs, - CandidateSet); + Object, Args, NumArgs, CandidateSet); } // Perform overload resolution. @@ -7544,14 +8615,15 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, // We selected one of the surrogate functions that converts the // object parameter to a function pointer. Perform the conversion // on the object argument, then let ActOnCallExpr finish the job. - + // Create an implicit member expr to refer to the conversion operator. // and then call it. - CXXMemberCallExpr *CE = BuildCXXMemberCallExpr(Object, Best->FoundDecl, - Conv); - - return ActOnCallExpr(S, CE, LParenLoc, MultiExprArg(Args, NumArgs), - CommaLocs, RParenLoc); + ExprResult Call = BuildCXXMemberCallExpr(Object, Best->FoundDecl, Conv); + if (Call.isInvalid()) + return ExprError(); + + return ActOnCallExpr(S, Call.get(), LParenLoc, MultiExprArg(Args, NumArgs), + RParenLoc); } CheckMemberOperatorAccess(LParenLoc, Object, 0, Best->FoundDecl); @@ -7561,7 +8633,8 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, // that calls this method, using Object for the implicit object // parameter and passing along the remaining arguments. CXXMethodDecl *Method = cast<CXXMethodDecl>(Best->Function); - const FunctionProtoType *Proto = Method->getType()->getAs<FunctionProtoType>(); + const FunctionProtoType *Proto = + Method->getType()->getAs<FunctionProtoType>(); unsigned NumArgsInProto = Proto->getNumArgs(); unsigned NumArgsToCheck = NumArgs; @@ -7580,23 +8653,24 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) MethodArgs[ArgIdx + 1] = Args[ArgIdx]; - Expr *NewFn = new (Context) DeclRefExpr(Method, Method->getType(), - SourceLocation()); - UsualUnaryConversions(NewFn); + Expr *NewFn = CreateFunctionRefExpr(*this, Method); // Once we've built TheCall, all of the expressions are properly // owned. - QualType ResultTy = Method->getCallResultType(); + QualType ResultTy = Method->getResultType(); + ExprValueKind VK = Expr::getValueKindForType(ResultTy); + ResultTy = ResultTy.getNonLValueExprType(Context); + CXXOperatorCallExpr *TheCall = new (Context) CXXOperatorCallExpr(Context, OO_Call, NewFn, MethodArgs, NumArgs + 1, - ResultTy, RParenLoc); + ResultTy, VK, RParenLoc); delete [] MethodArgs; - if (CheckCallReturnType(Method->getResultType(), LParenLoc, TheCall, + if (CheckCallReturnType(Method->getResultType(), LParenLoc, TheCall, Method)) return true; - + // We may have default arguments. If so, we need to allocate more // slots in the call for them. if (NumArgs < NumArgsInProto) @@ -7607,7 +8681,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, bool IsError = false; // Initialize the implicit object parameter. - IsError |= PerformObjectArgumentInitialization(Object, /*Qualifier=*/0, + IsError |= PerformObjectArgumentInitialization(Object, /*Qualifier=*/0, Best->FoundDecl, Method); TheCall->setArg(0, Object); @@ -7622,9 +8696,10 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, ExprResult InputInit = PerformCopyInitialization(InitializedEntity::InitializeParameter( + Context, Method->getParamDecl(i)), SourceLocation(), Arg); - + IsError |= InputInit.isInvalid(); Arg = InputInit.takeAs<Expr>(); } else { @@ -7634,7 +8709,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, IsError = true; break; } - + Arg = DefArg.takeAs<Expr>(); } @@ -7664,7 +8739,11 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, /// @c Member is the name of the member we're trying to find. ExprResult Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { - assert(Base->getType()->isRecordType() && "left-hand side must have class type"); + assert(Base->getType()->isRecordType() && + "left-hand side must have class type"); + + if (Base->getObjectKind() == OK_ObjCProperty) + ConvertPropertyForRValue(Base); SourceLocation Loc = Base->getExprLoc(); @@ -7674,7 +8753,8 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { // for a class object x of type T if T::operator->() exists and if // the operator is selected as the best match function by the // overload resolution mechanism (13.3). - DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Arrow); + DeclarationName OpName = + Context.DeclarationNames.getCXXOperatorName(OO_Arrow); OverloadCandidateSet CandidateSet(Loc); const RecordType *BaseRecord = Base->getType()->getAs<RecordType>(); @@ -7689,8 +8769,8 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { for (LookupResult::iterator Oper = R.begin(), OperEnd = R.end(); Oper != OperEnd; ++Oper) { - AddMethodCandidate(Oper.getPair(), Base->getType(), 0, 0, CandidateSet, - /*SuppressUserConversions=*/false); + AddMethodCandidate(Oper.getPair(), Base->getType(), Base->Classify(Context), + 0, 0, CandidateSet, /*SuppressUserConversions=*/false); } // Perform overload resolution. @@ -7711,8 +8791,8 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { return ExprError(); case OR_Ambiguous: - Diag(OpLoc, diag::err_ovl_ambiguous_oper) - << "->" << Base->getSourceRange(); + Diag(OpLoc, diag::err_ovl_ambiguous_oper_unary) + << "->" << Base->getType() << Base->getSourceRange(); CandidateSet.NoteCandidates(*this, OCD_ViableCandidates, &Base, 1); return ExprError(); @@ -7734,16 +8814,16 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc) { return ExprError(); // Build the operator call. - Expr *FnExpr = new (Context) DeclRefExpr(Method, Method->getType(), - SourceLocation()); - UsualUnaryConversions(FnExpr); - - QualType ResultTy = Method->getCallResultType(); + Expr *FnExpr = CreateFunctionRefExpr(*this, Method); + + QualType ResultTy = Method->getResultType(); + ExprValueKind VK = Expr::getValueKindForType(ResultTy); + ResultTy = ResultTy.getNonLValueExprType(Context); CXXOperatorCallExpr *TheCall = - new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr, - &Base, 1, ResultTy, OpLoc); + new (Context) CXXOperatorCallExpr(Context, OO_Arrow, FnExpr, + &Base, 1, ResultTy, VK, OpLoc); - if (CheckCallReturnType(Method->getResultType(), OpLoc, TheCall, + if (CheckCallReturnType(Method->getResultType(), OpLoc, TheCall, Method)) return ExprError(); return Owned(TheCall); @@ -7760,27 +8840,27 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, Expr *SubExpr = FixOverloadedFunctionReference(PE->getSubExpr(), Found, Fn); if (SubExpr == PE->getSubExpr()) - return PE->Retain(); - + return PE; + return new (Context) ParenExpr(PE->getLParen(), PE->getRParen(), SubExpr); - } - + } + if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) { Expr *SubExpr = FixOverloadedFunctionReference(ICE->getSubExpr(), Found, Fn); - assert(Context.hasSameType(ICE->getSubExpr()->getType(), + assert(Context.hasSameType(ICE->getSubExpr()->getType(), SubExpr->getType()) && "Implicit cast type cannot be determined from overload"); assert(ICE->path_empty() && "fixing up hierarchy conversion?"); if (SubExpr == ICE->getSubExpr()) - return ICE->Retain(); - - return ImplicitCastExpr::Create(Context, ICE->getType(), + return ICE; + + return ImplicitCastExpr::Create(Context, ICE->getType(), ICE->getCastKind(), SubExpr, 0, ICE->getValueKind()); - } - + } + if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(E)) { assert(UnOp->getOpcode() == UO_AddrOf && "Can only take the address of an overloaded function"); @@ -7795,7 +8875,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), Found, Fn); if (SubExpr == UnOp->getSubExpr()) - return UnOp->Retain(); + return UnOp; assert(isa<DeclRefExpr>(SubExpr) && "fixed to something other than a decl ref"); @@ -7810,19 +8890,21 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, QualType MemPtrType = Context.getMemberPointerType(Fn->getType(), ClassType.getTypePtr()); - return new (Context) UnaryOperator(SubExpr, UO_AddrOf, - MemPtrType, UnOp->getOperatorLoc()); + return new (Context) UnaryOperator(SubExpr, UO_AddrOf, MemPtrType, + VK_RValue, OK_Ordinary, + UnOp->getOperatorLoc()); } } Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), Found, Fn); if (SubExpr == UnOp->getSubExpr()) - return UnOp->Retain(); - + return UnOp; + return new (Context) UnaryOperator(SubExpr, UO_AddrOf, Context.getPointerType(SubExpr->getType()), + VK_RValue, OK_Ordinary, UnOp->getOperatorLoc()); - } + } if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(E)) { // FIXME: avoid copy. @@ -7838,6 +8920,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, Fn, ULE->getNameLoc(), Fn->getType(), + VK_LValue, TemplateArgs); } @@ -7851,7 +8934,8 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, Expr *Base; - // If we're filling in + // If we're filling in a static method where we used to have an + // implicit member access, rewrite to a simple decl ref. if (MemExpr->isImplicitAccess()) { if (cast<CXXMethodDecl>(Fn)->isStatic()) { return DeclRefExpr::Create(Context, @@ -7860,6 +8944,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, Fn, MemExpr->getMemberLoc(), Fn->getType(), + VK_LValue, TemplateArgs); } else { SourceLocation Loc = MemExpr->getMemberLoc(); @@ -7870,24 +8955,27 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, /*isImplicit=*/true); } } else - Base = MemExpr->getBase()->Retain(); + Base = MemExpr->getBase(); return MemberExpr::Create(Context, Base, - MemExpr->isArrow(), - MemExpr->getQualifier(), + MemExpr->isArrow(), + MemExpr->getQualifier(), MemExpr->getQualifierRange(), - Fn, + Fn, Found, MemExpr->getMemberNameInfo(), TemplateArgs, - Fn->getType()); + Fn->getType(), + cast<CXXMethodDecl>(Fn)->isStatic() + ? VK_LValue : VK_RValue, + OK_Ordinary); } - - assert(false && "Invalid reference to overloaded function"); - return E->Retain(); + + llvm_unreachable("Invalid reference to overloaded function"); + return E; } -ExprResult Sema::FixOverloadedFunctionReference(ExprResult E, +ExprResult Sema::FixOverloadedFunctionReference(ExprResult E, DeclAccessPair Found, FunctionDecl *Fn) { return Owned(FixOverloadedFunctionReference((Expr *)E.get(), Found, Fn)); |