mirror of
https://github.com/intel/llvm.git
synced 2026-01-27 06:06:34 +08:00
[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
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -12,8 +12,17 @@ void test(struct Point *p) {
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user