[cfe-commits] r111976 - in /cfe/trunk: include/clang/Lex/CodeCompletionHandler.h include/clang/Parse/Parser.h include/clang/Sema/Action.h include/clang/Sema/CodeCompleteConsumer.h include/clang/Sema/Sema.h lib/Frontend/ASTUnit.cpp lib/Lex/PPExpressions.cpp lib/Lex/PPMacroExpansion.cpp lib/Parse/Parser.cpp lib/Sema/SemaCodeComplete.cpp test/Index/complete-preprocessor.m

Douglas Gregor dgregor at apple.com
Tue Aug 24 15:20:20 PDT 2010


Author: dgregor
Date: Tue Aug 24 17:20:20 2010
New Revision: 111976

URL: http://llvm.org/viewvc/llvm-project?rev=111976&view=rev
Log:
Implement code completion for preprocessor expressions and in macro
arguments.

Modified:
    cfe/trunk/include/clang/Lex/CodeCompletionHandler.h
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/include/clang/Sema/Action.h
    cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Frontend/ASTUnit.cpp
    cfe/trunk/lib/Lex/PPExpressions.cpp
    cfe/trunk/lib/Lex/PPMacroExpansion.cpp
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/lib/Sema/SemaCodeComplete.cpp
    cfe/trunk/test/Index/complete-preprocessor.m

Modified: cfe/trunk/include/clang/Lex/CodeCompletionHandler.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/CodeCompletionHandler.h?rev=111976&r1=111975&r2=111976&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/CodeCompletionHandler.h (original)
+++ cfe/trunk/include/clang/Lex/CodeCompletionHandler.h Tue Aug 24 17:20:20 2010
@@ -16,6 +16,9 @@
 
 namespace clang {
 
+class IdentifierInfo;
+class MacroInfo;
+  
 /// \brief Callback handler that receives notifications when performing code 
 /// completion within the preprocessor.
 class CodeCompletionHandler {
@@ -42,6 +45,16 @@
   /// \param IsDefinition Whether this is the definition of a macro, e.g.,
   /// in a #define.
   virtual void CodeCompleteMacroName(bool IsDefinition) { }
+  
+  /// \brief Callback invoked when performing code completion in a preprocessor
+  /// expression, such as the condition of an #if or #elif directive.
+  virtual void CodeCompletePreprocessorExpression() { }
+  
+  /// \brief Callback invoked when performing code completion inside a 
+  /// function-like macro argument.
+  virtual void CodeCompleteMacroArgument(IdentifierInfo *Macro,
+                                         MacroInfo *MacroInfo,
+                                         unsigned ArgumentIndex) { }
 };
   
 }

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=111976&r1=111975&r2=111976&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Tue Aug 24 17:20:20 2010
@@ -1536,6 +1536,10 @@
   virtual void CodeCompleteDirective(bool InConditional);
   virtual void CodeCompleteInConditionalExclusion();
   virtual void CodeCompleteMacroName(bool IsDefinition);
+  virtual void CodeCompletePreprocessorExpression();
+  virtual void CodeCompleteMacroArgument(IdentifierInfo *Macro,
+                                         MacroInfo *MacroInfo,
+                                         unsigned ArgumentIndex);
 };
 
 }  // end namespace clang

Modified: cfe/trunk/include/clang/Sema/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Action.h?rev=111976&r1=111975&r2=111976&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Action.h (original)
+++ cfe/trunk/include/clang/Sema/Action.h Tue Aug 24 17:20:20 2010
@@ -43,7 +43,8 @@
   // Lex.
   class Preprocessor;
   class Token;
-
+  class MacroInfo;
+  
 /// Action - As the parser reads the input file and recognizes the productions
 /// of the grammar, it invokes methods on this class to turn the parsed input
 /// into something useful: e.g. a parse tree.
@@ -3207,9 +3208,8 @@
   
   /// \brief Code completion for a preprocessor directive.
   ///
-  /// \brief S The scope in which the preprocessor directive is being parsed.
   /// \brief InConditional Whether we're inside a preprocessor conditional.
