[cfe-commits] r82592 - in /cfe/trunk: include/clang/Sema/CodeCompleteConsumer.h lib/Sema/CodeCompleteConsumer.cpp lib/Sema/SemaCodeComplete.cpp test/CodeCompletion/call.cpp

Douglas Gregor dgregor at apple.com
Tue Sep 22 17:16:58 PDT 2009


Author: dgregor
Date: Tue Sep 22 19:16:58 2009
New Revision: 82592

URL: http://llvm.org/viewvc/llvm-project?rev=82592&view=rev
Log:
Separate the code-completion results for call completion from the
results for other, textual completion. For call completion, we now
produce enough information to show the function call argument that we
are currently on.

Modified:
    cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h
    cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp
    cfe/trunk/lib/Sema/SemaCodeComplete.cpp
    cfe/trunk/test/CodeCompletion/call.cpp

Modified: cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h?rev=82592&r1=82591&r2=82592&view=diff

==============================================================================
--- cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h (original)
+++ cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h Tue Sep 22 19:16:58 2009
@@ -22,7 +22,10 @@
 }
 
 namespace clang {
-  
+
+class FunctionDecl;
+class FunctionType;
+class FunctionTemplateDecl;
 class NamedDecl;
 class NestedNameSpecifier;
 class Sema;
@@ -213,6 +216,65 @@
     CodeCompletionString *CreateCodeCompletionString(Sema &S);
   };
     
+  class OverloadCandidate {
+  public:
+    /// \brief Describes the type of overload candidate.
+    enum CandidateKind {
+      /// \brief The candidate is a function declaration.
+      CK_Function,
+      /// \brief The candidate is a function template.
+      CK_FunctionTemplate,
+      /// \brief The "candidate" is actually a variable, expression, or block
+      /// for which we only have a function prototype.
+      CK_FunctionType
+    };
+    
+  private:
+    /// \brief The kind of overload candidate.
+    CandidateKind Kind;
+    
+    union {
+      /// \brief The function overload candidate, available when 
+      /// Kind == CK_Function.
+      FunctionDecl *Function;
+      
+      /// \brief The function template overload candidate, available when
+      /// Kind == CK_FunctionTemplate.
+      FunctionTemplateDecl *FunctionTemplate;
+      
+      /// \brief The function type that describes the entity being called,
+      /// when Kind == CK_FunctionType.
+      const FunctionType *Type;
+    };
+    
+  public:
+    OverloadCandidate(FunctionDecl *Function)
+      : Kind(CK_Function), Function(Function) { }
+
+    OverloadCandidate(FunctionTemplateDecl *FunctionTemplateDecl)
+      : Kind(CK_FunctionTemplate), FunctionTemplate(FunctionTemplate) { }
+
+    OverloadCandidate(const FunctionType *Type)
+      : Kind(CK_FunctionType), Type(Type) { }
+
+    /// \brief Determine the kind of overload candidate.
+    CandidateKind getKind() const { return Kind; }
+    
+    /// \brief Retrieve the function overload candidate or the templated 
+    /// function declaration for a function template.
+    FunctionDecl *getFunction() const;
+    
+    /// \brief Retrieve the function template overload candidate.
+    FunctionTemplateDecl *getFunctionTemplate() const {
+      assert(getKind() == CK_FunctionTemplate && "Not a function template");
+      return FunctionTemplate;
+    }
+    
+    /// \brief Retrieve the function type of the entity, regardless of how the
+    /// function is stored.
+    const FunctionType *getFunctionType() const;
+  };
+  
   /// \brief Deregisters and destroys this code-completion consumer.
   virtual ~CodeCompleteConsumer();
     
@@ -221,6 +283,17 @@
   /// \brief Process the finalized code-completion results.
   virtual void ProcessCodeCompleteResults(Result *Results, 
                                           unsigned NumResults) { }
+  
+  /// \brief Process the set of overload candidates.
+  ///
+  /// \param CurrentArg the index of the current argument.
+  ///
+  /// \param Candidates an array of overload candidates.
+  ///
+  /// \param NumCandidates the number of overload candidates
+  virtual void ProcessOverloadCandidates(unsigned CurrentArg,
+                                         OverloadCandidate *Candidates,
+                                         unsigned NumCandidates) { }
   //@}
 };
   
@@ -243,6 +316,10 @@
   /// \brief Prints the finalized code-completion results.
   virtual void ProcessCodeCompleteResults(Result *Results, 
                                           unsigned NumResults);
+  
+  virtual void ProcessOverloadCandidates(unsigned CurrentArg,
+                                         OverloadCandidate *Candidates,
+                                         unsigned NumCandidates);  
 };
   
 } // end namespace clang

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

==============================================================================
--- cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp (original)
+++ cfe/trunk/lib/Sema/CodeCompleteConsumer.cpp Tue Sep 22 19:16:58 2009
@@ -97,6 +97,36 @@
 }
 
 //===----------------------------------------------------------------------===//
