]> granicus.if.org Git - clang/commitdiff
[Lex] Fix crash on code completion in comment in included file.
authorVolodymyr Sapsai <vsapsai@apple.com>
Fri, 19 Jan 2018 23:41:47 +0000 (23:41 +0000)
committerVolodymyr Sapsai <vsapsai@apple.com>
Fri, 19 Jan 2018 23:41:47 +0000 (23:41 +0000)
This fixes PR32732 by updating CurLexerKind to reflect available lexers.
We were hitting null pointer in Preprocessor::Lex because CurLexerKind
was CLK_Lexer but CurLexer was null. And we set it to null in
Preprocessor::HandleEndOfFile when exiting a file with code completion
point.

To reproduce the crash it is important for a comment to be inside a
class specifier. In this case in Parser::ParseClassSpecifier we improve
error recovery by pushing a semicolon token back into the preprocessor
and later on try to lex a token because we haven't reached the end of
file.

Also clang crashes only on code completion in included file, i.e. when
IncludeMacroStack is not empty. Though we reset CurLexer even if include
stack is empty. The difference is that during pushing back a semicolon
token, preprocessor calls EnterCachingLexMode which decides it is
already in caching mode because various lexers are null and
IncludeMacroStack is not empty. As the result, CurLexerKind remains
CLK_Lexer instead of updating to CLK_CachingLexer.

rdar://problem/34787685

Reviewers: akyrtzi, doug.gregor, arphaman

Reviewed By: arphaman

Subscribers: cfe-commits, kfunk, arphaman, nemanjai, kbarton

Differential Revision: https://reviews.llvm.org/D41688

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@323008 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Lex/PPCaching.cpp
lib/Lex/PPLexerChange.cpp
test/CodeCompletion/Inputs/comments.h [new file with mode: 0644]
test/CodeCompletion/comments.cpp [new file with mode: 0644]

index f5e8cdc25d388f4723b5ec21c9e43f862c72cd7b..9758557d7b4481182130c508ced0bf47f6bd5d45 100644 (file)
@@ -105,8 +105,10 @@ void Preprocessor::CachingLex(Token &Result) {
 }
 
 void Preprocessor::EnterCachingLexMode() {
-  if (InCachingLexMode())
+  if (InCachingLexMode()) {
+    assert(CurLexerKind == CLK_CachingLexer && "Unexpected lexer kind");
     return;
+  }
 
   PushIncludeMacroStack();
   CurLexerKind = CLK_CachingLexer;
index e484e9c4c3a384813b3307447abd01e315428ac7..f21787338b37969ffcbef27d829afaccf9e7ba0f 100644 (file)
@@ -444,6 +444,7 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
       }
 
       CurPPLexer = nullptr;
+      recomputeCurLexerKind();
       return true;
     }
 
diff --git a/test/CodeCompletion/Inputs/comments.h b/test/CodeCompletion/Inputs/comments.h
new file mode 100644 (file)
index 0000000..7b4b5da
--- /dev/null
@@ -0,0 +1,4 @@
+// PR32732
+struct B {
+  // <- code completion
+};
diff --git a/test/CodeCompletion/comments.cpp b/test/CodeCompletion/comments.cpp
new file mode 100644 (file)
index 0000000..21f1465
--- /dev/null
@@ -0,0 +1,13 @@
+// Note: the run lines follow their respective tests, since line/column
+// matter in this test.
+
+#include "comments.h"
+
+struct A {
+  // <- code completion
+  /* <- code completion */
+};
+
+// RUN: %clang_cc1 -I %S/Inputs -fsyntax-only -code-completion-at=%s:7:6 %s
+// RUN: %clang_cc1 -I %S/Inputs -fsyntax-only -code-completion-at=%s:8:6 %s
+// RUN: %clang_cc1 -I %S/Inputs -fsyntax-only -code-completion-at=%S/Inputs/comments.h:3:6 %s