From 75f6cd2b796af85632aacb78ce74e1f06388920e Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Thu, 18 Aug 2011 19:41:28 +0000 Subject: [PATCH] [libclang] Support code-completion inside macro arguments. llvm-svn: 137973 --- .../include/clang/Lex/CodeCompletionHandler.h | 4 ++++ clang/lib/Lex/PPMacroExpansion.cpp | 18 ++++++++++++++- clang/lib/Sema/SemaCodeComplete.cpp | 5 ++--- clang/test/Index/complete-macro-args.c | 22 +++++++++++++++++++ 4 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 clang/test/Index/complete-macro-args.c diff --git a/clang/include/clang/Lex/CodeCompletionHandler.h b/clang/include/clang/Lex/CodeCompletionHandler.h index d28a3aa7d630..d876776c927c 100644 --- a/clang/include/clang/Lex/CodeCompletionHandler.h +++ b/clang/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/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index eaab73edc444..fd5b4c2efa28 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/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(" & "#if f(\n" diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index cff9d6b4a940..858a001d439d 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/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/clang/test/Index/complete-macro-args.c b/clang/test/Index/complete-macro-args.c new file mode 100644 index 000000000000..ca36af1f1043 --- /dev/null +++ b/clang/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