diff options
-rw-r--r-- | lib/Sema/CodeCompleteConsumer.cpp | 56 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 6 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 15 | ||||
-rw-r--r-- | test/CodeCompletion/function-templates.cpp | 16 |
4 files changed, 83 insertions, 10 deletions
diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp index 2c682ebbfc..8c8d6a1831 100644 --- a/lib/Sema/CodeCompleteConsumer.cpp +++ b/lib/Sema/CodeCompleteConsumer.cpp @@ -765,14 +765,16 @@ static void AddFunctionParameterChunks(ASTContext &Context, /// \brief Add template parameter chunks to the given code completion string. static void AddTemplateParameterChunks(ASTContext &Context, TemplateDecl *Template, - CodeCompletionString *Result) { + CodeCompletionString *Result, + unsigned MaxParameters = 0) { CodeCompletionString *CCStr = Result; bool FirstParameter = true; TemplateParameterList *Params = Template->getTemplateParameters(); - for (TemplateParameterList::iterator P = Params->begin(), - PEnd = Params->end(); - P != PEnd; ++P) { + TemplateParameterList::iterator PEnd = Params->end(); + if (MaxParameters) + PEnd = Params->begin() + MaxParameters; + for (TemplateParameterList::iterator P = Params->begin(); P != PEnd; ++P) { bool HasDefaultArg = false; std::string PlaceholderStr; if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) { @@ -850,13 +852,51 @@ CodeCompleteConsumer::CreateCodeCompletionString(Result R) { } if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) { - // FIXME: We treat these like functions for now, but it would be far - // better if we computed the template parameters that are non-deduced from - // a call, then printed only those template parameters in "<...>" before - // printing the function call arguments. CodeCompletionString *Result = new CodeCompletionString; FunctionDecl *Function = FunTmpl->getTemplatedDecl(); Result->AddTextChunk(Function->getNameAsString().c_str()); + + // Figure out which template parameters are deduced (or have default + // arguments). + llvm::SmallVector<bool, 16> Deduced; + getSema().MarkDeducedTemplateParameters(FunTmpl, Deduced); + unsigned LastDeducibleArgument; + for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0; + --LastDeducibleArgument) { + if (!Deduced[LastDeducibleArgument - 1]) { + // C++0x: Figure out if the template argument has a default. If so, + // the user doesn't need to type this argument. + // FIXME: We need to abstract template parameters better! + bool HasDefaultArg = false; + NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam( + LastDeducibleArgument - 1); + if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) + HasDefaultArg = TTP->hasDefaultArgument(); + else if (NonTypeTemplateParmDecl *NTTP + = dyn_cast<NonTypeTemplateParmDecl>(Param)) + HasDefaultArg = NTTP->hasDefaultArgument(); + else { + assert(isa<TemplateTemplateParmDecl>(Param)); + HasDefaultArg + = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument(); + } + + if (!HasDefaultArg) + break; + } + } + + if (LastDeducibleArgument) { + // Some of the function template arguments cannot be deduced from a + // function call, so we introduce an explicit template argument list + // containing all of the arguments up to the first deducible argument. + Result->AddTextChunk("<"); + AddTemplateParameterChunks(getSema().Context, FunTmpl, Result, + LastDeducibleArgument); + Result->AddTextChunk(">"); + } + + // Add the function parameters Result->AddTextChunk("("); AddFunctionParameterChunks(getSema().Context, Function, Result); Result->AddTextChunk(")"); diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index abbf1c3bff..a95fac9dcd 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -2750,8 +2750,10 @@ public: void MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs, bool OnlyDeduced, - llvm::SmallVectorImpl<bool> &Deduced); - + llvm::SmallVectorImpl<bool> &Used); + void MarkDeducedTemplateParameters(FunctionTemplateDecl *FunctionTemplate, + llvm::SmallVectorImpl<bool> &Deduced); + //===--------------------------------------------------------------------===// // C++ Template Instantiation // diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 24246e5734..5a5d63edc2 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -2199,3 +2199,18 @@ Sema::MarkUsedTemplateParameters(const TemplateArgumentList &TemplateArgs, for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) ::MarkUsedTemplateParameters(*this, TemplateArgs[I], OnlyDeduced, Used); } + +/// \brief Marks all of the template parameters that will be deduced by a +/// call to the given function template. +void Sema::MarkDeducedTemplateParameters(FunctionTemplateDecl *FunctionTemplate, + llvm::SmallVectorImpl<bool> &Deduced) { + TemplateParameterList *TemplateParams + = FunctionTemplate->getTemplateParameters(); + Deduced.clear(); + Deduced.resize(TemplateParams->size()); + + FunctionDecl *Function = FunctionTemplate->getTemplatedDecl(); + for (unsigned I = 0, N = Function->getNumParams(); I != N; ++I) + ::MarkUsedTemplateParameters(*this, Function->getParamDecl(I)->getType(), + true, Deduced); +} diff --git a/test/CodeCompletion/function-templates.cpp b/test/CodeCompletion/function-templates.cpp new file mode 100644 index 0000000000..c9a893ec9c --- /dev/null +++ b/test/CodeCompletion/function-templates.cpp @@ -0,0 +1,16 @@ +// RUN: clang-cc -fsyntax-only -code-completion-dump=1 %s -o - | FileCheck -check-prefix=CC1 %s && +// RUN: true + +namespace std { + template<typename RandomAccessIterator> + void sort(RandomAccessIterator first, RandomAccessIterator last); + + template<class X, class Y> + X* dyn_cast(Y *Val); +} + +void f() { + // CHECK-CC1: dyn_cast<<#class X#>>(<#Y *Val#>) + // CHECK-CC1: sort(<#RandomAccessIterator first#>, <#RandomAccessIterator last#>) + std:: + |