diff options
| author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-12-21 01:17:20 +0000 |
|---|---|---|
| committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-12-21 01:17:20 +0000 |
| commit | c1d9a67e2b2becce5c26e02a454b27df79e1b022 (patch) | |
| tree | de1dc52be37e10d7e6f895ec773fb0ca3c564a6a /clang/lib | |
| parent | 93f778d2bd285311b36c8b114f099d82744bdd4c (diff) | |
| download | bcm5719-llvm-c1d9a67e2b2becce5c26e02a454b27df79e1b022.tar.gz bcm5719-llvm-c1d9a67e2b2becce5c26e02a454b27df79e1b022.zip | |
[libclang] Make sure we can code-complete inside a macro argument even though
the macro invocation is not fully formed.
rdar://11290992
llvm-svn: 170824
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Lex/PPMacroExpansion.cpp | 40 |
1 files changed, 26 insertions, 14 deletions
diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index d2f1b5f05d7..a523612fbdb 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -497,9 +497,13 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName, // 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 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName, 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 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName, 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 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName, 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 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName, // #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 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName, 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); |

