]> granicus.if.org Git - clang/commitdiff
C++ code completion after the "operator" keyword. Provide overloaded
authorDouglas Gregor <dgregor@apple.com>
Fri, 18 Sep 2009 20:05:18 +0000 (20:05 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 18 Sep 2009 20:05:18 +0000 (20:05 +0000)
operators, type specifiers, type names, and nested-name-specifiers.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82264 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Parse/Action.h
include/clang/Sema/CodeCompleteConsumer.h
lib/Parse/ParseExprCXX.cpp
lib/Sema/CodeCompleteConsumer.cpp
lib/Sema/Sema.h
lib/Sema/SemaCodeComplete.cpp
test/CodeCompletion/operator.cpp [new file with mode: 0644]

index 5df0b1f596f4b204d149b00cb2bf0d34cc3c461f..2d37b86a28297974f8e78077e82774d3c5e0783b 100644 (file)
@@ -2270,6 +2270,14 @@ public:
   ///
   /// \param S the scope in which the namespace alias declaration occurs.
   virtual void CodeCompleteNamespaceAliasDecl(Scope *S) { }
+  
+  /// \brief Code completion for an operator name.
+  ///
+  /// This code completion action is invoked when the code-completion token is
+  /// found after the keyword "operator".
+  ///
+  /// \param S the scope in which the operator keyword occurs.
+  virtual void CodeCompleteOperatorName(Scope *S) { }
   //@}
 };
 
index d8d2bcc311aca4cc80960f8b4806eed855fd35ef..821678b22a3c5ccd5a9f686540d54283dad542bd 100644 (file)
@@ -219,7 +219,15 @@ public:
   /// found after "namespace identifier = ".
   ///
   /// \param S the scope in which the namespace alias declaration occurs.
-  virtual void CodeCompleteNamespaceAliasDecl(Scope *S);  
+  virtual void CodeCompleteNamespaceAliasDecl(Scope *S);
+  
+  /// \brief Code completion for an operator name.
+  ///
+  /// This code completion action is invoked when the code-completion token is
+  /// found after the keyword "operator".
+  ///
+  /// \param S the scope in which the operator keyword occurs.
+  virtual void CodeCompleteOperatorName(Scope *S);
   //@}
   
   /// \name Name lookup functions
@@ -248,14 +256,14 @@ public:
   bool IsUnion(NamedDecl *ND) const;
   bool IsNamespace(NamedDecl *ND) const;
   bool IsNamespaceOrAlias(NamedDecl *ND) const;
+  bool IsType(NamedDecl *ND) const;
   //@}
   
   /// \name Utility functions
   ///
-  //@{
-  
+  //@{  
   bool canHiddenResultBeFound(NamedDecl *Hidden, NamedDecl *Visible);
-  
+  void AddTypeSpecifierResults(unsigned Rank, ResultSet &Results);
   //@}
 };
   
index 4c0f699b3f0a98f5bcde97b7c02bba2c75f1549e..325f085a49d84072244206acd79adb494f1e454a 100644 (file)
@@ -835,6 +835,18 @@ Parser::TryParseOperatorFunctionId(SourceLocation *EndLoc) {
       *EndLoc = Loc;
     return OO_Subscript;
 
+  case tok::code_completion: {
+    // Code completion for the operator name.
+    Actions.CodeCompleteOperatorName(CurScope);
+    
+    // Consume the 'operator' token, then replace the code-completion token
+    // with an 'operator' token and try again.
+    SourceLocation OperatorLoc = ConsumeToken();
+    Tok.setLocation(OperatorLoc);
+    Tok.setKind(tok::kw_operator);
+    return TryParseOperatorFunctionId(EndLoc);
+  }
+      
   default:
     return OO_None;
   }
index fd187c5ef9fbda31c6820874850202b37355ffeb..d82047d912ecaa3a0dc12da0204e8bdba9b5424f 100644 (file)
@@ -175,6 +175,28 @@ void CodeCompleteConsumer::CodeCompleteNamespaceAliasDecl(Scope *S) {
   ProcessCodeCompleteResults(Results.data(), Results.size());  
 }
 
