diff options
Diffstat (limited to 'lib/Sema/SemaOverload.cpp')
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 724 |
1 files changed, 461 insertions, 263 deletions
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 2144845f4dd3..08af485ef4c7 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -223,6 +223,7 @@ bool StandardConversionSequence::isPointerConversionToBool() const { // a pointer. if (getToType(1)->isBooleanType() && (getFromType()->isPointerType() || + getFromType()->isMemberPointerType() || getFromType()->isObjCObjectPointerType() || getFromType()->isBlockPointerType() || getFromType()->isNullPtrType() || @@ -288,11 +289,11 @@ static const Expr *IgnoreNarrowingConversion(const Expr *Converted) { /// value of the expression prior to the narrowing conversion. /// \param ConstantType If this is an NK_Constant_Narrowing conversion, the /// type of the expression prior to the narrowing conversion. -NarrowingKind -StandardConversionSequence::getNarrowingKind(ASTContext &Ctx, - const Expr *Converted, - APValue &ConstantValue, - QualType &ConstantType) const { +/// \param IgnoreFloatToIntegralConversion If true type-narrowing conversions +/// from floating point types to integral types should be ignored. +NarrowingKind StandardConversionSequence::getNarrowingKind( + ASTContext &Ctx, const Expr *Converted, APValue &ConstantValue, + QualType &ConstantType, bool IgnoreFloatToIntegralConversion) const { assert(Ctx.getLangOpts().CPlusPlus && "narrowing check outside C++"); // C++11 [dcl.init.list]p7: @@ -327,7 +328,10 @@ StandardConversionSequence::getNarrowingKind(ASTContext &Ctx, FloatingIntegralConversion: if (FromType->isRealFloatingType() && ToType->isIntegralType(Ctx)) { return NK_Type_Narrowing; - } else if (FromType->isIntegralType(Ctx) && ToType->isRealFloatingType()) { + } else if (FromType->isIntegralOrUnscopedEnumerationType() && + ToType->isRealFloatingType()) { + if (IgnoreFloatToIntegralConversion) + return NK_Not_Narrowing; llvm::APSInt IntConstantValue; const Expr *Initializer = IgnoreNarrowingConversion(Converted); assert(Initializer && "Unknown conversion expression"); @@ -580,7 +584,7 @@ namespace { }; } -/// \brief Convert from Sema's representation of template deduction information +/// Convert from Sema's representation of template deduction information /// to the form used in overload-candidate information. DeductionFailureInfo clang::MakeDeductionFailureInfo(ASTContext &Context, @@ -625,6 +629,8 @@ clang::MakeDeductionFailureInfo(ASTContext &Context, break; } + case Sema::TDK_IncompletePack: + // FIXME: It's slightly wasteful to allocate two TemplateArguments for this. case Sema::TDK_Inconsistent: case Sema::TDK_Underqualified: { // FIXME: Should allocate from normal heap so that we can free this later. @@ -667,6 +673,7 @@ void DeductionFailureInfo::Destroy() { case Sema::TDK_NonDependentConversionFailure: break; + case Sema::TDK_IncompletePack: case Sema::TDK_Inconsistent: case Sema::TDK_Underqualified: case Sema::TDK_DeducedMismatch: @@ -716,6 +723,7 @@ TemplateParameter DeductionFailureInfo::getTemplateParameter() { case Sema::TDK_InvalidExplicitArguments: return TemplateParameter::getFromOpaqueValue(Data); + case Sema::TDK_IncompletePack: case Sema::TDK_Inconsistent: case Sema::TDK_Underqualified: return static_cast<DFIParamWithArguments*>(Data)->Param; @@ -736,6 +744,7 @@ TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() { case Sema::TDK_TooManyArguments: case Sema::TDK_TooFewArguments: case Sema::TDK_Incomplete: + case Sema::TDK_IncompletePack: case Sema::TDK_InvalidExplicitArguments: case Sema::TDK_Inconsistent: case Sema::TDK_Underqualified: @@ -773,6 +782,7 @@ const TemplateArgument *DeductionFailureInfo::getFirstArg() { case Sema::TDK_NonDependentConversionFailure: return nullptr; + case Sema::TDK_IncompletePack: case Sema::TDK_Inconsistent: case Sema::TDK_Underqualified: case Sema::TDK_DeducedMismatch: @@ -794,6 +804,7 @@ const TemplateArgument *DeductionFailureInfo::getSecondArg() { case Sema::TDK_Invalid: case Sema::TDK_InstantiationDepth: case Sema::TDK_Incomplete: + case Sema::TDK_IncompletePack: case Sema::TDK_TooManyArguments: case Sema::TDK_TooFewArguments: case Sema::TDK_InvalidExplicitArguments: @@ -997,6 +1008,13 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old, Match = *I; return Ovl_Match; } + + // Builtins that have custom typechecking or have a reference should + // not be overloadable or redeclarable. + if (!getASTContext().canBuiltinBeRedeclared(OldF)) { + Match = *I; + return Ovl_NonFunction; + } } else if (isa<UsingDecl>(OldD) || isa<UsingPackDecl>(OldD)) { // We can overload with these, which can show up when doing // redeclaration checks for UsingDecls. @@ -1182,7 +1200,7 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, return false; } -/// \brief Checks availability of the function depending on the current +/// Checks availability of the function depending on the current /// function context. Inside an unavailable function, unavailability is ignored. /// /// \returns true if \arg FD is unavailable and current context is inside @@ -1200,7 +1218,7 @@ bool Sema::isFunctionConsideredUnavailable(FunctionDecl *FD) { return true; } -/// \brief Tries a user-defined conversion from From to ToType. +/// Tries a user-defined conversion from From to ToType. /// /// Produces an implicit conversion sequence for when a standard conversion /// is not an option. See TryImplicitConversion for more information. @@ -1412,7 +1430,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, return PerformImplicitConversion(From, ToType, ICS, Action); } -/// \brief Determine whether the conversion from FromType to ToType is a valid +/// Determine whether the conversion from FromType to ToType is a valid /// conversion that strips "noexcept" or "noreturn" off the nested function /// type. bool Sema::IsFunctionConversion(QualType FromType, QualType ToType, @@ -1473,12 +1491,10 @@ bool Sema::IsFunctionConversion(QualType FromType, QualType ToType, // Drop 'noexcept' if not present in target type. if (const auto *FromFPT = dyn_cast<FunctionProtoType>(FromFn)) { const auto *ToFPT = cast<FunctionProtoType>(ToFn); - if (FromFPT->isNothrow(Context) && !ToFPT->isNothrow(Context)) { + if (FromFPT->isNothrow() && !ToFPT->isNothrow()) { FromFn = cast<FunctionType>( - Context.getFunctionType(FromFPT->getReturnType(), - FromFPT->getParamTypes(), - FromFPT->getExtProtoInfo().withExceptionSpec( - FunctionProtoType::ExceptionSpecInfo())) + Context.getFunctionTypeWithExceptionSpec(QualType(FromFPT, 0), + EST_None) .getTypePtr()); Changed = true; } @@ -1511,7 +1527,7 @@ bool Sema::IsFunctionConversion(QualType FromType, QualType ToType, return true; } -/// \brief Determine whether the conversion from FromType to ToType is a valid +/// 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 @@ -1766,8 +1782,8 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, (FromType == S.Context.LongDoubleTy && ToType == S.Context.Float128Ty)); if (Float128AndLongDouble && - (&S.Context.getFloatTypeSemantics(S.Context.LongDoubleTy) != - &llvm::APFloat::IEEEdouble())) + (&S.Context.getFloatTypeSemantics(S.Context.LongDoubleTy) == + &llvm::APFloat::PPCDoubleDouble())) return false; } // Floating point conversions (C++ 4.8). @@ -1998,6 +2014,14 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) { isCompleteType(From->getLocStart(), FromType)) return Context.hasSameUnqualifiedType( ToType, FromEnumType->getDecl()->getPromotionType()); + + // C++ [conv.prom]p5: + // If the bit-field has an enumerated type, it is treated as any other + // value of that type for promotion purposes. + // + // ... so do not fall through into the bit-field checks below in C++. + if (getLangOpts().CPlusPlus) + return false; } // C++0x [conv.prom]p2: @@ -2045,6 +2069,11 @@ bool Sema::IsIntegralPromotion(Expr *From, QualType FromType, QualType ToType) { // other value of that type for promotion purposes (C++ 4.5p3). // FIXME: We should delay checking of bit-fields until we actually perform the // conversion. + // + // FIXME: In C, only bit-fields of types _Bool, int, or unsigned int may be + // promoted, per C11 6.3.1.1/2. We promote all bit-fields (including enum + // bit-fields and those whose underlying type is larger than int) for GCC + // compatibility. if (From) { if (FieldDecl *MemberDecl = From->getSourceBitField()) { llvm::APSInt BitWidth; @@ -2111,7 +2140,7 @@ bool Sema::IsFloatingPointPromotion(QualType FromType, QualType ToType) { return false; } -/// \brief Determine if a conversion is a complex promotion. +/// Determine if a conversion is a complex promotion. /// /// A complex promotion is defined as a complex -> complex conversion /// where the conversion between the underlying real types is a @@ -2345,7 +2374,7 @@ bool Sema::IsPointerConversion(Expr *From, QualType FromType, QualType ToType, return false; } -/// \brief Adopt the given qualifiers for the given type. +/// Adopt the given qualifiers for the given type. static QualType AdoptQualifiers(ASTContext &Context, QualType T, Qualifiers Qs){ Qualifiers TQs = T.getQualifiers(); @@ -2533,7 +2562,7 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, return false; } -/// \brief Determine whether this is an Objective-C writeback conversion, +/// Determine whether this is an Objective-C writeback conversion, /// used for parameter passing when performing automatic reference counting. /// /// \param FromType The type we're converting form. @@ -2593,7 +2622,7 @@ bool Sema::isObjCWritebackConversion(QualType FromType, QualType ToType, IncompatibleObjC)) return false; - /// \brief Construct the type we're converting to, which is a pointer to + /// Construct the type we're converting to, which is a pointer to /// __autoreleasing pointee. FromPointee = Context.getQualifiedType(FromPointee, FromQuals); ConvertedType = Context.getPointerType(FromPointee); @@ -2803,9 +2832,9 @@ void Sema::HandleFunctionTypeMismatch(PartialDiagnostic &PDiag, // Handle exception specification differences on canonical type (in C++17 // onwards). if (cast<FunctionProtoType>(FromFunction->getCanonicalTypeUnqualified()) - ->isNothrow(Context) != + ->isNothrow() != cast<FunctionProtoType>(ToFunction->getCanonicalTypeUnqualified()) - ->isNothrow(Context)) { + ->isNothrow()) { PDiag << ft_noexcept; return; } @@ -3065,7 +3094,7 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType, // in multi-level pointers, subject to the following rules: [...] bool PreviousToQualsIncludeConst = true; bool UnwrappedAnyPointer = false; - while (Context.UnwrapSimilarPointerTypes(FromType, ToType)) { + while (Context.UnwrapSimilarTypes(FromType, ToType)) { // Within each iteration of the loop, we check the qualifiers to // determine if this still looks like a qualification // conversion. Then, if all is well, we unwrap one more level of @@ -3121,6 +3150,15 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType, = PreviousToQualsIncludeConst && ToQuals.hasConst(); } + // Allows address space promotion by language rules implemented in + // Type::Qualifiers::isAddressSpaceSupersetOf. + Qualifiers FromQuals = FromType.getQualifiers(); + Qualifiers ToQuals = ToType.getQualifiers(); + if (!ToQuals.isAddressSpaceSupersetOf(FromQuals) && + !FromQuals.isAddressSpaceSupersetOf(ToQuals)) { + return false; + } + // We are left with FromType and ToType being the pointee types // after unwrapping the original FromType and ToType the same number // of types. If we unwrapped any pointers, and if FromType and @@ -3129,7 +3167,7 @@ Sema::IsQualificationConversion(QualType FromType, QualType ToType, return UnwrappedAnyPointer && Context.hasSameUnqualifiedType(FromType,ToType); } -/// \brief - Determine whether this is a conversion from a scalar type to an +/// - Determine whether this is a conversion from a scalar type to an /// atomic type. /// /// If successful, updates \c SCS's second and third steps in the conversion @@ -3472,7 +3510,7 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) { return true; } -/// \brief Compare the user-defined conversion functions or constructors +/// Compare the user-defined conversion functions or constructors /// of two user-defined conversion sequences to determine whether any ordering /// is possible. static ImplicitConversionSequence::CompareKind @@ -3620,16 +3658,6 @@ CompareImplicitConversionSequences(Sema &S, SourceLocation Loc, return Result; } -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); - } - - 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 @@ -3653,7 +3681,7 @@ compareStandardConversionSubsets(ASTContext &Context, Result = ImplicitConversionSequence::Worse; else return ImplicitConversionSequence::Indistinguishable; - } else if (!hasSimilarType(Context, SCS1.getToType(1), SCS2.getToType(1))) + } else if (!Context.hasSimilarType(SCS1.getToType(1), SCS2.getToType(1))) return ImplicitConversionSequence::Indistinguishable; if (SCS1.Third == SCS2.Third) { @@ -3674,7 +3702,7 @@ compareStandardConversionSubsets(ASTContext &Context, return ImplicitConversionSequence::Indistinguishable; } -/// \brief Determine whether one of the given reference bindings is better +/// 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, @@ -3927,7 +3955,7 @@ CompareQualificationConversions(Sema &S, : ImplicitConversionSequence::Better; } - while (S.Context.UnwrapSimilarPointerTypes(T1, T2)) { + while (S.Context.UnwrapSimilarTypes(T1, T2)) { // Within each iteration of the loop, we check the qualifiers to // determine if this still looks like a qualification // conversion. Then, if all is well, we unwrap one more level of @@ -4199,7 +4227,7 @@ CompareDerivedToBaseConversions(Sema &S, SourceLocation Loc, return ImplicitConversionSequence::Indistinguishable; } -/// \brief Determine whether the given type is valid, e.g., it is not an invalid +/// Determine whether the given type is valid, e.g., it is not an invalid /// C++ class. static bool isTypeValid(QualType T) { if (CXXRecordDecl *Record = T->getAsCXXRecordDecl()) @@ -4302,7 +4330,7 @@ Sema::CompareReferenceRelationship(SourceLocation Loc, return Ref_Related; } -/// \brief Look for a user-defined conversion to a value reference-compatible +/// Look for a user-defined conversion to a value reference-compatible /// with DeclType. Return true if something definite is found. static bool FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, @@ -4429,7 +4457,7 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS, llvm_unreachable("Invalid OverloadResult!"); } -/// \brief Compute an implicit conversion sequence for reference +/// Compute an implicit conversion sequence for reference /// initialization. static ImplicitConversionSequence TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, @@ -5137,6 +5165,13 @@ Sema::PerformObjectArgumentInitialization(Expr *From, FromRecordType = From->getType(); DestType = ImplicitParamRecordType; FromClassification = From->Classify(Context); + + // When performing member access on an rvalue, materialize a temporary. + if (From->isRValue()) { + From = CreateMaterializeTemporaryExpr(FromRecordType, From, + Method->getRefQualifier() != + RefQualifierKind::RQ_RValue); + } } // Note that we always use the true parent context when performing @@ -5145,7 +5180,8 @@ Sema::PerformObjectArgumentInitialization(Expr *From, *this, From->getLocStart(), From->getType(), FromClassification, Method, Method->getParent()); if (ICS.isBad()) { - if (ICS.Bad.Kind == BadConversionSequence::bad_qualifiers) { + switch (ICS.Bad.Kind) { + case BadConversionSequence::bad_qualifiers: { Qualifiers FromQs = FromRecordType.getQualifiers(); Qualifiers ToQs = DestType.getQualifiers(); unsigned CVR = FromQs.getCVRQualifiers() & ~ToQs.getCVRQualifiers(); @@ -5158,10 +5194,28 @@ Sema::PerformObjectArgumentInitialization(Expr *From, << Method->getDeclName(); return ExprError(); } + break; + } + + case BadConversionSequence::lvalue_ref_to_rvalue: + case BadConversionSequence::rvalue_ref_to_lvalue: { + bool IsRValueQualified = + Method->getRefQualifier() == RefQualifierKind::RQ_RValue; + Diag(From->getLocStart(), diag::err_member_function_call_bad_ref) + << Method->getDeclName() << FromClassification.isRValue() + << IsRValueQualified; + Diag(Method->getLocation(), diag::note_previous_decl) + << Method->getDeclName(); + return ExprError(); + } + + case BadConversionSequence::no_conversion: + case BadConversionSequence::unrelated_class: + break; } return Diag(From->getLocStart(), - diag::err_implicit_object_parameter_init) + diag::err_member_function_call_bad_type) << ImplicitParamRecordType << FromRecordType << From->getSourceRange(); } @@ -5380,10 +5434,11 @@ static ExprResult CheckConvertedConstantExpression(Sema &S, Expr *From, SmallVector<PartialDiagnosticAt, 8> Notes; Expr::EvalResult Eval; Eval.Diag = &Notes; + Expr::ConstExprUsage Usage = CCE == Sema::CCEK_TemplateArg + ? Expr::EvaluateForMangling + : Expr::EvaluateForCodeGen; - if ((T->isReferenceType() - ? !Result.get()->EvaluateAsLValue(Eval, S.Context) - : !Result.get()->EvaluateAsRValue(Eval, S.Context)) || + if (!Result.get()->EvaluateAsConstantExpr(Eval, Usage, S.Context) || (RequireInt && !Eval.Val.isInt())) { // The expression can't be folded, so we can't keep it at this position in // the AST. @@ -5622,7 +5677,7 @@ collectViableConversionCandidates(Sema &SemaRef, Expr *From, QualType ToType, } } -/// \brief Attempt to convert the given expression to a type which is accepted +/// Attempt to convert the given expression to a type which is accepted /// by the given converter. /// /// This routine will attempt to convert an expression of class type to a @@ -5940,6 +5995,13 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, Candidate.IgnoreObjectArgument = false; Candidate.ExplicitCallArguments = Args.size(); + if (Function->isMultiVersion() && Function->hasAttr<TargetAttr>() && + !Function->getAttr<TargetAttr>()->isDefaultVersion()) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_non_default_multiversion_function; + return; + } + if (Constructor) { // C++ [class.copy]p3: // A member function template is never instantiated to perform the copy @@ -6220,12 +6282,17 @@ convertArgsForAvailabilityChecks(Sema &S, FunctionDecl *Function, Expr *ThisArg, if (!Function->isVariadic() && Args.size() < Function->getNumParams()) { for (unsigned i = Args.size(), e = Function->getNumParams(); i != e; ++i) { ParmVarDecl *P = Function->getParamDecl(i); - ExprResult R = S.PerformCopyInitialization( - InitializedEntity::InitializeParameter(S.Context, - Function->getParamDecl(i)), - SourceLocation(), - P->hasUninstantiatedDefaultArg() ? P->getUninstantiatedDefaultArg() - : P->getDefaultArg()); + Expr *DefArg = P->hasUninstantiatedDefaultArg() + ? P->getUninstantiatedDefaultArg() + : P->getDefaultArg(); + // This can only happen in code completion, i.e. when PartialOverloading + // is true. + if (!DefArg) + return false; + ExprResult R = + S.PerformCopyInitialization(InitializedEntity::InitializeParameter( + S.Context, Function->getParamDecl(i)), + SourceLocation(), DefArg); if (R.isInvalid()) return false; ConvertedArgs.push_back(R.get()); @@ -6336,67 +6403,65 @@ bool Sema::diagnoseArgIndependentDiagnoseIfAttrs(const NamedDecl *ND, }); } -/// \brief Add all of the function declarations in the given function set to +/// Add all of the function declarations in the given function set to /// the overload candidate set. void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, ArrayRef<Expr *> Args, - OverloadCandidateSet& CandidateSet, + OverloadCandidateSet &CandidateSet, TemplateArgumentListInfo *ExplicitTemplateArgs, bool SuppressUserConversions, bool PartialOverloading, bool FirstArgumentIsBase) { for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) { NamedDecl *D = F.getDecl()->getUnderlyingDecl(); - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { - ArrayRef<Expr *> FunctionArgs = Args; - if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic()) { - QualType ObjectType; - Expr::Classification ObjectClassification; - if (Args.size() > 0) { - if (Expr *E = Args[0]) { - // Use the explit base to restrict the lookup: - ObjectType = E->getType(); - ObjectClassification = E->Classify(Context); - } // .. else there is an implit base. - FunctionArgs = Args.slice(1); - } - AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(), - cast<CXXMethodDecl>(FD)->getParent(), ObjectType, - ObjectClassification, FunctionArgs, CandidateSet, - SuppressUserConversions, PartialOverloading); - } else { - // Slice the first argument (which is the base) when we access - // static method as non-static - if (Args.size() > 0 && (!Args[0] || (FirstArgumentIsBase && isa<CXXMethodDecl>(FD) && - !isa<CXXConstructorDecl>(FD)))) { - assert(cast<CXXMethodDecl>(FD)->isStatic()); - FunctionArgs = Args.slice(1); - } - AddOverloadCandidate(FD, F.getPair(), FunctionArgs, CandidateSet, - SuppressUserConversions, PartialOverloading); - } - } else { - FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(D); - if (isa<CXXMethodDecl>(FunTmpl->getTemplatedDecl()) && - !cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())->isStatic()) { - QualType ObjectType; - Expr::Classification ObjectClassification; + ArrayRef<Expr *> FunctionArgs = Args; + + FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D); + FunctionDecl *FD = + FunTmpl ? FunTmpl->getTemplatedDecl() : cast<FunctionDecl>(D); + + if (isa<CXXMethodDecl>(FD) && !cast<CXXMethodDecl>(FD)->isStatic()) { + QualType ObjectType; + Expr::Classification ObjectClassification; + if (Args.size() > 0) { if (Expr *E = Args[0]) { - // Use the explit base to restrict the lookup: + // Use the explicit base to restrict the lookup: ObjectType = E->getType(); ObjectClassification = E->Classify(Context); - } // .. else there is an implit base. + } // .. else there is an implicit base. + FunctionArgs = Args.slice(1); + } + if (FunTmpl) { AddMethodTemplateCandidate( FunTmpl, F.getPair(), cast<CXXRecordDecl>(FunTmpl->getDeclContext()), ExplicitTemplateArgs, ObjectType, ObjectClassification, - Args.slice(1), CandidateSet, SuppressUserConversions, + FunctionArgs, CandidateSet, SuppressUserConversions, PartialOverloading); } else { - AddTemplateOverloadCandidate(FunTmpl, F.getPair(), - ExplicitTemplateArgs, Args, - CandidateSet, SuppressUserConversions, - PartialOverloading); + AddMethodCandidate(cast<CXXMethodDecl>(FD), F.getPair(), + cast<CXXMethodDecl>(FD)->getParent(), ObjectType, + ObjectClassification, FunctionArgs, CandidateSet, + SuppressUserConversions, PartialOverloading); + } + } else { + // This branch handles both standalone functions and static methods. + + // Slice the first argument (which is the base) when we access + // static method as non-static. + if (Args.size() > 0 && + (!Args[0] || (FirstArgumentIsBase && isa<CXXMethodDecl>(FD) && + !isa<CXXConstructorDecl>(FD)))) { + assert(cast<CXXMethodDecl>(FD)->isStatic()); + FunctionArgs = Args.slice(1); + } + if (FunTmpl) { + AddTemplateOverloadCandidate( + FunTmpl, F.getPair(), ExplicitTemplateArgs, FunctionArgs, + CandidateSet, SuppressUserConversions, PartialOverloading); + } else { + AddOverloadCandidate(FD, F.getPair(), FunctionArgs, CandidateSet, + SuppressUserConversions, PartialOverloading); } } } @@ -6564,9 +6629,15 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, Candidate.DeductionFailure.Data = FailedAttr; return; } + + if (Method->isMultiVersion() && Method->hasAttr<TargetAttr>() && + !Method->getAttr<TargetAttr>()->isDefaultVersion()) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_non_default_multiversion_function; + } } -/// \brief Add a C++ member function template as a candidate to the candidate +/// 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. void @@ -6634,7 +6705,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, Conversions); } -/// \brief Add a C++ function template specialization as a candidate +/// Add a C++ function template specialization as a candidate /// in the candidate set, using template argument deduction to produce /// an appropriate function template specialization. void @@ -6967,9 +7038,15 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion, Candidate.DeductionFailure.Data = FailedAttr; return; } + + if (Conversion->isMultiVersion() && Conversion->hasAttr<TargetAttr>() && + !Conversion->getAttr<TargetAttr>()->isDefaultVersion()) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_non_default_multiversion_function; + } } -/// \brief Adds a conversion function template specialization +/// Adds a conversion function template specialization /// candidate to the overload set, using template argument deduction /// to deduce the template arguments of the conversion function /// template from the type that we are converting to (C++ @@ -7124,7 +7201,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, } } -/// \brief Add overload candidates for overloaded operators that are +/// Add overload candidates for overloaded operators that are /// member functions. /// /// Add the overloaded operator candidates that are member functions @@ -7260,18 +7337,18 @@ class BuiltinCandidateTypeSet { /// used in the built-in candidates. TypeSet EnumerationTypes; - /// \brief The set of vector types that will be used in the built-in + /// 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 + /// A flag indicating non-record types are viable candidates bool HasNonRecordTypes; - /// \brief A flag indicating whether either arithmetic or enumeration types + /// A flag indicating whether either arithmetic or enumeration types /// were present in the candidate set. bool HasArithmeticOrEnumeralTypes; - /// \brief A flag indicating whether the nullptr type was present in the + /// A flag indicating whether the nullptr type was present in the /// candidate set. bool HasNullPtrType; @@ -7524,7 +7601,7 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty, } } -/// \brief Helper function for AddBuiltinOperatorCandidates() that adds +/// Helper function for AddBuiltinOperatorCandidates() that adds /// the volatile- and non-volatile-qualified assignment operators for the /// given type to the candidate set. static void AddBuiltinAssignmentOperatorCandidates(Sema &S, @@ -7602,7 +7679,7 @@ static Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) { namespace { -/// \brief Helper class to manage the addition of builtin operator overload +/// 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. @@ -7658,6 +7735,8 @@ class BuiltinOperatorOverloadBuilder { ArithmeticTypes.push_back(S.Context.BoolTy); ArithmeticTypes.push_back(S.Context.CharTy); ArithmeticTypes.push_back(S.Context.WCharTy); + if (S.Context.getLangOpts().Char8) + ArithmeticTypes.push_back(S.Context.Char8Ty); ArithmeticTypes.push_back(S.Context.Char16Ty); ArithmeticTypes.push_back(S.Context.Char32Ty); ArithmeticTypes.push_back(S.Context.SignedCharTy); @@ -7673,7 +7752,7 @@ class BuiltinOperatorOverloadBuilder { "Enough inline storage for all arithmetic types."); } - /// \brief Helper method to factor out the common pattern of adding overloads + /// Helper method to factor out the common pattern of adding overloads /// for '++' and '--' builtin operators. void addPlusPlusMinusMinusStyleOverloads(QualType CandidateTy, bool HasVolatile, @@ -7733,11 +7812,13 @@ public: InitArithmeticTypes(); } + // Increment is deprecated for bool since C++17. + // // 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 + // 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); @@ -7754,10 +7835,16 @@ public: if (!HasArithmeticOrEnumeralCandidateType) return; - for (unsigned Arith = (Op == OO_PlusPlus? 0 : 1); - Arith < NumArithmeticTypes; ++Arith) { + for (unsigned Arith = 0; Arith < NumArithmeticTypes; ++Arith) { + const auto TypeOfT = ArithmeticTypes[Arith]; + if (TypeOfT == S.Context.BoolTy) { + if (Op == OO_MinusMinus) + continue; + if (Op == OO_PlusPlus && S.getLangOpts().CPlusPlus17) + continue; + } addPlusPlusMinusMinusStyleOverloads( - ArithmeticTypes[Arith], + TypeOfT, VisibleTypeConversionsQuals.hasVolatile(), VisibleTypeConversionsQuals.hasRestrict()); } @@ -7929,7 +8016,8 @@ public: // bool operator>=(T, T); // bool operator==(T, T); // bool operator!=(T, T); - void addRelationalPointerOrEnumeralOverloads() { + // R operator<=>(T, T) + void addGenericBinaryPointerOrEnumeralOverloads() { // C++ [over.match.oper]p3: // [...]the built-in candidates include all of the candidate operator // functions defined in 13.6 that, compared to the given operator, [...] @@ -8002,7 +8090,6 @@ public: UserDefinedBinaryOperators.count(std::make_pair(CanonType, CanonType))) continue; - QualType ParamTypes[2] = { *Enum, *Enum }; S.AddBuiltinCandidate(ParamTypes, Args, CandidateSet); } @@ -8120,6 +8207,41 @@ public: } } + // C++2a [over.built]p14: + // + // For every integral type T there exists a candidate operator function + // of the form + // + // std::strong_ordering operator<=>(T, T) + // + // C++2a [over.built]p15: + // + // For every pair of floating-point types L and R, there exists a candidate + // operator function of the form + // + // std::partial_ordering operator<=>(L, R); + // + // FIXME: The current specification for integral types doesn't play nice with + // the direction of p0946r0, which allows mixed integral and unscoped-enum + // comparisons. Under the current spec this can lead to ambiguity during + // overload resolution. For example: + // + // enum A : int {a}; + // auto x = (a <=> (long)42); + // + // error: call is ambiguous for arguments 'A' and 'long'. + // note: candidate operator<=>(int, int) + // note: candidate operator<=>(long, long) + // + // To avoid this error, this function deviates from the specification and adds + // the mixed overloads `operator<=>(L, R)` where L and R are promoted + // arithmetic types (the same as the generic relational overloads). + // + // For now this function acts as a placeholder. + void addThreeWayArithmeticOverloads() { + addGenericBinaryArithmeticOverloads(); + } + // C++ [over.built]p17: // // For every pair of promoted integral types L and R, there @@ -8688,12 +8810,14 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, case OO_Greater: case OO_LessEqual: case OO_GreaterEqual: - OpBuilder.addRelationalPointerOrEnumeralOverloads(); + OpBuilder.addGenericBinaryPointerOrEnumeralOverloads(); OpBuilder.addGenericBinaryArithmeticOverloads(); break; case OO_Spaceship: - llvm_unreachable("<=> expressions not supported yet"); + OpBuilder.addGenericBinaryPointerOrEnumeralOverloads(); + OpBuilder.addThreeWayArithmeticOverloads(); + break; case OO_Percent: case OO_Caret: @@ -8764,7 +8888,7 @@ void Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, } } -/// \brief Add function candidates found via argument-dependent lookup +/// Add function candidates found via argument-dependent lookup /// to the set of overloading candidates. /// /// This routine performs argument-dependent name lookup based on the @@ -8870,6 +8994,47 @@ static Comparison compareEnableIfAttrs(const Sema &S, const FunctionDecl *Cand1, return Cand1I == Cand1Attrs.end() ? Comparison::Equal : Comparison::Better; } +static bool isBetterMultiversionCandidate(const OverloadCandidate &Cand1, + const OverloadCandidate &Cand2) { + if (!Cand1.Function || !Cand1.Function->isMultiVersion() || !Cand2.Function || + !Cand2.Function->isMultiVersion()) + return false; + + // If this is a cpu_dispatch/cpu_specific multiversion situation, prefer + // cpu_dispatch, else arbitrarily based on the identifiers. + bool Cand1CPUDisp = Cand1.Function->hasAttr<CPUDispatchAttr>(); + bool Cand2CPUDisp = Cand2.Function->hasAttr<CPUDispatchAttr>(); + const auto *Cand1CPUSpec = Cand1.Function->getAttr<CPUSpecificAttr>(); + const auto *Cand2CPUSpec = Cand2.Function->getAttr<CPUSpecificAttr>(); + + if (!Cand1CPUDisp && !Cand2CPUDisp && !Cand1CPUSpec && !Cand2CPUSpec) + return false; + + if (Cand1CPUDisp && !Cand2CPUDisp) + return true; + if (Cand2CPUDisp && !Cand1CPUDisp) + return false; + + if (Cand1CPUSpec && Cand2CPUSpec) { + if (Cand1CPUSpec->cpus_size() != Cand2CPUSpec->cpus_size()) + return Cand1CPUSpec->cpus_size() < Cand2CPUSpec->cpus_size(); + + std::pair<CPUSpecificAttr::cpus_iterator, CPUSpecificAttr::cpus_iterator> + FirstDiff = std::mismatch( + Cand1CPUSpec->cpus_begin(), Cand1CPUSpec->cpus_end(), + Cand2CPUSpec->cpus_begin(), + [](const IdentifierInfo *LHS, const IdentifierInfo *RHS) { + return LHS->getName() == RHS->getName(); + }); + + assert(FirstDiff.first != Cand1CPUSpec->cpus_end() && + "Two different cpu-specific versions should not have the same " + "identifier list, otherwise they'd be the same decl!"); + return (*FirstDiff.first)->getName() < (*FirstDiff.second)->getName(); + } + llvm_unreachable("No way to get here unless both had cpu_dispatch"); +} + /// isBetterOverloadCandidate - Determines whether the first overload /// candidate is a better candidate than the second (C++ 13.3.3p1). bool clang::isBetterOverloadCandidate( @@ -9067,7 +9232,10 @@ bool clang::isBetterOverloadCandidate( functionHasPassObjectSizeParams(Cand1.Function); bool HasPS2 = Cand2.Function != nullptr && functionHasPassObjectSizeParams(Cand2.Function); - return HasPS1 != HasPS2 && HasPS1; + if (HasPS1 != HasPS2 && HasPS1) + return true; + + return isBetterMultiversionCandidate(Cand1, Cand2); } /// Determine whether two declarations are "equivalent" for the purposes of @@ -9137,7 +9305,7 @@ void Sema::diagnoseEquivalentInternalLinkageDeclarations( } } -/// \brief Computes the best viable function (C++ 13.3.3) +/// Computes the best viable function (C++ 13.3.3) /// within an overload candidate set. /// /// \param Loc The location of the function name (or operator symbol) for @@ -9228,66 +9396,77 @@ enum OverloadCandidateKind { oc_function, oc_method, oc_constructor, - oc_function_template, - oc_method_template, - oc_constructor_template, oc_implicit_default_constructor, oc_implicit_copy_constructor, oc_implicit_move_constructor, oc_implicit_copy_assignment, oc_implicit_move_assignment, - oc_inherited_constructor, - oc_inherited_constructor_template + oc_inherited_constructor +}; + +enum OverloadCandidateSelect { + ocs_non_template, + ocs_template, + ocs_described_template, }; -static OverloadCandidateKind +static std::pair<OverloadCandidateKind, OverloadCandidateSelect> ClassifyOverloadCandidate(Sema &S, NamedDecl *Found, FunctionDecl *Fn, std::string &Description) { - bool isTemplate = false; + bool isTemplate = Fn->isTemplateDecl() || Found->isTemplateDecl(); if (FunctionTemplateDecl *FunTmpl = Fn->getPrimaryTemplate()) { isTemplate = true; Description = S.getTemplateArgumentBindingsText( - FunTmpl->getTemplateParameters(), *Fn->getTemplateSpecializationArgs()); + FunTmpl->getTemplateParameters(), *Fn->getTemplateSpecializationArgs()); } - if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn)) { - if (!Ctor->isImplicit()) { - if (isa<ConstructorUsingShadowDecl>(Found)) - return isTemplate ? oc_inherited_constructor_template - : oc_inherited_constructor; - else - return isTemplate ? oc_constructor_template : oc_constructor; - } + OverloadCandidateSelect Select = [&]() { + if (!Description.empty()) + return ocs_described_template; + return isTemplate ? ocs_template : ocs_non_template; + }(); - if (Ctor->isDefaultConstructor()) - return oc_implicit_default_constructor; + OverloadCandidateKind Kind = [&]() { + if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn)) { + if (!Ctor->isImplicit()) { + if (isa<ConstructorUsingShadowDecl>(Found)) + return oc_inherited_constructor; + else + return oc_constructor; + } - if (Ctor->isMoveConstructor()) - return oc_implicit_move_constructor; + if (Ctor->isDefaultConstructor()) + return oc_implicit_default_constructor; - assert(Ctor->isCopyConstructor() && - "unexpected sort of implicit constructor"); - return oc_implicit_copy_constructor; - } + if (Ctor->isMoveConstructor()) + return oc_implicit_move_constructor; - if (CXXMethodDecl *Meth = dyn_cast<CXXMethodDecl>(Fn)) { - // This actually gets spelled 'candidate function' for now, but - // it doesn't hurt to split it out. - if (!Meth->isImplicit()) - return isTemplate ? oc_method_template : oc_method; + assert(Ctor->isCopyConstructor() && + "unexpected sort of implicit constructor"); + return oc_implicit_copy_constructor; + } - if (Meth->isMoveAssignmentOperator()) - return oc_implicit_move_assignment; + if (CXXMethodDecl *Meth = dyn_cast<CXXMethodDecl>(Fn)) { + // This actually gets spelled 'candidate function' for now, but + // it doesn't hurt to split it out. + if (!Meth->isImplicit()) + return oc_method; - if (Meth->isCopyAssignmentOperator()) - return oc_implicit_copy_assignment; + if (Meth->isMoveAssignmentOperator()) + return oc_implicit_move_assignment; - assert(isa<CXXConversionDecl>(Meth) && "expected conversion"); - return oc_method; - } + if (Meth->isCopyAssignmentOperator()) + return oc_implicit_copy_assignment; + + assert(isa<CXXConversionDecl>(Meth) && "expected conversion"); + return oc_method; + } - return isTemplate ? oc_function_template : oc_function; + return oc_function; + }(); + + return std::make_pair(Kind, Select); } void MaybeEmitInheritedConstructorNote(Sema &S, Decl *FoundDecl) { @@ -9313,7 +9492,7 @@ static bool isFunctionAlwaysEnabled(const ASTContext &Ctx, return true; } -/// \brief Returns true if we can take the address of the function. +/// Returns true if we can take the address of the function. /// /// \param Complain - If true, we'll emit a diagnostic /// \param InOverloadResolution - For the purposes of emitting a diagnostic, are @@ -9375,11 +9554,16 @@ void Sema::NoteOverloadCandidate(NamedDecl *Found, FunctionDecl *Fn, QualType DestType, bool TakingAddress) { if (TakingAddress && !checkAddressOfCandidateIsAvailable(*this, Fn)) return; + if (Fn->isMultiVersion() && Fn->hasAttr<TargetAttr>() && + !Fn->getAttr<TargetAttr>()->isDefaultVersion()) + return; std::string FnDesc; - OverloadCandidateKind K = ClassifyOverloadCandidate(*this, Found, Fn, FnDesc); + std::pair<OverloadCandidateKind, OverloadCandidateSelect> KSPair = + ClassifyOverloadCandidate(*this, Found, Fn, FnDesc); PartialDiagnostic PD = PDiag(diag::note_ovl_candidate) - << (unsigned) K << Fn << FnDesc; + << (unsigned)KSPair.first << (unsigned)KSPair.second + << Fn << FnDesc; HandleFunctionTypeMismatch(PD, Fn->getType(), DestType); Diag(Fn->getLocation(), PD); @@ -9453,7 +9637,7 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, } std::string FnDesc; - OverloadCandidateKind FnKind = + std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair = ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn, FnDesc); Expr *FromExpr = Conv.Bad.FromExpr; @@ -9468,9 +9652,9 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, DeclarationName Name = cast<OverloadExpr>(E)->getName(); S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_overload) - << (unsigned) FnKind << FnDesc - << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) - << ToTy << Name << I+1; + << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << ToTy + << Name << I + 1; MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); return; } @@ -9497,43 +9681,38 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, if (FromQs.getAddressSpace() != ToQs.getAddressSpace()) { S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_addrspace) - << (unsigned) FnKind << FnDesc - << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) - << FromTy - << FromQs.getAddressSpaceAttributePrintValue() - << ToQs.getAddressSpaceAttributePrintValue() - << (unsigned) isObjectArgument << I+1; + << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy + << ToTy << (unsigned)isObjectArgument << I + 1; MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); return; } if (FromQs.getObjCLifetime() != ToQs.getObjCLifetime()) { S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_ownership) - << (unsigned) FnKind << FnDesc - << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) - << FromTy - << FromQs.getObjCLifetime() << ToQs.getObjCLifetime() - << (unsigned) isObjectArgument << I+1; + << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy + << FromQs.getObjCLifetime() << ToQs.getObjCLifetime() + << (unsigned)isObjectArgument << I + 1; MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); return; } if (FromQs.getObjCGCAttr() != ToQs.getObjCGCAttr()) { S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_gc) - << (unsigned) FnKind << FnDesc - << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) - << FromTy - << FromQs.getObjCGCAttr() << ToQs.getObjCGCAttr() - << (unsigned) isObjectArgument << I+1; + << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy + << FromQs.getObjCGCAttr() << ToQs.getObjCGCAttr() + << (unsigned)isObjectArgument << I + 1; MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); return; } if (FromQs.hasUnaligned() != ToQs.hasUnaligned()) { S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_unaligned) - << (unsigned) FnKind << FnDesc - << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) - << FromTy << FromQs.hasUnaligned() << I+1; + << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy + << FromQs.hasUnaligned() << I + 1; MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); return; } @@ -9543,14 +9722,14 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, if (isObjectArgument) { S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_cvr_this) - << (unsigned) FnKind << FnDesc - << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) - << FromTy << (CVR - 1); + << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy + << (CVR - 1); } else { S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_cvr) - << (unsigned) FnKind << FnDesc - << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) - << FromTy << (CVR - 1) << I+1; + << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy + << (CVR - 1) << I + 1; } MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); return; @@ -9560,9 +9739,9 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, // telling the user that it has type void is not useful. if (FromExpr && isa<InitListExpr>(FromExpr)) { S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_list_argument) - << (unsigned) FnKind << FnDesc - << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) - << FromTy << ToTy << (unsigned) isObjectArgument << I+1; + << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy + << ToTy << (unsigned)isObjectArgument << I + 1; MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); return; } @@ -9576,10 +9755,10 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, if (TempFromTy->isIncompleteType()) { // Emit the generic diagnostic and, optionally, add the hints to it. S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_conv_incomplete) - << (unsigned) FnKind << FnDesc - << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) - << FromTy << ToTy << (unsigned) isObjectArgument << I+1 - << (unsigned) (Cand->Fix.Kind); + << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy + << ToTy << (unsigned)isObjectArgument << I + 1 + << (unsigned)(Cand->Fix.Kind); MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); return; @@ -9617,21 +9796,19 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, ToTy.getNonReferenceType().getCanonicalType() == FromTy.getNonReferenceType().getCanonicalType()) { S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_lvalue) - << (unsigned) FnKind << FnDesc - << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) - << (unsigned) isObjectArgument << I + 1; + << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc + << (unsigned)isObjectArgument << I + 1 + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()); MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); return; } } if (BaseToDerivedConversion) { - 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; + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_base_to_derived_conv) + << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) + << (BaseToDerivedConversion - 1) << FromTy << ToTy << I + 1; MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); return; } @@ -9642,9 +9819,9 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, Qualifiers ToQs = CToTy.getQualifiers(); if (FromQs.getObjCLifetime() != ToQs.getObjCLifetime()) { S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_arc_conv) - << (unsigned) FnKind << FnDesc - << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) - << FromTy << ToTy << (unsigned) isObjectArgument << I+1; + << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second + << FnDesc << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) + << FromTy << ToTy << (unsigned)isObjectArgument << I + 1; MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); return; } @@ -9656,10 +9833,10 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, // Emit the generic diagnostic and, optionally, add the hints to it. PartialDiagnostic FDiag = S.PDiag(diag::note_ovl_candidate_bad_conv); - FDiag << (unsigned) FnKind << FnDesc - << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) - << FromTy << ToTy << (unsigned) isObjectArgument << I + 1 - << (unsigned) (Cand->Fix.Kind); + FDiag << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc + << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy + << ToTy << (unsigned)isObjectArgument << I + 1 + << (unsigned)(Cand->Fix.Kind); // If we can fix the conversion, suggest the FixIts. for (std::vector<FixItHint>::iterator HI = Cand->Fix.Hints.begin(), @@ -9732,17 +9909,18 @@ static void DiagnoseArityMismatch(Sema &S, NamedDecl *Found, Decl *D, } std::string Description; - OverloadCandidateKind FnKind = + std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair = ClassifyOverloadCandidate(S, Found, Fn, Description); if (modeCount == 1 && Fn->getParamDecl(0)->getDeclName()) S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity_one) - << (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != nullptr) - << mode << Fn->getParamDecl(0) << NumFormalArgs; + << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second + << Description << mode << Fn->getParamDecl(0) << NumFormalArgs; else S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity) - << (unsigned) FnKind << (Fn->getDescribedFunctionTemplate() != nullptr) - << mode << modeCount << NumFormalArgs; + << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second + << Description << mode << modeCount << NumFormalArgs; + MaybeEmitInheritedConstructorNote(S, Found); } @@ -9783,6 +9961,17 @@ static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated, return; } + case Sema::TDK_IncompletePack: { + assert(ParamD && "no parameter found for incomplete deduction result"); + S.Diag(Templated->getLocation(), + diag::note_ovl_candidate_incomplete_deduction_pack) + << ParamD->getDeclName() + << (DeductionFailure.getFirstArg()->pack_size() + 1) + << *DeductionFailure.getFirstArg(); + MaybeEmitInheritedConstructorNote(S, Found); + return; + } + case Sema::TDK_Underqualified: { assert(ParamD && "no parameter found for bad qualifiers deduction result"); TemplateTypeParmDecl *TParam = cast<TemplateTypeParmDecl>(ParamD); @@ -10017,11 +10206,13 @@ static void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) { CalleeTarget = S.IdentifyCUDATarget(Callee); std::string FnDesc; - OverloadCandidateKind FnKind = + std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair = ClassifyOverloadCandidate(S, Cand->FoundDecl, Callee, FnDesc); S.Diag(Callee->getLocation(), diag::note_ovl_candidate_bad_target) - << (unsigned)FnKind << CalleeTarget << CallerTarget; + << (unsigned)FnKindPair.first << (unsigned)ocs_non_template + << FnDesc /* Ignored */ + << CalleeTarget << CallerTarget; // This could be an implicit constructor for which we could not infer the // target due to a collsion. Diagnose that case. @@ -10030,7 +10221,7 @@ static void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) { CXXRecordDecl *ParentClass = Meth->getParent(); Sema::CXXSpecialMember CSM; - switch (FnKind) { + switch (FnKindPair.first) { default: return; case oc_implicit_default_constructor: @@ -10102,12 +10293,12 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, if (Cand->Viable) { if (Fn->isDeleted() || S.isFunctionConsideredUnavailable(Fn)) { std::string FnDesc; - OverloadCandidateKind FnKind = - ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn, FnDesc); + std::pair<OverloadCandidateKind, OverloadCandidateSelect> FnKindPair = + ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn, FnDesc); S.Diag(Fn->getLocation(), diag::note_ovl_candidate_deleted) - << FnKind << FnDesc - << (Fn->isDeleted() ? (Fn->isDeletedAsWritten() ? 1 : 2) : 0); + << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc + << (Fn->isDeleted() ? (Fn->isDeletedAsWritten() ? 1 : 2) : 0); MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); return; } @@ -10176,6 +10367,9 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand, assert(!Available); break; } + case ovl_non_default_multiversion_function: + // Do nothing, these should simply be ignored. + break; } } @@ -10257,6 +10451,7 @@ static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) { case Sema::TDK_Invalid: case Sema::TDK_Incomplete: + case Sema::TDK_IncompletePack: return 1; case Sema::TDK_Underqualified: @@ -10493,9 +10688,8 @@ static void CompleteNonViableCandidate(Sema &S, OverloadCandidate *Cand, } } -/// PrintOverloadCandidates - When overload resolution fails, prints -/// diagnostic messages containing the candidates in the candidate -/// set. +/// When overload resolution fails, prints diagnostic messages containing the +/// candidates in the candidate set. void OverloadCandidateSet::NoteCandidates( Sema &S, OverloadCandidateDisplayKind OCD, ArrayRef<Expr *> Args, StringRef Opc, SourceLocation OpLoc, @@ -10642,8 +10836,8 @@ void TemplateSpecCandidateSet::NoteCandidates(Sema &S, SourceLocation Loc) { // in general, want to list every possible builtin candidate. } - std::sort(Cands.begin(), Cands.end(), - CompareTemplateSpecCandidatesForDisplay(S)); + llvm::sort(Cands.begin(), Cands.end(), + CompareTemplateSpecCandidatesForDisplay(S)); // FIXME: Perhaps rename OverloadsShown and getShowOverloads() // for generalization purposes (?). @@ -10912,6 +11106,11 @@ private: if (FunctionDecl *Caller = dyn_cast<FunctionDecl>(S.CurContext)) if (!Caller->isImplicit() && !S.IsAllowedCUDACall(Caller, FunDecl)) return false; + if (FunDecl->isMultiVersion()) { + const auto *TA = FunDecl->getAttr<TargetAttr>(); + if (TA && !TA->isDefaultVersion()) + return false; + } // If any candidate has a placeholder return type, trigger its deduction // now. @@ -10993,9 +11192,9 @@ private: MatchesCopy.begin(), MatchesCopy.end(), FailedCandidates, SourceExpr->getLocStart(), S.PDiag(), S.PDiag(diag::err_addr_ovl_ambiguous) - << Matches[0].second->getDeclName(), + << Matches[0].second->getDeclName(), S.PDiag(diag::note_ovl_candidate) - << (unsigned)oc_function_template, + << (unsigned)oc_function << (unsigned)ocs_described_template, Complain, TargetFunctionType); if (Result != MatchesCopy.end()) { @@ -11157,7 +11356,7 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr, return Fn; } -/// \brief Given an expression that refers to an overloaded function, try to +/// Given an expression that refers to an overloaded function, try to /// resolve that function to a single function that can have its address taken. /// This will modify `Pair` iff it returns non-null. /// @@ -11193,7 +11392,7 @@ Sema::resolveAddressOfOnlyViableOverloadCandidate(Expr *E, return Result; } -/// \brief Given an overloaded function, tries to turn it into a non-overloaded +/// Given an overloaded function, tries to turn it into a non-overloaded /// function reference using resolveAddressOfOnlyViableOverloadCandidate. This /// will perform access checks, diagnose the use of the resultant decl, and, if /// requested, potentially perform a function-to-pointer decay. @@ -11207,7 +11406,8 @@ bool Sema::resolveAndFixAddressOfOnlyViableOverloadCandidate( DeclAccessPair DAP; FunctionDecl *Found = resolveAddressOfOnlyViableOverloadCandidate(E, DAP); - if (!Found) + if (!Found || Found->isCPUDispatchMultiVersion() || + Found->isCPUSpecificMultiVersion()) return false; // Emitting multiple diagnostics for a function that is both inaccessible and @@ -11223,7 +11423,7 @@ bool Sema::resolveAndFixAddressOfOnlyViableOverloadCandidate( return true; } -/// \brief Given an expression that refers to an overloaded function, try to +/// 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 @@ -11309,9 +11509,6 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, return Matched; } - - - // Resolve and fix an overloaded expression that can be resolved // because it identifies a single function template specialization. // @@ -11395,7 +11592,7 @@ bool Sema::ResolveAndFixSingleFunctionTemplateSpecialization( return true; } -/// \brief Add a single candidate to the overload set. +/// Add a single candidate to the overload set. static void AddOverloadedCallCandidate(Sema &S, DeclAccessPair FoundDecl, TemplateArgumentListInfo *ExplicitTemplateArgs, @@ -11434,7 +11631,7 @@ static void AddOverloadedCallCandidate(Sema &S, assert(!KnownValid && "unhandled case in overloaded call candidate"); } -/// \brief Add the overload candidates named by callee and/or found by argument +/// Add the overload candidates named by callee and/or found by argument /// dependent lookup to the given overload set. void Sema::AddOverloadedCallCandidates(UnresolvedLookupExpr *ULE, ArrayRef<Expr *> Args, @@ -11726,7 +11923,7 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, RParenLoc); } -/// \brief Constructs and populates an OverloadedCandidateSet from +/// Constructs and populates an OverloadedCandidateSet from /// the given function. /// \returns true when an the ExprResult output parameter has been set. bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn, @@ -11866,7 +12063,7 @@ static ExprResult FinishOverloadedCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, << Fn->getSourceRange(); CandidateSet->NoteCandidates(SemaRef, OCD_AllCandidates, Args); - // We emitted an error for the unvailable/deleted function call but keep + // We emitted an error for the unavailable/deleted function call but keep // the call in the AST. FunctionDecl *FDecl = (*Best)->Function; Fn = SemaRef.FixOverloadedFunctionReference(Fn, (*Best)->FoundDecl, FDecl); @@ -11932,7 +12129,7 @@ static bool IsOverloaded(const UnresolvedSetImpl &Functions) { (Functions.size() == 1 && isa<FunctionTemplateDecl>(*Functions.begin())); } -/// \brief Create a unary operation that may resolve to an overloaded +/// Create a unary operation that may resolve to an overloaded /// operator. /// /// \param OpLoc The location of the operator itself (e.g., '*'). @@ -11978,7 +12175,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, if (Input->isTypeDependent()) { if (Fns.empty()) return new (Context) UnaryOperator(Input, Opc, Context.DependentTy, - VK_RValue, OK_Ordinary, OpLoc); + VK_RValue, OK_Ordinary, OpLoc, false); CXXRecordDecl *NamingClass = nullptr; // lookup ignores member operators UnresolvedLookupExpr *Fn @@ -12077,7 +12274,8 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, // break out so that we will build the appropriate built-in // operator node. ExprResult InputRes = PerformImplicitConversion( - Input, Best->BuiltinParamTypes[0], Best->Conversions[0], AA_Passing); + Input, Best->BuiltinParamTypes[0], Best->Conversions[0], AA_Passing, + CCK_ForBuiltinOverloadedOp); if (InputRes.isInvalid()) return ExprError(); Input = InputRes.get(); @@ -12123,7 +12321,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, return CreateBuiltinUnaryOp(OpLoc, Opc, Input); } -/// \brief Create a binary operation that may resolve to an overloaded +/// Create a binary operation that may resolve to an overloaded /// operator. /// /// \param OpLoc The location of the operator itself (e.g., '+'). @@ -12321,16 +12519,16 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, // We matched a built-in operator. Convert the arguments, then // break out so that we will build the appropriate built-in // operator node. - ExprResult ArgsRes0 = - PerformImplicitConversion(Args[0], Best->BuiltinParamTypes[0], - Best->Conversions[0], AA_Passing); + ExprResult ArgsRes0 = PerformImplicitConversion( + Args[0], Best->BuiltinParamTypes[0], Best->Conversions[0], + AA_Passing, CCK_ForBuiltinOverloadedOp); if (ArgsRes0.isInvalid()) return ExprError(); Args[0] = ArgsRes0.get(); - ExprResult ArgsRes1 = - PerformImplicitConversion(Args[1], Best->BuiltinParamTypes[1], - Best->Conversions[1], AA_Passing); + ExprResult ArgsRes1 = PerformImplicitConversion( + Args[1], Best->BuiltinParamTypes[1], Best->Conversions[1], + AA_Passing, CCK_ForBuiltinOverloadedOp); if (ArgsRes1.isInvalid()) return ExprError(); Args[1] = ArgsRes1.get(); @@ -12346,7 +12544,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, if (Opc == BO_Comma) break; - // For class as left operand for assignment or compound assigment + // For class as left operand for assignment or compound assignment // operator do not fall through to handling in built-in, but report that // no overloaded assignment operator found ExprResult Result = ExprError(); @@ -12533,16 +12731,16 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc, // We matched a built-in operator. Convert the arguments, then // break out so that we will build the appropriate built-in // operator node. - ExprResult ArgsRes0 = - PerformImplicitConversion(Args[0], Best->BuiltinParamTypes[0], - Best->Conversions[0], AA_Passing); + ExprResult ArgsRes0 = PerformImplicitConversion( + Args[0], Best->BuiltinParamTypes[0], Best->Conversions[0], + AA_Passing, CCK_ForBuiltinOverloadedOp); if (ArgsRes0.isInvalid()) return ExprError(); Args[0] = ArgsRes0.get(); - ExprResult ArgsRes1 = - PerformImplicitConversion(Args[1], Best->BuiltinParamTypes[1], - Best->Conversions[1], AA_Passing); + ExprResult ArgsRes1 = PerformImplicitConversion( + Args[1], Best->BuiltinParamTypes[1], Best->Conversions[1], + AA_Passing, CCK_ForBuiltinOverloadedOp); if (ArgsRes1.isInvalid()) return ExprError(); Args[1] = ArgsRes1.get(); @@ -13508,7 +13706,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, return new (Context) UnaryOperator(SubExpr, UO_AddrOf, MemPtrType, VK_RValue, OK_Ordinary, - UnOp->getOperatorLoc()); + UnOp->getOperatorLoc(), false); } } Expr *SubExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), @@ -13519,7 +13717,7 @@ Expr *Sema::FixOverloadedFunctionReference(Expr *E, DeclAccessPair Found, return new (Context) UnaryOperator(SubExpr, UO_AddrOf, Context.getPointerType(SubExpr->getType()), VK_RValue, OK_Ordinary, - UnOp->getOperatorLoc()); + UnOp->getOperatorLoc(), false); } // C++ [except.spec]p17: |