summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2012-12-22 04:48:10 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2012-12-22 04:48:10 +0000
commitbb06b5000b9639a92e92c368ff3e5e5f8bb1e724 (patch)
treef282b3def1e064a335e68968195697f898ebba59
parentac504561cd888455a48bf85d21ada20a932ebd94 (diff)
downloadclang-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.cpp43
-rw-r--r--lib/Lex/PPMacroExpansion.cpp4
-rw-r--r--test/Index/complete-macro-args.c23
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