diff options
| author | Douglas Gregor <dgregor@apple.com> | 2009-08-21 00:16:32 +0000 |
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2009-08-21 00:16:32 +0000 |
| commit | 97628d6a4ce229f2936d2b34231bb7dfa432f810 (patch) | |
| tree | 27be13699dc244a271a8fa07342c0a900a852a33 /clang/lib/Sema/SemaOverload.cpp | |
| parent | d5eaa05a7f307df355ff4dc3ba99f1df0a2eb581 (diff) | |
| download | bcm5719-llvm-97628d6a4ce229f2936d2b34231bb7dfa432f810.tar.gz bcm5719-llvm-97628d6a4ce229f2936d2b34231bb7dfa432f810.zip | |
Implement support for calling member function templates, which involves:
- Allowing one to name a member function template within a class
template and on the right-hand side of a member access expression.
- Template argument deduction for calls to member function templates.
- Registering specializations of member function templates (and
finding them later).
llvm-svn: 79581
Diffstat (limited to 'clang/lib/Sema/SemaOverload.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 87 |
1 files changed, 73 insertions, 14 deletions
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index d338e427c8d..df92634745b 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -2237,6 +2237,48 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, Expr *Object, } } +/// \brief Add a C++ member function template as a candidate to the candidate +/// set, using template argument deduction to produce an appropriate member +/// function template specialization. +void +Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, + bool HasExplicitTemplateArgs, + const TemplateArgument *ExplicitTemplateArgs, + unsigned NumExplicitTemplateArgs, + Expr *Object, Expr **Args, unsigned NumArgs, + OverloadCandidateSet& CandidateSet, + bool SuppressUserConversions, + bool ForceRValue) { + // C++ [over.match.funcs]p7: + // In each case where a candidate is a function template, candidate + // function template specializations are generated using template argument + // deduction (14.8.3, 14.8.2). Those candidates are then handled as + // candidate functions in the usual way.113) A given name can refer to one + // or more function templates and also to a set of overloaded non-template + // functions. In such a case, the candidate functions generated from each + // function template are combined with the set of non-template candidate + // functions. + TemplateDeductionInfo Info(Context); + FunctionDecl *Specialization = 0; + if (TemplateDeductionResult Result + = DeduceTemplateArguments(MethodTmpl, HasExplicitTemplateArgs, + ExplicitTemplateArgs, NumExplicitTemplateArgs, + Args, NumArgs, Specialization, Info)) { + // FIXME: Record what happened with template argument deduction, so + // that we can give the user a beautiful diagnostic. + (void)Result; + return; + } + + // Add the function template specialization produced by template argument + // deduction as a candidate. + assert(Specialization && "Missing member function template specialization?"); + assert(isa<CXXMethodDecl>(Specialization) && + "Specialization is not a member function?"); + AddMethodCandidate(cast<CXXMethodDecl>(Specialization), Object, Args, NumArgs, + CandidateSet, SuppressUserConversions, ForceRValue); +} + /// \brief Add a C++ function template as a candidate in the candidate set, /// using template argument deduction to produce an appropriate function /// template specialization. @@ -4276,19 +4318,36 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, Expr *ObjectArg = MemExpr->getBase(); CXXMethodDecl *Method = 0; - if (OverloadedFunctionDecl *Ovl - = dyn_cast<OverloadedFunctionDecl>(MemExpr->getMemberDecl())) { + if (isa<OverloadedFunctionDecl>(MemExpr->getMemberDecl()) || + isa<FunctionTemplateDecl>(MemExpr->getMemberDecl())) { // Add overload candidates OverloadCandidateSet CandidateSet; - for (OverloadedFunctionDecl::function_iterator Func = Ovl->function_begin(), - FuncEnd = Ovl->function_end(); - Func != FuncEnd; ++Func) { - assert(isa<CXXMethodDecl>(*Func) && "Function is not a method"); - Method = cast<CXXMethodDecl>(*Func); - AddMethodCandidate(Method, ObjectArg, Args, NumArgs, CandidateSet, - /*SuppressUserConversions=*/false); - } - + DeclarationName DeclName = MemExpr->getMemberDecl()->getDeclName(); + + if (OverloadedFunctionDecl *Ovl + = dyn_cast<OverloadedFunctionDecl>(MemExpr->getMemberDecl())) { + for (OverloadedFunctionDecl::function_iterator + Func = Ovl->function_begin(), + FuncEnd = Ovl->function_end(); + Func != FuncEnd; ++Func) { + if (Method = dyn_cast<CXXMethodDecl>(*Func)) + AddMethodCandidate(Method, ObjectArg, Args, NumArgs, CandidateSet, + /*SuppressUserConversions=*/false); + else + AddMethodTemplateCandidate(cast<FunctionTemplateDecl>(*Func), + /*FIXME:*/false, /*FIXME:*/0, + /*FIXME:*/0, ObjectArg, Args, NumArgs, + CandidateSet, + /*SuppressUsedConversions=*/false); + } + } else + AddMethodTemplateCandidate( + cast<FunctionTemplateDecl>(MemExpr->getMemberDecl()), + /*FIXME:*/false, /*FIXME:*/0, + /*FIXME:*/0, ObjectArg, Args, NumArgs, + CandidateSet, + /*SuppressUsedConversions=*/false); + OverloadCandidateSet::iterator Best; switch (BestViableFunction(CandidateSet, MemExpr->getLocStart(), Best)) { case OR_Success: @@ -4298,7 +4357,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, case OR_No_Viable_Function: Diag(MemExpr->getSourceRange().getBegin(), diag::err_ovl_no_viable_member_function_in_call) - << Ovl->getDeclName() << MemExprE->getSourceRange(); + << DeclName << MemExprE->getSourceRange(); PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false); // FIXME: Leaking incoming expressions! return true; @@ -4306,7 +4365,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, case OR_Ambiguous: Diag(MemExpr->getSourceRange().getBegin(), diag::err_ovl_ambiguous_member_call) - << Ovl->getDeclName() << MemExprE->getSourceRange(); + << DeclName << MemExprE->getSourceRange(); PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false); // FIXME: Leaking incoming expressions! return true; @@ -4315,7 +4374,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, Diag(MemExpr->getSourceRange().getBegin(), diag::err_ovl_deleted_member_call) << Best->Function->isDeleted() - << Ovl->getDeclName() << MemExprE->getSourceRange(); + << DeclName << MemExprE->getSourceRange(); PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false); // FIXME: Leaking incoming expressions! return true; |

