[cfe-commits] r170824 - in /cfe/trunk: lib/Lex/PPMacroExpansion.cpp test/Index/complete-macro-args.c

Argyrios Kyrtzidis akyrtzi at gmail.com
Thu Dec 20 17:17:20 PST 2012


Author: akirtzidis
Date: Thu Dec 20 19:17:20 2012
New Revision: 170824

URL: http://llvm.org/viewvc/llvm-project?rev=170824&view=rev
Log:
[libclang] Make sure we can code-complete inside a macro argument even though
the macro invocation is not fully formed.

rdar://11290992

Modified:
    cfe/trunk/lib/Lex/PPMacroExpansion.cpp
    cfe/trunk/test/Index/complete-macro-args.c

Modified: cfe/trunk/lib/Lex/PPMacroExpansion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPMacroExpansion.cpp?rev=170824&r1=170823&r2=170824&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPMacroExpansion.cpp (original)
+++ cfe/trunk/lib/Lex/PPMacroExpansion.cpp Thu Dec 20 19:17:20 2012
@@ -497,9 +497,13 @@
   // argument is separated by an EOF token.  Use a SmallVector so we can avoid
   // heap allocations in the common case.
   SmallVector<Token, 64> ArgTokens;
+  bool ContainsCodeCompletionTok = false;
 
   unsigned NumActuals = 0;
   while (Tok.isNot(tok::r_paren)) {
+    if (ContainsCodeCompletionTok && (Tok.is(tok::eof) || Tok.is(tok::eod)))
+      break;
+
     assert((Tok.is(tok::l_paren) || Tok.is(tok::comma)) &&
            "only expect argument separators here");
 
@@ -516,12 +520,16 @@
       LexUnexpandedToken(Tok);
 
       if (Tok.is(tok::eof) || Tok.is(tok::eod)) { // "#if f(<eof>" & "#if f(\n"
-        Diag(MacroName, diag::err_unterm_macro_invoc);
-        Diag(MI->getDefinitionLoc(), diag::note_macro_here)
-          << MacroName.getIdentifierInfo();
-        // Do not lose the EOF/EOD.  Return it to the client.
-        MacroName = Tok;
-        return 0;
+        if (!ContainsCodeCompletionTok) {
+          Diag(MacroName, diag::err_unterm_macro_invoc);
+          Diag(MI->getDefinitionLoc(), diag::note_macro_here)
+            << MacroName.getIdentifierInfo();
+          // Do not lose the EOF/EOD.  Return it to the client.
+          MacroName = Tok;
+          return 0;
+        } else {
+          break;
+        }
       } else if (Tok.is(tok::r_paren)) {
         // If we found the ) token, the macro arg list is done.
         if (NumParens-- == 0) {
@@ -552,6 +560,7 @@
           if (!MI->isEnabled())
             Tok.setFlag(Token::DisableExpand);
       } else if (Tok.is(tok::code_completion)) {
+        ContainsCodeCompletionTok = true;
         if (CodeComplete)
           CodeComplete->CodeCompleteMacroArgument(MacroName.getIdentifierInfo(),
                                                   MI, NumActuals);
@@ -574,12 +583,14 @@
       if (ArgTokens.size() != ArgTokenStart)
         ArgStartLoc = ArgTokens[ArgTokenStart].getLocation();
 
-      // Emit the diagnostic at the macro name in case there is a missing ).
-      // Emitting it at the , could be far away from the macro name.
-      Diag(ArgStartLoc, diag::err_too_many_args_in_macro_invoc);
-      Diag(MI->getDefinitionLoc(), diag::note_macro_here)
-        << MacroName.getIdentifierInfo();
-      return 0;
+      if (!ContainsCodeCompletionTok) {
+        // Emit the diagnostic at the macro name in case there is a missing ).
+        // Emitting it at the , could be far away from the macro name.
+        Diag(ArgStartLoc, diag::err_too_many_args_in_macro_invoc);
+        Diag(MI->getDefinitionLoc(), diag::note_macro_here)
+          << MacroName.getIdentifierInfo();
+        return 0;
+      }
     }
 
     // Empty arguments are standard in C99 and C++0x, and are supported as an extension in
@@ -639,7 +650,7 @@
       //   #define C(...) blah(a, ## __VA_ARGS__)
       //  A(x) B(x) C()
       isVarargsElided = true;
-    } else {
+    } else if (!ContainsCodeCompletionTok) {
       // Otherwise, emit the error.
       Diag(Tok, diag::err_too_few_args_in_macro_invoc);
       Diag(MI->getDefinitionLoc(), diag::note_macro_here)
@@ -659,7 +670,8 @@
     if (NumActuals == 0 && MinArgsExpected == 2)
       ArgTokens.push_back(Tok);
 
-  } else if (NumActuals > MinArgsExpected && !MI->isVariadic()) {
+  } else if (NumActuals > MinArgsExpected && !MI->isVariadic() &&
+             !ContainsCodeCompletionTok) {
     // Emit the diagnostic at the macro name in case there is a missing ).
     // Emitting it at the , could be far away from the macro name.
     Diag(MacroName, diag::err_too_many_args_in_macro_invoc);

Modified: cfe/trunk/test/Index/complete-macro-args.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-macro-args.c?rev=170824&r1=170823&r2=170824&view=diff
==============================================================================
--- cfe/trunk/test/Index/complete-macro-args.c (original)
+++ cfe/trunk/test/Index/complete-macro-args.c Thu Dec 20 19:17:20 2012
@@ -12,8 +12,17 @@
   MACRO(p->x);
 }
 
+#define MACRO3(x,y,z) x
+
+void test(struct Point *p) {
+  MACRO3(p->x);
+  MACRO3(p->x
+}
+
 // RUN: c-index-test -code-completion-at=%s:11:12 %s | FileCheck %s
 // RUN: c-index-test -code-completion-at=%s:12:12 %s | FileCheck %s
+// RUN: c-index-test -code-completion-at=%s:18:13 %s | FileCheck %s
+// RUN: c-index-test -code-completion-at=%s:19:13 %s | FileCheck %s
 // CHECK:      FieldDecl:{ResultType float}{TypedText x} (35)
 // CHECK-NEXT: FieldDecl:{ResultType float}{TypedText y} (35)
 // CHECK-NEXT: FieldDecl:{ResultType float}{TypedText z} (35)





More information about the cfe-commits mailing list