-  virtual void CodeCompletePreprocessorDirective(Scope *S, bool InConditional) { 
+  virtual void CodeCompletePreprocessorDirective(bool InConditional) { 
   }
   
   /// \brief Code completion while in an area of the translation unit that was
@@ -3219,13 +3219,31 @@
   /// \brief Code completion in the preprocessor where an already-defined
   /// macro name is expected, e.g., an #ifdef or #undef.
   ///
-  /// \param S The scope in which the macro name occurs.
-  ///
   /// \param IsDefinition Whether this code completion for a macro name occurs
   /// in a definition of the macro (#define) or in another use that already
   /// expects that the macro is defined (e.g., #undef or #ifdef).
-  virtual void CodeCompletePreprocessorMacroName(Scope *S, bool IsDefinition) { 
+  virtual void CodeCompletePreprocessorMacroName(bool IsDefinition) { 
   }
+  
+  /// \brief Callback invoked when performing code completion in a preprocessor
+  /// expression, such as the condition of an #if or #elif directive.
+  virtual void CodeCompletePreprocessorExpression() { }
+  
+  /// \brief Callback invoked when performing code completion inside a 
+  /// function-like macro argument.
+  ///
+  /// \param S The scope in which this macro is being expanded.
+  ///
+  /// \param Macro The name of the macro that is going to be expanded.
+  ///
+  /// \param MacroInfo Information about the macro that is going to be
+  /// expanded.
+  ///
+  /// \param Argument The argument in which the code-completion token occurs.
+  virtual void CodeCompletePreprocessorMacroArgument(Scope *S,
+                                                     IdentifierInfo *Macro,
+                                                     MacroInfo *MacroInfo,
+                                                     unsigned Argument) { }
   //@}
 };
 

Modified: cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h?rev=111976&r1=111975&r2=111976&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h (original)
+++ cfe/trunk/include/clang/Sema/CodeCompleteConsumer.h Tue Aug 24 17:20:20 2010
@@ -174,7 +174,9 @@
     CCC_MacroName,
     /// \brief Code completion occurred where a macro name is expected
     /// (without any arguments, in the case of a function-like macro).
-    CCC_MacroNameUse
+    CCC_MacroNameUse,
+    /// \brief Code completion occurred within a preprocessor expression.
+    CCC_PreprocessorExpression
   };
 
 private:

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=111976&r1=111975&r2=111976&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Aug 24 17:20:20 2010
@@ -4633,9 +4633,14 @@
                                                   ParsedType ReturnType,
                                                   IdentifierInfo **SelIdents,
                                                   unsigned NumSelIdents);
-  virtual void CodeCompletePreprocessorDirective(Scope *S, bool InConditional);
+  virtual void CodeCompletePreprocessorDirective(bool InConditional);
   virtual void CodeCompleteInPreprocessorConditionalExclusion(Scope *S);
-  virtual void CodeCompletePreprocessorMacroName(Scope *S, bool IsDefinition);
+  virtual void CodeCompletePreprocessorMacroName(bool IsDefinition);
+  virtual void CodeCompletePreprocessorExpression();
+  virtual void CodeCompletePreprocessorMacroArgument(Scope *S,
+                                                     IdentifierInfo *Macro,
+                                                     MacroInfo *MacroInfo,
+                                                     unsigned Argument);
   void GatherGlobalCodeCompletions(
                   llvm::SmallVectorImpl<CodeCompleteConsumer::Result> &Results);
   //@}

Modified: cfe/trunk/lib/Frontend/ASTUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/ASTUnit.cpp?rev=111976&r1=111975&r2=111976&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/ASTUnit.cpp (original)
+++ cfe/trunk/lib/Frontend/ASTUnit.cpp Tue Aug 24 17:20:20 2010
@@ -278,7 +278,8 @@
         | (1 << (CodeCompletionContext::CCC_Statement - 1))
         | (1 << (CodeCompletionContext::CCC_Expression - 1))
         | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1))
-        | (1 << (CodeCompletionContext::CCC_MacroNameUse - 1));
+        | (1 << (CodeCompletionContext::CCC_MacroNameUse - 1))
+        | (1 << (CodeCompletionContext::CCC_PreprocessorExpression - 1));
       
       CachedResult.Priority = Results[I].Priority;
       CachedResult.Kind = Results[I].CursorKind;
@@ -1550,6 +1551,7 @@
   case CodeCompletionContext::CCC_ObjCProtocolName:
   case CodeCompletionContext::CCC_MacroName:
   case CodeCompletionContext::CCC_MacroNameUse:
+  case CodeCompletionContext::CCC_PreprocessorExpression:
     // If we're just looking for protocol or macro names, nothing can hide them.
     return;
   }