+// Code completion overload candidate implementation
+//===----------------------------------------------------------------------===//
+FunctionDecl *
+CodeCompleteConsumer::OverloadCandidate::getFunction() const {
+  if (getKind() == CK_Function)
+    return Function;
+  else if (getKind() == CK_FunctionTemplate)
+    return FunctionTemplate->getTemplatedDecl();
+  else
+    return 0;
+}
+
+const FunctionType *
+CodeCompleteConsumer::OverloadCandidate::getFunctionType() const {
+  switch (Kind) {
+  case CK_Function:
+    return Function->getType()->getAs<FunctionType>();
+      
+  case CK_FunctionTemplate:
+    return FunctionTemplate->getTemplatedDecl()->getType()
+             ->getAs<FunctionType>();
+      
+  case CK_FunctionType:
+    return Type;
+  }
+  
+  return 0;
+}
+
+//===----------------------------------------------------------------------===//
 // Code completion consumer implementation
 //===----------------------------------------------------------------------===//
 
@@ -133,3 +163,37 @@
   // FIXME: Move this somewhere else!
   SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
 }
+
+void 
+PrintingCodeCompleteConsumer::ProcessOverloadCandidates(unsigned CurrentArg,
+                                              OverloadCandidate *Candidates,
+                                                     unsigned NumCandidates) {
+  for (unsigned I = 0; I != NumCandidates; ++I) {
+    std::string ArgString;
+    QualType ArgType;
+    
+    if (FunctionDecl *Function = Candidates[I].getFunction()) {
+      if (CurrentArg < Function->getNumParams()) {
+        ArgString = Function->getParamDecl(CurrentArg)->getNameAsString();
+        ArgType = Function->getParamDecl(CurrentArg)->getOriginalType();
+      }
+    } else if (const FunctionProtoType *Proto 
+                 = dyn_cast<FunctionProtoType>(
+                                            Candidates[I].getFunctionType())) {
+      if (CurrentArg < Proto->getNumArgs())
+        ArgType = Proto->getArgType(CurrentArg);
+    }
+    
+    if (ArgType.isNull())
+      OS << "...\n";  // We have no prototype or we're matching an ellipsis.
+    else {
+      ArgType.getAsStringInternal(ArgString, SemaRef.Context.PrintingPolicy);
+      OS << ArgString << "\n";
+    }
+  }
+
+  // Once we've printed the code-completion results, suppress remaining
+  // diagnostics.
+  // FIXME: Move this somewhere else!
+  SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
+}

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Tue Sep 22 19:16:58 2009
@@ -1161,19 +1161,17 @@
                    IsBetterOverloadCandidate(*this));
   
   // Add the remaining viable overload candidates as code-completion reslults.  
-  typedef CodeCompleteConsumer::Result Result;
-  ResultBuilder Results(*this);
-  Results.EnterNewScope();
+  typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
+  llvm::SmallVector<ResultCandidate, 8> Results;
   
   for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
                                    CandEnd = CandidateSet.end();
        Cand != CandEnd; ++Cand) {
     if (Cand->Viable)
-      Results.MaybeAddResult(Result(Cand->Function, 0), 0);
+      Results.push_back(ResultCandidate(Cand->Function));
   }
-  
-  Results.ExitScope();
-  HandleCodeCompleteResults(CodeCompleter, Results.data(), Results.size());
+  CodeCompleter->ProcessOverloadCandidates(NumArgs, Results.data(), 
+                                           Results.size());
 }
 
 void Sema::CodeCompleteQualifiedId(Scope *S, const CXXScopeSpec &SS,

Modified: cfe/trunk/test/CodeCompletion/call.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeCompletion/call.cpp?rev=82592&r1=82591&r2=82592&view=diff

==============================================================================
--- cfe/trunk/test/CodeCompletion/call.cpp (original)
+++ cfe/trunk/test/CodeCompletion/call.cpp Tue Sep 22 19:16:58 2009
@@ -10,7 +10,7 @@
     
     operator int() const;
   };
-  void f(Y y, int);
+  void f(Y y, int ZZ);
 }
 typedef N::Y Y;
 void f();
@@ -18,12 +18,11 @@
 void test() {
   f(Y(), 0, 0);
   // RUN: clang-cc -fsyntax-only -code-completion-at=%s:19:9 %s -o - | FileCheck -check-prefix=CC1 %s &&
-  // CHECK-CC1: f : 0 : f(<#struct N::Y y#>, <#int#>)
-  // CHECK-NEXT-CC1: f : 0 : f(<#int i#>, <#int j#>, <#int k#>)
-  // CHECK-NEXT-CC1: f : 0 : f(<#float x#>, <#float y#>)
+  // CHECK-CC1: int ZZ
+  // CHECK-NEXT-CC1: int j
+  // CHECK-NEXT-CC1: float y
   // RUN: clang-cc -fsyntax-only -code-completion-at=%s:19:13 %s -o - | FileCheck -check-prefix=CC2 %s &&
-  // CHECK-NOT-CC2: f : 0 : f(<#struct N::Y y#>, <#int#>)
-  // CHECK-CC2: f : 0 : f(<#int i#>, <#int j#>, <#int k#>)
-  // CHECK-NEXT-CC2: f : 0 : f(<#float x#>, <#float y#>)
+  // FIXME: two ellipses are showing up when they shouldn't
+  // CHECK-CC2: int k
   // RUN: true
 }





More information about the cfe-commits mailing list