[cfe-commits] r82306 - in /cfe/trunk: lib/Sema/CodeCompleteConsumer.cpp lib/Sema/Sema.h lib/Sema/SemaTemplateDeduction.cpp test/CodeCompletion/function-templates.cpp

Douglas Gregor dgregor at apple.com
Fri Sep 18 16:21:38 PDT 2009


Author: dgregor
Date: Fri Sep 18 18:21:38 2009
New Revision: 82306

URL: http://llvm.org/viewvc/llvm-project?rev=82306&view=rev
Log:
Make the construction of the code-completion string for a function
template smarter, by taking into account which function template
parameters are deducible from the call arguments. For example,

  template<typename RandomAccessIterator>
  void sort(RandomAccessIterator first, RandomAccessIterator last);

will have a code-completion string like

  sort({RandomAccessIterator first}, {RandomAccessIterator last})

since the template argument for its template parameter is
deducible. On the other hand,

  template<class X, class Y>
  X* dyn_cast(Y *Val);

will have a code-completion string like

  dyn_cast<{class X}>({Y *Val})

since the template type parameter X is not deducible from the function
call.

Added:
    cfe/trunk/test/CodeCompletion/function-templates.cpp   (with props)
Modified:
    cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp

Modified: cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp?rev=82306&r1=82305&r2=82306&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp (original)
+++ cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp Fri Sep 18 18:21:38 2009
@@ -765,14 +765,16 @@
 /// \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 @@
   }
   
   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(")");

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=82306&r1=82305&r2=82306&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Fri Sep 18 18:21:38 2009
@@ -2750,8 +2750,10 @@
   
   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
   //

Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=82306&r1=82305&r2=82306&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Fri Sep 18 18:21:38 2009
@@ -2199,3 +2199,18 @@
   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);
+}

Added: cfe/trunk/test/CodeCompletion/function-templates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeCompletion/function-templates.cpp?rev=82306&view=auto

==============================================================================
--- cfe/trunk/test/CodeCompletion/function-templates.cpp (added)
+++ cfe/trunk/test/CodeCompletion/function-templates.cpp Fri Sep 18 18:21:38 2009
@@ -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::
+  

Propchange: cfe/trunk/test/CodeCompletion/function-templates.cpp

------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/CodeCompletion/function-templates.cpp

------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/test/CodeCompletion/function-templates.cpp

------------------------------------------------------------------------------
    svn:mime-type = text/plain





More information about the cfe-commits mailing list