+void CodeCompleteConsumer::CodeCompleteOperatorName(Scope *S) {
+  ResultSet Results(*this, &CodeCompleteConsumer::IsType);
+  
+  // Add the names of overloadable operators.
+#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly)      \
+  if (strcmp(Spelling, "?"))                                                  \
+    Results.MaybeAddResult(Result(Spelling, 0));
+#include "clang/Basic/OperatorKinds.def"
+  
+  // Add any type names visible from the current scope
+  unsigned NextRank = CollectLookupResults(S, 0, Results);
+  
+  // Add any type specifiers
+  AddTypeSpecifierResults(0, Results);
+  
+  // Add any nested-name-specifiers
+  Results.setFilter(&CodeCompleteConsumer::IsNestedNameSpecifier);
+  CollectLookupResults(S, NextRank + 1, Results);
+
+  ProcessCodeCompleteResults(Results.data(), Results.size());  
+}
+
 void CodeCompleteConsumer::ResultSet::MaybeAddResult(Result R) {
   if (R.Kind != Result::RK_Declaration) {
     // For non-declaration results, just add the result.
@@ -208,7 +230,7 @@ void CodeCompleteConsumer::ResultSet::MaybeAddResult(Result R) {
 
   if (const IdentifierInfo *Id = R.Declaration->getIdentifier()) {
     // __va_list_tag is a freak of nature. Find it and skip it.
-    if (Id->isStr("__va_list_tag"))
+    if (Id->isStr("__va_list_tag") || Id->isStr("__builtin_va_list"))
       return;
 
     // FIXME: Should we filter out other names in the implementation's
@@ -522,6 +544,12 @@ bool CodeCompleteConsumer::IsNamespaceOrAlias(NamedDecl *ND) const {
   return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
 }
 
+/// \brief Brief determines whether the given declaration is a namespace or
+/// namespace alias.
+bool CodeCompleteConsumer::IsType(NamedDecl *ND) const {
+  return isa<TypeDecl>(ND);
+}
+
 namespace {
   struct VISIBILITY_HIDDEN SortCodeCompleteResult {
     typedef CodeCompleteConsumer::Result Result;
@@ -588,6 +616,53 @@ bool CodeCompleteConsumer::canHiddenResultBeFound(NamedDecl *Hidden,
   return HiddenCtx != Visible->getDeclContext()->getLookupContext();
 }
 
+/// \brief Add type specifiers for the current language as keyword results.
+void CodeCompleteConsumer::AddTypeSpecifierResults(unsigned Rank, 
+                                                   ResultSet &Results) {
+  Results.MaybeAddResult(Result("short", Rank));
+  Results.MaybeAddResult(Result("long", Rank));
+  Results.MaybeAddResult(Result("signed", Rank));
+  Results.MaybeAddResult(Result("unsigned", Rank));
+  Results.MaybeAddResult(Result("void", Rank));
+  Results.MaybeAddResult(Result("char", Rank));
+  Results.MaybeAddResult(Result("int", Rank));
+  Results.MaybeAddResult(Result("float", Rank));
+  Results.MaybeAddResult(Result("double", Rank));
+  Results.MaybeAddResult(Result("enum", Rank));
+  Results.MaybeAddResult(Result("struct", Rank));
+  Results.MaybeAddResult(Result("union", Rank));
+
+  if (getSema().getLangOptions().C99) {
+    // C99-specific
+    Results.MaybeAddResult(Result("_Complex", Rank));
+    Results.MaybeAddResult(Result("_Imaginary", Rank));
+    Results.MaybeAddResult(Result("_Bool", Rank));
+  }
+  
+  if (getSema().getLangOptions().CPlusPlus) {
+    // C++-specific
+    Results.MaybeAddResult(Result("bool", Rank));
+    Results.MaybeAddResult(Result("class", Rank));
+    Results.MaybeAddResult(Result("typename", Rank));
+    Results.MaybeAddResult(Result("wchar_t", Rank));
+    
+    if (getSema().getLangOptions().CPlusPlus0x) {
+      Results.MaybeAddResult(Result("char16_t", Rank));
+      Results.MaybeAddResult(Result("char32_t", Rank));
+      Results.MaybeAddResult(Result("decltype", Rank));
+    }
+  }
+  
+  // GNU extensions
+  if (getSema().getLangOptions().GNUMode) {
+    // FIXME: Enable when we actually support decimal floating point.
+    //    Results.MaybeAddResult(Result("_Decimal32", Rank));
+    //    Results.MaybeAddResult(Result("_Decimal64", Rank));
+    //    Results.MaybeAddResult(Result("_Decimal128", Rank));
+    Results.MaybeAddResult(Result("typeof", Rank));
+  }
+}
+
 void 
 PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Result *Results, 
                                                          unsigned NumResults) {
index 8bec9d54f5d39afa2fe98d15d4c667617028964f..abbf1c3bff6059783c8852b845819428860d4883 100644 (file)
@@ -3642,6 +3642,7 @@ public:
   virtual void CodeCompleteUsingDirective(Scope *S);
   virtual void CodeCompleteNamespaceDecl(Scope *S);
   virtual void CodeCompleteNamespaceAliasDecl(Scope *S);
+  virtual void CodeCompleteOperatorName(Scope *S);
   //@}
   
   //===--------------------------------------------------------------------===//
index 50b8ffd1f49bba3554b56d450b1d42d21ae9caf5..adb0469cf0bbb712886f845b8fc9415134748989 100644 (file)
@@ -101,4 +101,10 @@ void Sema::CodeCompleteNamespaceAliasDecl(Scope *S)  {
   CodeCompleter->CodeCompleteNamespaceAliasDecl(S);
 }
 
+void Sema::CodeCompleteOperatorName(Scope *S) {
+  if (!CodeCompleter)
+    return;
+  
+  CodeCompleter->CodeCompleteOperatorName(S);
+}
 
diff --git a/test/CodeCompletion/operator.cpp b/test/CodeCompletion/operator.cpp
new file mode 100644 (file)
index 0000000..8089405
--- /dev/null
@@ -0,0 +1,19 @@
+// RUN: clang-cc -fsyntax-only -code-completion-dump=1 %s -o - | FileCheck -check-prefix=CC1 %s &&
+// RUN: true
+
+class T { };
+
+typedef int Integer;
+
+namespace N { }
+
+void f() {
+  typedef float Float;
+  
+  // CHECK-CC1: Float : 0
+  // CHECK-CC1: + : 0
+  // CHECK-CC1: short : 0
+  // CHECK-CC1: Integer : 2
+  // CHECK-CC1: T : 2
+  // CHECK-CC1: N : 5
+  operator