forked from OSchip/llvm-project
[libclang] Fix crash when code-completing a macro invocation that
reached EOF and did not expand the argument into the source context. llvm-svn: 170980
This commit is contained in:
parent
430a938fde
commit
9fd1571e7a
|
@ -158,15 +158,17 @@ void Preprocessor::EnterSourceFileWithPTH(PTHLexer *PL,
|
|||
/// tokens from it instead of the current buffer.
|
||||
void Preprocessor::EnterMacro(Token &Tok, SourceLocation ILEnd,
|
||||
MacroInfo *Macro, MacroArgs *Args) {
|
||||
TokenLexer *TokLexer;
|
||||
if (NumCachedTokenLexers == 0) {
|
||||
TokLexer = new TokenLexer(Tok, ILEnd, Macro, Args, *this);
|
||||
} else {
|
||||
TokLexer = TokenLexerCache[--NumCachedTokenLexers];
|
||||
TokLexer->Init(Tok, ILEnd, Macro, Args);
|
||||
}
|
||||
|
||||
PushIncludeMacroStack();
|
||||
CurDirLookup = 0;
|
||||
|
||||
if (NumCachedTokenLexers == 0) {
|
||||
CurTokenLexer.reset(new TokenLexer(Tok, ILEnd, Macro, Args, *this));
|
||||
} else {
|
||||
CurTokenLexer.reset(TokenLexerCache[--NumCachedTokenLexers]);
|
||||
CurTokenLexer->Init(Tok, ILEnd, Macro, Args);
|
||||
}
|
||||
CurTokenLexer.reset(TokLexer);
|
||||
if (CurLexerKind != CLK_LexAfterModuleImport)
|
||||
CurLexerKind = CLK_TokenLexer;
|
||||
}
|
||||
|
@ -186,18 +188,20 @@ void Preprocessor::EnterMacro(Token &Tok, SourceLocation ILEnd,
|
|||
void Preprocessor::EnterTokenStream(const Token *Toks, unsigned NumToks,
|
||||
bool DisableMacroExpansion,
|
||||
bool OwnsTokens) {
|
||||
// Create a macro expander to expand from the specified token stream.
|
||||
TokenLexer *TokLexer;
|
||||
if (NumCachedTokenLexers == 0) {
|
||||
TokLexer = new TokenLexer(Toks, NumToks, DisableMacroExpansion,
|
||||
OwnsTokens, *this);
|
||||
} else {
|
||||
TokLexer = TokenLexerCache[--NumCachedTokenLexers];
|
||||
TokLexer->Init(Toks, NumToks, DisableMacroExpansion, OwnsTokens);
|
||||
}
|
||||
|
||||
// Save our current state.
|
||||
PushIncludeMacroStack();
|
||||
CurDirLookup = 0;
|
||||
|
||||
// Create a macro expander to expand from the specified token stream.
|
||||
if (NumCachedTokenLexers == 0) {
|
||||
CurTokenLexer.reset(new TokenLexer(Toks, NumToks, DisableMacroExpansion,
|
||||
OwnsTokens, *this));
|
||||
} else {
|
||||
CurTokenLexer.reset(TokenLexerCache[--NumCachedTokenLexers]);
|
||||
CurTokenLexer->Init(Toks, NumToks, DisableMacroExpansion, OwnsTokens);
|
||||
}
|
||||
CurTokenLexer.reset(TokLexer);
|
||||
if (CurLexerKind != CLK_LexAfterModuleImport)
|
||||
CurLexerKind = CLK_TokenLexer;
|
||||
}
|
||||
|
@ -328,6 +332,17 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
|
|||
CurLexer->BufferPtr = EndPos;
|
||||
CurLexer->FormTokenWithChars(Result, EndPos, tok::eof);
|
||||
|
||||
if (isCodeCompletionEnabled()) {
|
||||
// Inserting the code-completion point increases the source buffer by 1,
|
||||
// but the main FileID was created before inserting the point.
|
||||
// Compensate by reducing the EOF location by 1, otherwise the location
|
||||
// will point to the next FileID.
|
||||
// FIXME: This is hacky, the code-completion point should probably be
|
||||
// inserted before the main FileID is created.
|
||||
if (CurLexer->getFileLoc() == CodeCompletionFileLoc)
|
||||
Result.setLocation(Result.getLocation().getLocWithOffset(-1));
|
||||
}
|
||||
|
||||
if (!isIncrementalProcessingEnabled())
|
||||
// We're done with lexing.
|
||||
CurLexer.reset();
|
||||
|
|
|
@ -528,6 +528,10 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName,
|
|||
MacroName = Tok;
|
||||
return 0;
|
||||
} else {
|
||||
// Do not lose the EOF/EOD.
|
||||
Token *Toks = new Token[1];
|
||||
Toks[0] = Tok;
|
||||
EnterTokenStream(Toks, 1, true, true);
|
||||
break;
|
||||
}
|
||||
} else if (Tok.is(tok::r_paren)) {
|
||||
|
|
|
@ -14,11 +14,25 @@ void test(struct Point *p) {
|
|||
|
||||
#define MACRO3(x,y,z) x;y;z
|
||||
|
||||
void test(struct Point *p) {
|
||||
void test2(struct Point *p) {
|
||||
MACRO3(p->x);
|
||||
MACRO3(p->x
|
||||
}
|
||||
|
||||
#define VGM(...) 0
|
||||
#define VGM2(...) __VA_ARGS__
|
||||
|
||||
// These need to be last, to test proper handling of EOF.
|
||||
#ifdef EOF_TEST1
|
||||
void test3(struct Point *p) {
|
||||
VGM(1,2, p->x
|
||||
|
||||
#elif EOF_TEST2
|
||||
void test3(struct Point *p) {
|
||||
VGM2(VGM(1,2, p->x
|
||||
|
||||
#endif
|
||||
|
||||
// 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
|
||||
|
@ -29,3 +43,10 @@ void test(struct Point *p) {
|
|||
// CHECK-NEXT: Completion contexts:
|
||||
// CHECK-NEXT: Arrow member access
|
||||
// CHECK-NEXT: Container Kind: StructDecl
|
||||
|
||||
// With these, code-completion is unknown because the macro argument (and the
|
||||
// completion point) is not expanded by the macro definition.
|
||||
// RUN: c-index-test -code-completion-at=%s:28:15 %s -DEOF_TEST1 | FileCheck %s -check-prefix=CHECK-EOF
|
||||
// RUN: c-index-test -code-completion-at=%s:32:20 %s -DEOF_TEST2 | FileCheck %s -check-prefix=CHECK-EOF
|
||||
// CHECK-EOF: Completion contexts:
|
||||
// CHECK-EOF: Unknown
|
||||
|
|
Loading…
Reference in New Issue