diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-12-22 04:48:10 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2012-12-22 04:48:10 +0000 |
commit | bb06b5000b9639a92e92c368ff3e5e5f8bb1e724 (patch) | |
tree | f282b3def1e064a335e68968195697f898ebba59 | |
parent | ac504561cd888455a48bf85d21ada20a932ebd94 (diff) | |
download | clang-bb06b5000b9639a92e92c368ff3e5e5f8bb1e724.tar.gz clang-bb06b5000b9639a92e92c368ff3e5e5f8bb1e724.tar.bz2 clang-bb06b5000b9639a92e92c368ff3e5e5f8bb1e724.tar.xz |
[libclang] Fix crash when code-completing a macro invocation that
reached EOF and did not expand the argument into the source context.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@170980 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Lex/PPLexerChange.cpp | 43 | ||||
-rw-r--r-- | lib/Lex/PPMacroExpansion.cpp | 4 | ||||
-rw-r--r-- | test/Index/complete-macro-args.c | 23 |
3 files changed, 55 insertions, 15 deletions
diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp index 552df7127f..0ce67dce7e 100644 --- a/lib/Lex/PPLexerChange.cpp +++ b/lib/Lex/PPLexerChange.cpp @@ -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) { - PushIncludeMacroStack(); - CurDirLookup = 0; - + TokenLexer *TokLexer; if (NumCachedTokenLexers == 0) { - CurTokenLexer.reset(new TokenLexer(Tok, ILEnd, Macro, Args, *this)); + TokLexer = new TokenLexer(Tok, ILEnd, Macro, Args, *this); } else { - CurTokenLexer.reset(TokenLexerCache[--NumCachedTokenLexers]); - CurTokenLexer->Init(Tok, ILEnd, Macro, Args); + TokLexer = TokenLexerCache[--NumCachedTokenLexers]; + TokLexer->Init(Tok, ILEnd, Macro, Args); } + + PushIncludeMacroStack(); + CurDirLookup = 0; + 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) { - // Save our current state. - PushIncludeMacroStack(); - CurDirLookup = 0; - // Create a macro expander to expand from the specified token stream. + TokenLexer *TokLexer; if (NumCachedTokenLexers == 0) { - CurTokenLexer.reset(new TokenLexer(Toks, NumToks, DisableMacroExpansion, - OwnsTokens, *this)); + TokLexer = new TokenLexer(Toks, NumToks, DisableMacroExpansion, + OwnsTokens, *this); } else { - CurTokenLexer.reset(TokenLexerCache[--NumCachedTokenLexers]); - CurTokenLexer->Init(Toks, NumToks, DisableMacroExpansion, OwnsTokens); + TokLexer = TokenLexerCache[--NumCachedTokenLexers]; + TokLexer->Init(Toks, NumToks, DisableMacroExpansion, OwnsTokens); } + + // Save our current state. + PushIncludeMacroStack(); + CurDirLookup = 0; + 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(); diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index b7ea30e83c..8ba8318fe9 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -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)) { diff --git a/test/Index/complete-macro-args.c b/test/Index/complete-macro-args.c index 62a42ffa21..0b4dd20734 100644 --- a/test/Index/complete-macro-args.c +++ b/test/Index/complete-macro-args.c @@ -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 |