Modified: cfe/trunk/lib/Lex/PPExpressions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPExpressions.cpp?rev=111976&r1=111975&r2=111976&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPExpressions.cpp (original)
+++ cfe/trunk/lib/Lex/PPExpressions.cpp Tue Aug 24 17:20:20 2010
@@ -149,6 +149,12 @@
                           bool ValueLive, Preprocessor &PP) {
   DT.State = DefinedTracker::Unknown;
 
+  if (PeekTok.is(tok::code_completion)) {
+    if (PP.getCodeCompletionHandler())
+      PP.getCodeCompletionHandler()->CodeCompletePreprocessorExpression();
+    PP.LexUnexpandedToken(PeekTok);
+  }
+      
   // If this token's spelling is a pp-identifier, check to see if it is
   // 'defined' or if it is a macro.  Note that we check here because many
   // keywords are pp-identifiers, so we can't check the kind.

Modified: cfe/trunk/lib/Lex/PPMacroExpansion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPMacroExpansion.cpp?rev=111976&r1=111975&r2=111976&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPMacroExpansion.cpp (original)
+++ cfe/trunk/lib/Lex/PPMacroExpansion.cpp Tue Aug 24 17:20:20 2010
@@ -19,6 +19,7 @@
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Lex/LexDiagnostic.h"
+#include "clang/Lex/CodeCompletionHandler.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cstdio>
@@ -323,6 +324,13 @@
       // an argument value in a macro could expand to ',' or '(' or ')'.
       LexUnexpandedToken(Tok);
 
+      if (Tok.is(tok::code_completion)) {
+        if (CodeComplete)
+          CodeComplete->CodeCompleteMacroArgument(MacroName.getIdentifierInfo(),
+                                                  MI, NumActuals);
+        LexUnexpandedToken(Tok);
+      }
+      
       if (Tok.is(tok::eof) || Tok.is(tok::eom)) { // "#if f(<eof>" & "#if f(\n"
         Diag(MacroName, diag::err_unterm_macro_invoc);
         // Do not lose the EOF/EOM.  Return it to the client.

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=111976&r1=111975&r2=111976&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Tue Aug 24 17:20:20 2010
@@ -1133,7 +1133,7 @@
 // Code-completion pass-through functions
 
 void Parser::CodeCompleteDirective(bool InConditional) {
-  Actions.CodeCompletePreprocessorDirective(getCurScope(), InConditional);
+  Actions.CodeCompletePreprocessorDirective(InConditional);
 }
 
 void Parser::CodeCompleteInConditionalExclusion() {
@@ -1141,5 +1141,16 @@
 }
 
 void Parser::CodeCompleteMacroName(bool IsDefinition) {
-  Actions.CodeCompletePreprocessorMacroName(getCurScope(), IsDefinition);
+  Actions.CodeCompletePreprocessorMacroName(IsDefinition);
+}
+
+void Parser::CodeCompletePreprocessorExpression() { 
+  Actions.CodeCompletePreprocessorExpression();
+}
+
+void Parser::CodeCompleteMacroArgument(IdentifierInfo *Macro,
+                                       MacroInfo *MacroInfo,
+                                       unsigned ArgumentIndex) {
+  Actions.CodeCompletePreprocessorMacroArgument(getCurScope(), Macro, MacroInfo, 
+                                                ArgumentIndex);
 }

Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=111976&r1=111975&r2=111976&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Tue Aug 24 17:20:20 2010
@@ -4608,7 +4608,7 @@
                             Results.data(),Results.size());
 }
 
-void Sema::CodeCompletePreprocessorDirective(Scope *S, bool InConditional) {
+void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
   ResultBuilder Results(*this);
   Results.EnterNewScope();
   
@@ -4785,11 +4785,12 @@
 }
 
 void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
-  CodeCompleteOrdinaryName(S, Action::PCC_RecoveryInFunction);
+  CodeCompleteOrdinaryName(S,
+                           S->getFnParent()? Action::PCC_RecoveryInFunction 
+                                           : Action::PCC_Namespace);
 }
 
-void Sema::CodeCompletePreprocessorMacroName(Scope *S, bool IsDefinition) {
-  typedef CodeCompleteConsumer::Result Result;
+void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
   ResultBuilder Results(*this);
   if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
     // Add just the names of macros, not their arguments.    
@@ -4812,6 +4813,40 @@
                             Results.data(), Results.size()); 
 }
 
