From e5cdfe0ea82a4f97d01175d67ac1cb6b87d0a56e Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 23 Aug 2017 19:56:39 +0000 Subject: Merging r311330: ------------------------------------------------------------------------ r311330 | ibiryukov | 2017-08-21 05:03:08 -0700 (Mon, 21 Aug 2017) | 16 lines Fixed a crash on replaying Preamble's PP conditional stack. Summary: The crash occurs when the first token after a preamble is a macro expansion. Fixed by moving replayPreambleConditionalStack from Parser into Preprocessor. It is now called right after the predefines file is processed. Reviewers: erikjv, bkramer, klimek, yvvan Reviewed By: bkramer Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D36872 ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/cfe/branches/release_50@311591 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Lex/Preprocessor.h | 8 ++++---- lib/Lex/PPLexerChange.cpp | 13 ++++++++++++- lib/Lex/Preprocessor.cpp | 2 ++ lib/Parse/Parser.cpp | 2 -- test/Index/preamble-conditionals-crash.cpp | 12 ++++++++++++ test/Index/preamble-conditionals.cpp | 8 ++++++++ 6 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 test/Index/preamble-conditionals-crash.cpp create mode 100644 test/Index/preamble-conditionals.cpp diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index a058fbfbb4..dba4b80f60 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -1048,10 +1048,6 @@ public: /// which implicitly adds the builtin defines etc. void EnterMainSourceFile(); - /// \brief After parser warm-up, initialize the conditional stack from - /// the preamble. - void replayPreambleConditionalStack(); - /// \brief Inform the preprocessor callbacks that processing is complete. void EndSourceFile(); @@ -2025,6 +2021,10 @@ public: } private: + /// \brief After processing predefined file, initialize the conditional stack from + /// the preamble. + void replayPreambleConditionalStack(); + // Macro handling. void HandleDefineDirective(Token &Tok, bool ImmediatelyAfterTopLevelIfndef); void HandleUndefDirective(); diff --git a/lib/Lex/PPLexerChange.cpp b/lib/Lex/PPLexerChange.cpp index 5a589d6a17..36d7028da6 100644 --- a/lib/Lex/PPLexerChange.cpp +++ b/lib/Lex/PPLexerChange.cpp @@ -458,10 +458,16 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) { SourceMgr.setNumCreatedFIDsForFileID(CurPPLexer->getFileID(), NumFIDs); } + bool ExitedFromPredefinesFile = false; FileID ExitedFID; - if (Callbacks && !isEndOfMacro && CurPPLexer) + if (!isEndOfMacro && CurPPLexer) { ExitedFID = CurPPLexer->getFileID(); + assert(PredefinesFileID.isValid() && + "HandleEndOfFile is called before PredefinesFileId is set"); + ExitedFromPredefinesFile = (PredefinesFileID == ExitedFID); + } + if (LeavingSubmodule) { // We're done with this submodule. Module *M = LeaveSubmodule(/*ForPragma*/false); @@ -489,6 +495,11 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) { PPCallbacks::ExitFile, FileType, ExitedFID); } + // Restore conditional stack from the preamble right after exiting from the + // predefines file. + if (ExitedFromPredefinesFile) + replayPreambleConditionalStack(); + // Client should lex another token unless we generated an EOM. return LeavingSubmodule; } diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index d1dc8e1c00..7979be773a 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -540,6 +540,8 @@ void Preprocessor::EnterMainSourceFile() { void Preprocessor::replayPreambleConditionalStack() { // Restore the conditional stack from the preamble, if there is one. if (PreambleConditionalStack.isReplaying()) { + assert(CurPPLexer && + "CurPPLexer is null when calling replayPreambleConditionalStack."); CurPPLexer->setConditionalLevels(PreambleConditionalStack.getStack()); PreambleConditionalStack.doneReplaying(); } diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 4aa9a59719..1ed7ef9663 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -516,8 +516,6 @@ void Parser::Initialize() { // Prime the lexer look-ahead. ConsumeToken(); - - PP.replayPreambleConditionalStack(); } void Parser::LateTemplateParserCleanupCallback(void *P) { diff --git a/test/Index/preamble-conditionals-crash.cpp b/test/Index/preamble-conditionals-crash.cpp new file mode 100644 index 0000000000..6b18c87d19 --- /dev/null +++ b/test/Index/preamble-conditionals-crash.cpp @@ -0,0 +1,12 @@ +#ifndef HEADER_GUARD + +#define FOO int aba; +FOO + +#endif +// RUN: env CINDEXTEST_EDITING=1 c-index-test -test-load-source-reparse 5 \ +// RUN: local -std=c++14 %s 2>&1 \ +// RUN: | FileCheck %s --implicit-check-not "libclang: crash detected" \ +// RUN: --implicit-check-not "error:" +// CHECK: macro expansion=FOO:3:9 Extent=[4:1 - 4:4] +// CHECK: VarDecl=aba:4:1 (Definition) Extent=[4:1 - 4:4] diff --git a/test/Index/preamble-conditionals.cpp b/test/Index/preamble-conditionals.cpp new file mode 100644 index 0000000000..81ef8265e8 --- /dev/null +++ b/test/Index/preamble-conditionals.cpp @@ -0,0 +1,8 @@ +// RUN: env CINDEXTEST_EDITING=1 c-index-test -test-load-source local %s 2>&1 \ +// RUN: | FileCheck %s --implicit-check-not "error:" +#ifndef FOO_H +#define FOO_H + +void foo(); + +#endif -- cgit v1.2.3