summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Parse/ParseDecl.cpp6
-rw-r--r--clang/lib/Parse/ParseExpr.cpp14
-rw-r--r--clang/lib/Parse/ParseExprCXX.cpp15
-rw-r--r--clang/lib/Sema/SemaCodeComplete.cpp226
-rw-r--r--clang/lib/Sema/SemaOverload.cpp57
-rw-r--r--clang/lib/Sema/SemaTemplateDeduction.cpp26
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,
OpenPOWER on IntegriCloud