forked from OSchip/llvm-project
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 llvm-svn: 311330
This commit is contained in:
parent
7bc77e87c8
commit
f315000613
|
@ -1049,10 +1049,6 @@ public:
|
||||||
/// which implicitly adds the builtin defines etc.
|
/// which implicitly adds the builtin defines etc.
|
||||||
void EnterMainSourceFile();
|
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.
|
/// \brief Inform the preprocessor callbacks that processing is complete.
|
||||||
void EndSourceFile();
|
void EndSourceFile();
|
||||||
|
|
||||||
|
@ -2026,6 +2022,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/// \brief After processing predefined file, initialize the conditional stack from
|
||||||
|
/// the preamble.
|
||||||
|
void replayPreambleConditionalStack();
|
||||||
|
|
||||||
// Macro handling.
|
// Macro handling.
|
||||||
void HandleDefineDirective(Token &Tok, bool ImmediatelyAfterTopLevelIfndef);
|
void HandleDefineDirective(Token &Tok, bool ImmediatelyAfterTopLevelIfndef);
|
||||||
void HandleUndefDirective();
|
void HandleUndefDirective();
|
||||||
|
|
|
@ -458,10 +458,16 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
|
||||||
SourceMgr.setNumCreatedFIDsForFileID(CurPPLexer->getFileID(), NumFIDs);
|
SourceMgr.setNumCreatedFIDsForFileID(CurPPLexer->getFileID(), NumFIDs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ExitedFromPredefinesFile = false;
|
||||||
FileID ExitedFID;
|
FileID ExitedFID;
|
||||||
if (Callbacks && !isEndOfMacro && CurPPLexer)
|
if (!isEndOfMacro && CurPPLexer) {
|
||||||
ExitedFID = CurPPLexer->getFileID();
|
ExitedFID = CurPPLexer->getFileID();
|
||||||
|
|
||||||
|
assert(PredefinesFileID.isValid() &&
|
||||||
|
"HandleEndOfFile is called before PredefinesFileId is set");
|
||||||
|
ExitedFromPredefinesFile = (PredefinesFileID == ExitedFID);
|
||||||
|
}
|
||||||
|
|
||||||
if (LeavingSubmodule) {
|
if (LeavingSubmodule) {
|
||||||
// We're done with this submodule.
|
// We're done with this submodule.
|
||||||
Module *M = LeaveSubmodule(/*ForPragma*/false);
|
Module *M = LeaveSubmodule(/*ForPragma*/false);
|
||||||
|
@ -489,6 +495,11 @@ bool Preprocessor::HandleEndOfFile(Token &Result, bool isEndOfMacro) {
|
||||||
PPCallbacks::ExitFile, FileType, ExitedFID);
|
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.
|
// Client should lex another token unless we generated an EOM.
|
||||||
return LeavingSubmodule;
|
return LeavingSubmodule;
|
||||||
}
|
}
|
||||||
|
|
|
@ -540,6 +540,8 @@ void Preprocessor::EnterMainSourceFile() {
|
||||||
void Preprocessor::replayPreambleConditionalStack() {
|
void Preprocessor::replayPreambleConditionalStack() {
|
||||||
// Restore the conditional stack from the preamble, if there is one.
|
// Restore the conditional stack from the preamble, if there is one.
|
||||||
if (PreambleConditionalStack.isReplaying()) {
|
if (PreambleConditionalStack.isReplaying()) {
|
||||||
|
assert(CurPPLexer &&
|
||||||
|
"CurPPLexer is null when calling replayPreambleConditionalStack.");
|
||||||
CurPPLexer->setConditionalLevels(PreambleConditionalStack.getStack());
|
CurPPLexer->setConditionalLevels(PreambleConditionalStack.getStack());
|
||||||
PreambleConditionalStack.doneReplaying();
|
PreambleConditionalStack.doneReplaying();
|
||||||
}
|
}
|
||||||
|
|
|
@ -516,8 +516,6 @@ void Parser::Initialize() {
|
||||||
|
|
||||||
// Prime the lexer look-ahead.
|
// Prime the lexer look-ahead.
|
||||||
ConsumeToken();
|
ConsumeToken();
|
||||||
|
|
||||||
PP.replayPreambleConditionalStack();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Parser::LateTemplateParserCleanupCallback(void *P) {
|
void Parser::LateTemplateParserCleanupCallback(void *P) {
|
||||||
|
|
|
@ -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]
|
|
@ -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
|
Loading…
Reference in New Issue