+void Sema::CodeCompletePreprocessorExpression() {
+  ResultBuilder Results(*this);
+  
+  if (!CodeCompleter || CodeCompleter->includeMacros())
+    AddMacroResults(PP, Results);
+  
+    // defined (<macro>)
+  Results.EnterNewScope();
+  CodeCompletionString *Pattern = new CodeCompletionString;
+  Pattern->AddTypedTextChunk("defined");
+  Pattern->AddChunk(CodeCompletionString::CK_HorizontalSpace);
+  Pattern->AddChunk(CodeCompletionString::CK_LeftParen);
+  Pattern->AddPlaceholderChunk("macro");
+  Pattern->AddChunk(CodeCompletionString::CK_RightParen);
+  Results.AddResult(Pattern);
+  Results.ExitScope();
+  
+  HandleCodeCompleteResults(this, CodeCompleter, 
+                            CodeCompletionContext::CCC_PreprocessorExpression,
+                            Results.data(), Results.size()); 
+}
+
+void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
+                                                 IdentifierInfo *Macro,
+                                                 MacroInfo *MacroInfo,
+                                                 unsigned Argument) {
+  // FIXME: In the future, we could provide "overload" results, much like we
+  // do for function calls.
+  
+  CodeCompleteOrdinaryName(S,
+                           S->getFnParent()? Action::PCC_RecoveryInFunction 
+                                           : Action::PCC_Namespace);
+}
+
 void Sema::GatherGlobalCodeCompletions(
                  llvm::SmallVectorImpl<CodeCompleteConsumer::Result> &Results) {
   ResultBuilder Builder(*this);

Modified: cfe/trunk/test/Index/complete-preprocessor.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-preprocessor.m?rev=111976&r1=111975&r2=111976&view=diff
==============================================================================
--- cfe/trunk/test/Index/complete-preprocessor.m (original)
+++ cfe/trunk/test/Index/complete-preprocessor.m Tue Aug 24 17:20:20 2010
@@ -11,6 +11,8 @@
 #if defined(FOO)
 #endif
 
+FOO(in,t) value;
+
 // RUN: c-index-test -code-completion-at=%s:4:2 %s | FileCheck -check-prefix=CHECK-CC1 %s
 // CHECK-CC1: NotImplemented:{TypedText define}{HorizontalSpace  }{Placeholder macro} (30)
 // CHECK-CC1-NEXT: NotImplemented:{TypedText define}{HorizontalSpace  }{Placeholder macro}{LeftParen (}{Placeholder args}{RightParen )} (30)
@@ -55,3 +57,18 @@
 // CHECK-CC3: NotImplemented:{TypedText FOO} (30)
 // RUN: c-index-test -code-completion-at=%s:11:12 %s | FileCheck -check-prefix=CHECK-CC3 %s
 // RUN: c-index-test -code-completion-at=%s:11:13 %s | FileCheck -check-prefix=CHECK-CC3 %s
+// RUN: c-index-test -code-completion-at=%s:11:5 %s | FileCheck -check-prefix=CHECK-CC4 %s
+// CHECK-CC4: macro definition:{TypedText BAR} (70)
+// CHECK-CC4: macro definition:{TypedText FOO}{LeftParen (}{Placeholder a}{Comma , }{Placeholder b}{RightParen )} (70)
+// RUN: c-index-test -code-completion-at=%s:14:5 %s | FileCheck -check-prefix=CHECK-CC5 %s
+// CHECK-CC5: NotImplemented:{TypedText const} (40)
+// CHECK-CC5: NotImplemented:{TypedText double} (40)
+// CHECK-CC5: NotImplemented:{TypedText enum} (40)
+// CHECK-CC5: NotImplemented:{TypedText extern} (30)
+// CHECK-CC5: NotImplemented:{TypedText float} (40)
+// CHECK-CC5: macro definition:{TypedText FOO}{LeftParen (}{Placeholder a}{Comma , }{Placeholder b}{RightParen )} (70)
+// CHECK-CC5: macro definition:{TypedText i386} (70)
+// CHECK-CC5: TypedefDecl:{TypedText id} (40)
+// CHECK-CC5: NotImplemented:{TypedText inline} (30)
+// CHECK-CC5: NotImplemented:{TypedText int} (40)
+// CHECK-CC5: NotImplemented:{TypedText long} (40)





More information about the cfe-commits mailing list