aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Lex/CodeCompletionHandler.h4
-rw-r--r--lib/Lex/PPMacroExpansion.cpp18
-rw-r--r--lib/Sema/SemaCodeComplete.cpp5
-rw-r--r--test/Index/complete-macro-args.c22
4 files changed, 45 insertions, 4 deletions
diff --git a/include/clang/Lex/CodeCompletionHandler.h b/include/clang/Lex/CodeCompletionHandler.h
index d28a3aa7d6..d876776c92 100644
--- a/include/clang/Lex/CodeCompletionHandler.h
+++ b/include/clang/Lex/CodeCompletionHandler.h
@@ -52,6 +52,10 @@ public:
/// \brief Callback invoked when performing code completion inside a
/// function-like macro argument.
+ ///
+ /// There will be another callback invocation after the macro arguments are
+ /// parsed, so this callback should generally be used to note that the next
+ /// callback is invoked inside a macro argument.
virtual void CodeCompleteMacroArgument(IdentifierInfo *Macro,
MacroInfo *MacroInfo,
unsigned ArgumentIndex) { }
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index eaab73edc4..fd5b4c2efa 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -358,7 +358,23 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName,
if (CodeComplete)
CodeComplete->CodeCompleteMacroArgument(MacroName.getIdentifierInfo(),
MI, NumActuals);
- LexUnexpandedToken(Tok);
+
+ // Add the code-completion token and finish the lexing normally so that
+ // normal code-completion occurs again with the expanded tokens.
+ ArgTokens.push_back(Tok);
+ // Add a marker EOF token to the end of the token list.
+ Token EOFTok;
+ EOFTok.startToken();
+ EOFTok.setKind(tok::eof);
+ EOFTok.setLocation(Tok.getLocation());
+ EOFTok.setLength(0);
+ ArgTokens.push_back(EOFTok);
+ ++NumActuals;
+ // "Fill out" the other arguments.
+ for (; NumActuals < MI->getNumArgs(); ++NumActuals)
+ ArgTokens.push_back(EOFTok);
+ return MacroArgs::create(MI, ArgTokens.data(), ArgTokens.size(),
+ /*isVarargsElided=*/false, *this);
}
if (Tok.is(tok::eof) || Tok.is(tok::eod)) { // "#if f(<eof>" & "#if f(\n"
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index cff9d6b4a9..858a001d43 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -6857,9 +6857,8 @@ void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
// FIXME: In the future, we could provide "overload" results, much like we
// do for function calls.
- CodeCompleteOrdinaryName(S,
- S->getFnParent()? Sema::PCC_RecoveryInFunction
- : Sema::PCC_Namespace);
+ // Now just ignore this. There will be another code-completion callback
+ // for the expanded tokens.
}
void Sema::CodeCompleteNaturalLanguage() {
diff --git a/test/Index/complete-macro-args.c b/test/Index/complete-macro-args.c
new file mode 100644
index 0000000000..ca36af1f10
--- /dev/null
+++ b/test/Index/complete-macro-args.c
@@ -0,0 +1,22 @@
+struct Point {
+ float x;
+ float y;
+ float z;
+};
+
+#define MACRO2(x) x
+#define MACRO(x) MACRO2(x)
+
+void test(struct Point *p) {
+ p->x;
+ MACRO(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
+// CHECK: FieldDecl:{ResultType float}{TypedText x} (35)
+// CHECK-NEXT: FieldDecl:{ResultType float}{TypedText y} (35)
+// CHECK-NEXT: FieldDecl:{ResultType float}{TypedText z} (35)
+// CHECK-NEXT: Completion contexts:
+// CHECK-NEXT: Arrow member access
+// CHECK-NEXT: Container Kind: StructDecl