diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExpr.cpp | 14 | ||||
-rw-r--r-- | clang/lib/Parse/ParseExprCXX.cpp | 15 | ||||
-rw-r--r-- | clang/lib/Sema/SemaCodeComplete.cpp | 226 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 57 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateDeduction.cpp | 26 |
6 files changed, 224 insertions, 120 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 1ee243155ab..8fcfcb34be2 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -1993,7 +1993,11 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( Actions.ActOnCXXEnterDeclInitializer(getCurScope(), ThisDecl); } - if (ParseExpressionList(Exprs, CommaLocs)) { + if (ParseExpressionList(Exprs, CommaLocs, [&] { + Actions.CodeCompleteConstructor(getCurScope(), + cast<VarDecl>(ThisDecl)->getType()->getCanonicalTypeInternal(), + ThisDecl->getLocation(), Exprs); + })) { Actions.ActOnInitializerError(ThisDecl); SkipUntil(tok::r_paren, StopAtSemi); diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index 4c83bd8a77b..6e4ba768d96 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -1454,8 +1454,9 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { if (OpKind == tok::l_paren || !LHS.isInvalid()) { if (Tok.isNot(tok::r_paren)) { - if (ParseExpressionList(ArgExprs, CommaLocs, &Sema::CodeCompleteCall, - LHS.get())) { + if (ParseExpressionList(ArgExprs, CommaLocs, [&] { + Actions.CodeCompleteCall(getCurScope(), LHS.get(), ArgExprs); + })) { (void)Actions.CorrectDelayedTyposInExpr(LHS); LHS = ExprError(); } @@ -2506,17 +2507,14 @@ ExprResult Parser::ParseFoldExpression(ExprResult LHS, /// [C++0x] assignment-expression /// [C++0x] braced-init-list /// \endverbatim -bool Parser::ParseExpressionList(SmallVectorImpl<Expr*> &Exprs, +bool Parser::ParseExpressionList(SmallVectorImpl<Expr *> &Exprs, SmallVectorImpl<SourceLocation> &CommaLocs, - void (Sema::*Completer)(Scope *S, - Expr *Data, - ArrayRef<Expr *> Args), - Expr *Data) { + std::function<void()> Completer) { bool SawError = false; while (1) { if (Tok.is(tok::code_completion)) { if (Completer) - (Actions.*Completer)(getCurScope(), Data, Exprs); + Completer(); else Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression); cutOffParsing(); diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 751a90ae71d..422b486c7b2 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -1597,7 +1597,11 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { CommaLocsTy CommaLocs; if (Tok.isNot(tok::r_paren)) { - if (ParseExpressionList(Exprs, CommaLocs)) { + if (ParseExpressionList(Exprs, CommaLocs, [&] { + Actions.CodeCompleteConstructor(getCurScope(), + TypeRep.get()->getCanonicalTypeInternal(), + DS.getLocEnd(), Exprs); + })) { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } @@ -2668,7 +2672,14 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { ConstructorLParen = T.getOpenLocation(); if (Tok.isNot(tok::r_paren)) { CommaLocsTy CommaLocs; - if (ParseExpressionList(ConstructorArgs, CommaLocs)) { + if (ParseExpressionList(ConstructorArgs, CommaLocs, [&] { + ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(), + DeclaratorInfo).get(); + Actions.CodeCompleteConstructor(getCurScope(), + TypeRep.get()->getCanonicalTypeInternal(), + DeclaratorInfo.getLocEnd(), + ConstructorArgs); + })) { SkipUntil(tok::semi, StopAtSemi | StopBeforeMatch); return ExprError(); } diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 384972bc728..b3059d58871 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -3819,7 +3819,73 @@ static bool anyNullArguments(ArrayRef<Expr *> Args) { return false; } -void Sema::CodeCompleteCall(Scope *S, Expr *FnIn, ArrayRef<Expr *> Args) { +typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate; + +void mergeCandidatesWithResults(Sema &SemaRef, + SmallVectorImpl<ResultCandidate> &Results, + OverloadCandidateSet &CandidateSet, + SourceLocation Loc) { + if (!CandidateSet.empty()) { + // Sort the overload candidate set by placing the best overloads first. + std::stable_sort( + CandidateSet.begin(), CandidateSet.end(), + [&](const OverloadCandidate &X, const OverloadCandidate &Y) { + return isBetterOverloadCandidate(SemaRef, X, Y, Loc); + }); + + // Add the remaining viable overload candidates as code-completion results. + for (auto &Candidate : CandidateSet) + if (Candidate.Viable) + Results.push_back(ResultCandidate(Candidate.Function)); + } +} + +/// \brief Get the type of the Nth parameter from a given set of overload +/// candidates. +QualType getParamType(Sema &SemaRef, ArrayRef<ResultCandidate> Candidates, + unsigned N) { + + // Given the overloads 'Candidates' for a function call matching all arguments + // up to N, return the type of the Nth parameter if it is the same for all + // overload candidates. + QualType ParamType; + for (auto &Candidate : Candidates) { + if (auto FType = Candidate.getFunctionType()) + if (auto Proto = dyn_cast<FunctionProtoType>(FType)) + if (N < Proto->getNumParams()) { + if (ParamType.isNull()) + ParamType = Proto->getParamType(N); + else if (!SemaRef.Context.hasSameUnqualifiedType( + ParamType.getNonReferenceType(), + Proto->getParamType(N).getNonReferenceType())) + // Otherwise return a default-constructed QualType. + return QualType(); + } + } + + return ParamType; +} + +void CodeCompleteOverloadResults(Sema &SemaRef, Scope *S, + MutableArrayRef<ResultCandidate> Candidates, + unsigned CurrentArg, + bool CompleteExpressionWithCurrentArg = true) { + QualType ParamType; + if (CompleteExpressionWithCurrentArg) + ParamType = getParamType(SemaRef, Candidates, CurrentArg); + + if (ParamType.isNull()) + SemaRef.CodeCompleteOrdinaryName(S, Sema::PCC_Expression); + else + SemaRef.CodeCompleteExpression(S, ParamType); + + if (!Candidates.empty()) + SemaRef.CodeCompleter->ProcessOverloadCandidates(SemaRef, CurrentArg, + Candidates.data(), + Candidates.size()); +} + +void Sema::CodeCompleteCall(Scope *S, Expr *Fn, ArrayRef<Expr *> Args) { if (!CodeCompleter) return; @@ -3828,7 +3894,8 @@ void Sema::CodeCompleteCall(Scope *S, Expr *FnIn, ArrayRef<Expr *> Args) { // results. We may want to revisit this strategy in the future, // e.g., by merging the two kinds of results. - Expr *Fn = (Expr *)FnIn; + // FIXME: Provide support for highlighting optional parameters. + // FIXME: Provide support for variadic template functions. // Ignore type-dependent call expressions entirely. if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) || @@ -3841,92 +3908,99 @@ void Sema::CodeCompleteCall(Scope *S, Expr *FnIn, ArrayRef<Expr *> Args) { SourceLocation Loc = Fn->getExprLoc(); OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal); - // FIXME: What if we're calling something that isn't a function declaration? - // FIXME: What if we're calling a pseudo-destructor? - // FIXME: What if we're calling a member function? - - typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate; SmallVector<ResultCandidate, 8> Results; Expr *NakedFn = Fn->IgnoreParenCasts(); - if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn)) + if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn)) AddOverloadedCallCandidates(ULE, Args, CandidateSet, - /*PartialOverloading=*/ true); - else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) { - FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl()); - if (FDecl) { + /*PartialOverloading=*/true); + else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) { + TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr; + if (UME->hasExplicitTemplateArgs()) { + UME->copyTemplateArgumentsInto(TemplateArgsBuffer); + TemplateArgs = &TemplateArgsBuffer; + } + SmallVector<Expr *, 12> ArgExprs(1, UME->getBase()); + ArgExprs.append(Args.begin(), Args.end()); + UnresolvedSet<8> Decls; + Decls.append(UME->decls_begin(), UME->decls_end()); + AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs, + /*SuppressUsedConversions=*/false, + /*PartialOverloading=*/true); + } else if (auto DC = NakedFn->getType()->getCanonicalTypeInternal() + ->getAsCXXRecordDecl()) { + // If it's a CXXRecordDecl, it may overload the function call operator, + // so we check if it does and add them as candidates. + DeclarationName OpName = Context.DeclarationNames + .getCXXOperatorName(OO_Call); + LookupResult R(*this, OpName, Loc, LookupOrdinaryName); + LookupQualifiedName(R, DC); + R.suppressDiagnostics(); + SmallVector<Expr *, 12> ArgExprs(1, NakedFn); + ArgExprs.append(Args.begin(), Args.end()); + AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet, + /*ExplicitArgs=*/nullptr, + /*SuppressUsedConversions=*/false, + /*PartialOverloading=*/true); + } else { + // Lastly we check, as a possibly resolved expression, whether it can be + // converted to a function. + FunctionDecl *FD = nullptr; + if (auto MCE = dyn_cast<MemberExpr>(NakedFn)) + FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl()); + else if (auto DRE = dyn_cast<DeclRefExpr>(NakedFn)) + FD = dyn_cast<FunctionDecl>(DRE->getDecl()); + if (FD) { if (!getLangOpts().CPlusPlus || - !FDecl->getType()->getAs<FunctionProtoType>()) - Results.push_back(ResultCandidate(FDecl)); + !FD->getType()->getAs<FunctionProtoType>()) + Results.push_back(ResultCandidate(FD)); else - // FIXME: access? - AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), Args, - CandidateSet, false, /*PartialOverloading*/true); + AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()), + Args, CandidateSet, + /*SuppressUsedConversions=*/false, + /*PartialOverloading=*/true); } } - - QualType ParamType; - - if (!CandidateSet.empty()) { - // Sort the overload candidate set by placing the best overloads first. - std::stable_sort( - CandidateSet.begin(), CandidateSet.end(), - [&](const OverloadCandidate &X, const OverloadCandidate &Y) { - return isBetterOverloadCandidate(*this, X, Y, Loc); - }); - // Add the remaining viable overload candidates as code-completion reslults. - for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(), - CandEnd = CandidateSet.end(); - Cand != CandEnd; ++Cand) { - if (Cand->Viable) - Results.push_back(ResultCandidate(Cand->Function)); - } - - // From the viable candidates, try to determine the type of this parameter. - for (unsigned I = 0, N = Results.size(); I != N; ++I) { - if (const FunctionType *FType = Results[I].getFunctionType()) - if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType)) - if (Args.size() < Proto->getNumParams()) { - if (ParamType.isNull()) - ParamType = Proto->getParamType(Args.size()); - else if (!Context.hasSameUnqualifiedType( - ParamType.getNonReferenceType(), - Proto->getParamType(Args.size()) - .getNonReferenceType())) { - ParamType = QualType(); - break; - } - } - } - } else { - // Try to determine the parameter type from the type of the expression - // being called. - QualType FunctionType = Fn->getType(); - if (const PointerType *Ptr = FunctionType->getAs<PointerType>()) - FunctionType = Ptr->getPointeeType(); - else if (const BlockPointerType *BlockPtr - = FunctionType->getAs<BlockPointerType>()) - FunctionType = BlockPtr->getPointeeType(); - else if (const MemberPointerType *MemPtr - = FunctionType->getAs<MemberPointerType>()) - FunctionType = MemPtr->getPointeeType(); - - if (const FunctionProtoType *Proto - = FunctionType->getAs<FunctionProtoType>()) { - if (Args.size() < Proto->getNumParams()) - ParamType = Proto->getParamType(Args.size()); + mergeCandidatesWithResults(*this, Results, CandidateSet, Loc); + CodeCompleteOverloadResults(*this, S, Results, Args.size(), + !CandidateSet.empty()); +} + +void Sema::CodeCompleteConstructor(Scope *S, QualType Type, SourceLocation Loc, + ArrayRef<Expr *> Args) { + if (!CodeCompleter) + return; + + // A complete type is needed to lookup for constructors. + if (RequireCompleteType(Loc, Type, 0)) + return; + + // FIXME: Provide support for member initializers. + // FIXME: Provide support for variadic template constructors. + // FIXME: Provide support for highlighting optional parameters. + + OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal); + + for (auto C : LookupConstructors(Type->getAsCXXRecordDecl())) { + if (auto FD = dyn_cast<FunctionDecl>(C)) { + AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), + Args, CandidateSet, + /*SuppressUsedConversions=*/false, + /*PartialOverloading=*/true); + } else if (auto FTD = dyn_cast<FunctionTemplateDecl>(C)) { + AddTemplateOverloadCandidate(FTD, + DeclAccessPair::make(FTD, C->getAccess()), + /*ExplicitTemplateArgs=*/nullptr, + Args, CandidateSet, + /*SuppressUsedConversions=*/false, + /*PartialOverloading=*/true); } } - if (ParamType.isNull()) - CodeCompleteOrdinaryName(S, PCC_Expression); - else - CodeCompleteExpression(S, ParamType); - - if (!Results.empty()) - CodeCompleter->ProcessOverloadCandidates(*this, Args.size(), Results.data(), - Results.size()); + SmallVector<ResultCandidate, 8> Results; + mergeCandidatesWithResults(*this, Results, CandidateSet, Loc); + CodeCompleteOverloadResults(*this, S, Results, Args.size()); } void Sema::CodeCompleteInitializer(Scope *S, Decl *D) { diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 9195ee59075..75a511403d2 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -5554,7 +5554,8 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, // is irrelevant. AddMethodCandidate(Method, FoundDecl, Method->getParent(), QualType(), Expr::Classification::makeSimpleLValue(), - Args, CandidateSet, SuppressUserConversions); + Args, CandidateSet, SuppressUserConversions, + PartialOverloading); return; } // We treat a constructor like a non-member function, since its object @@ -5615,7 +5616,7 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, // (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 ((Args.size() + (PartialOverloading && Args.size())) > NumParams && + if (TooManyArguments(NumParams, Args.size(), PartialOverloading) && !Proto->isVariadic()) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_too_many_arguments; @@ -5850,8 +5851,9 @@ EnableIfAttr *Sema::CheckEnableIf(FunctionDecl *Function, ArrayRef<Expr *> Args, void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, + TemplateArgumentListInfo *ExplicitTemplateArgs, bool SuppressUserConversions, - TemplateArgumentListInfo *ExplicitTemplateArgs) { + bool PartialOverloading) { for (UnresolvedSetIterator F = Fns.begin(), E = Fns.end(); F != E; ++F) { NamedDecl *D = F.getDecl()->getUnderlyingDecl(); if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { @@ -5860,10 +5862,10 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, cast<CXXMethodDecl>(FD)->getParent(), Args[0]->getType(), Args[0]->Classify(Context), Args.slice(1), CandidateSet, - SuppressUserConversions); + SuppressUserConversions, PartialOverloading); else AddOverloadCandidate(FD, F.getPair(), Args, CandidateSet, - SuppressUserConversions); + SuppressUserConversions, PartialOverloading); } else { FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(D); if (isa<CXXMethodDecl>(FunTmpl->getTemplatedDecl()) && @@ -5873,11 +5875,13 @@ void Sema::AddFunctionCandidates(const UnresolvedSetImpl &Fns, ExplicitTemplateArgs, Args[0]->getType(), Args[0]->Classify(Context), Args.slice(1), - CandidateSet, SuppressUserConversions); + CandidateSet, SuppressUserConversions, + PartialOverloading); else AddTemplateOverloadCandidate(FunTmpl, F.getPair(), ExplicitTemplateArgs, Args, - CandidateSet, SuppressUserConversions); + CandidateSet, SuppressUserConversions, + PartialOverloading); } } } @@ -5925,7 +5929,8 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, Expr::Classification ObjectClassification, ArrayRef<Expr *> Args, OverloadCandidateSet &CandidateSet, - bool SuppressUserConversions) { + bool SuppressUserConversions, + bool PartialOverloading) { const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(Method->getType()->getAs<FunctionType>()); assert(Proto && "Methods without a prototype cannot be overloaded"); @@ -5958,7 +5963,8 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, // (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 (Args.size() > NumParams && !Proto->isVariadic()) { + if (TooManyArguments(NumParams, Args.size(), PartialOverloading) && + !Proto->isVariadic()) { Candidate.Viable = false; Candidate.FailureKind = ovl_fail_too_many_arguments; return; @@ -5970,7 +5976,7 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, // parameter list is truncated on the right, so that there are // exactly m parameters. unsigned MinRequiredArgs = Method->getMinRequiredArguments(); - if (Args.size() < MinRequiredArgs) { + if (Args.size() < MinRequiredArgs && !PartialOverloading) { // Not enough arguments. Candidate.Viable = false; Candidate.FailureKind = ovl_fail_too_few_arguments; @@ -6052,7 +6058,8 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, Expr::Classification ObjectClassification, ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, - bool SuppressUserConversions) { + bool SuppressUserConversions, + bool PartialOverloading) { if (!CandidateSet.isNewCandidate(MethodTmpl)) return; @@ -6069,7 +6076,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, FunctionDecl *Specialization = nullptr; if (TemplateDeductionResult Result = DeduceTemplateArguments(MethodTmpl, ExplicitTemplateArgs, Args, - Specialization, Info)) { + Specialization, Info, PartialOverloading)) { OverloadCandidate &Candidate = CandidateSet.addCandidate(); Candidate.FoundDecl = FoundDecl; Candidate.Function = MethodTmpl->getTemplatedDecl(); @@ -6090,7 +6097,7 @@ Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, "Specialization is not a member function?"); AddMethodCandidate(cast<CXXMethodDecl>(Specialization), FoundDecl, ActingContext, ObjectType, ObjectClassification, Args, - CandidateSet, SuppressUserConversions); + CandidateSet, SuppressUserConversions, PartialOverloading); } /// \brief Add a C++ function template specialization as a candidate @@ -6102,7 +6109,8 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args, OverloadCandidateSet& CandidateSet, - bool SuppressUserConversions) { + bool SuppressUserConversions, + bool PartialOverloading) { if (!CandidateSet.isNewCandidate(FunctionTemplate)) return; @@ -6119,7 +6127,7 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, FunctionDecl *Specialization = nullptr; if (TemplateDeductionResult Result = DeduceTemplateArguments(FunctionTemplate, ExplicitTemplateArgs, Args, - Specialization, Info)) { + Specialization, Info, PartialOverloading)) { OverloadCandidate &Candidate = CandidateSet.addCandidate(); Candidate.FoundDecl = FoundDecl; Candidate.Function = FunctionTemplate->getTemplatedDecl(); @@ -6137,7 +6145,7 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, // deduction as a candidate. assert(Specialization && "Missing function template specialization?"); AddOverloadCandidate(Specialization, FoundDecl, Args, CandidateSet, - SuppressUserConversions); + SuppressUserConversions, PartialOverloading); } /// Determine whether this is an allowable conversion from the result @@ -8291,7 +8299,7 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, } else AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*I), FoundDecl, ExplicitTemplateArgs, - Args, CandidateSet); + Args, CandidateSet, PartialOverloading); } } @@ -10363,7 +10371,8 @@ static void AddOverloadedCallCandidate(Sema &S, assert(!KnownValid && "Explicit template arguments?"); return; } - S.AddOverloadCandidate(Func, FoundDecl, Args, CandidateSet, false, + S.AddOverloadCandidate(Func, FoundDecl, Args, CandidateSet, + /*SuppressUsedConversions=*/false, PartialOverloading); return; } @@ -10371,7 +10380,9 @@ static void AddOverloadedCallCandidate(Sema &S, if (FunctionTemplateDecl *FuncTemplate = dyn_cast<FunctionTemplateDecl>(Callee)) { S.AddTemplateOverloadCandidate(FuncTemplate, FoundDecl, - ExplicitTemplateArgs, Args, CandidateSet); + ExplicitTemplateArgs, Args, CandidateSet, + /*SuppressUsedConversions=*/false, + PartialOverloading); return; } @@ -10896,7 +10907,7 @@ Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc, unsigned OpcIn, OverloadCandidateSet CandidateSet(OpLoc, OverloadCandidateSet::CSK_Operator); // Add the candidates from the given function set. - AddFunctionCandidates(Fns, ArgsArray, CandidateSet, false); + AddFunctionCandidates(Fns, ArgsArray, CandidateSet); // Add operator candidates that are member functions. AddMemberOperatorCandidates(Op, OpLoc, ArgsArray, CandidateSet); @@ -11105,7 +11116,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc, OverloadCandidateSet CandidateSet(OpLoc, OverloadCandidateSet::CSK_Operator); // Add the candidates from the given function set. - AddFunctionCandidates(Fns, Args, CandidateSet, false); + AddFunctionCandidates(Fns, Args, CandidateSet); // Add operator candidates that are member functions. AddMemberOperatorCandidates(Op, OpLoc, Args, CandidateSet); @@ -12154,8 +12165,8 @@ ExprResult Sema::BuildLiteralOperatorCall(LookupResult &R, OverloadCandidateSet CandidateSet(UDSuffixLoc, OverloadCandidateSet::CSK_Normal); - AddFunctionCandidates(R.asUnresolvedSet(), Args, CandidateSet, true, - TemplateArgs); + AddFunctionCandidates(R.asUnresolvedSet(), Args, CandidateSet, TemplateArgs, + /*SuppressUserConversions=*/true); bool HadMultipleCandidates = (CandidateSet.size() > 1); diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 90384f0b0a9..89b04798265 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -2784,7 +2784,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, unsigned NumExplicitlySpecified, FunctionDecl *&Specialization, TemplateDeductionInfo &Info, - SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs) { + SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs, + bool PartialOverloading) { TemplateParameterList *TemplateParams = FunctionTemplate->getTemplateParameters(); @@ -2911,6 +2912,8 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate, const_cast<NamedDecl *>(TemplateParams->getParam(I))); Info.reset(TemplateArgumentList::CreateCopy(Context, Builder.data(), Builder.size())); + if (PartialOverloading) break; + return HasDefaultArg ? TDK_SubstitutionFailure : TDK_Incomplete; } @@ -3285,26 +3288,28 @@ DeduceTemplateArgumentByListElement(Sema &S, Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( FunctionTemplateDecl *FunctionTemplate, TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args, - FunctionDecl *&Specialization, TemplateDeductionInfo &Info) { + FunctionDecl *&Specialization, TemplateDeductionInfo &Info, + bool PartialOverloading) { if (FunctionTemplate->isInvalidDecl()) return TDK_Invalid; FunctionDecl *Function = FunctionTemplate->getTemplatedDecl(); + unsigned NumParams = Function->getNumParams(); // C++ [temp.deduct.call]p1: // Template argument deduction is done by comparing each function template // parameter type (call it P) with the type of the corresponding argument // of the call (call it A) as described below. unsigned CheckArgs = Args.size(); - if (Args.size() < Function->getMinRequiredArguments()) + if (Args.size() < Function->getMinRequiredArguments() && !PartialOverloading) return TDK_TooFewArguments; - else if (Args.size() > Function->getNumParams()) { + else if (TooManyArguments(NumParams, Args.size(), PartialOverloading)) { const FunctionProtoType *Proto = Function->getType()->getAs<FunctionProtoType>(); if (Proto->isTemplateVariadic()) /* Do nothing */; else if (Proto->isVariadic()) - CheckArgs = Function->getNumParams(); + CheckArgs = NumParams; else return TDK_TooManyArguments; } @@ -3331,7 +3336,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( NumExplicitlySpecified = Deduced.size(); } else { // Just fill in the parameter types from the function declaration. - for (unsigned I = 0, N = Function->getNumParams(); I != N; ++I) + for (unsigned I = 0; I != NumParams; ++I) ParamTypes.push_back(Function->getParamDecl(I)->getType()); } @@ -3339,8 +3344,8 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( Deduced.resize(TemplateParams->size()); unsigned ArgIdx = 0; SmallVector<OriginalCallArg, 4> OriginalCallArgs; - for (unsigned ParamIdx = 0, NumParams = ParamTypes.size(); - ParamIdx != NumParams; ++ParamIdx) { + for (unsigned ParamIdx = 0, NumParamTypes = ParamTypes.size(); + ParamIdx != NumParamTypes; ++ParamIdx) { QualType OrigParamType = ParamTypes[ParamIdx]; QualType ParamType = OrigParamType; @@ -3409,7 +3414,7 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( // the function parameter pack. For a function parameter pack that does // not occur at the end of the parameter-declaration-list, the type of // the parameter pack is a non-deduced context. - if (ParamIdx + 1 < NumParams) + if (ParamIdx + 1 < NumParamTypes) break; QualType ParamPattern = ParamExpansion->getPattern(); @@ -3479,7 +3484,8 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, NumExplicitlySpecified, Specialization, - Info, &OriginalCallArgs); + Info, &OriginalCallArgs, + PartialOverloading); } QualType Sema::adjustCCAndNoReturn(QualType ArgFunctionType, |