diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Lex/Lexer.cpp | 22 | ||||
-rw-r--r-- | lib/Lex/PreprocessorLexer.cpp | 2 |
2 files changed, 23 insertions, 1 deletions
diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp index e6e7ca5ee1..7983a6b3e8 100644 --- a/lib/Lex/Lexer.cpp +++ b/lib/Lex/Lexer.cpp @@ -2595,8 +2595,14 @@ LexNextToken: // Read the PP instance variable into an automatic variable, because // LexEndOfFile will often delete 'this'. Preprocessor *PPCache = PP; + bool EnableIncludedEOFCache = EnableIncludedEOF; if (LexEndOfFile(Result, CurPtr-1)) // Retreat back into the file. return; // Got a token to return. + + if (EnableIncludedEOFCache) { + Result.setKind(tok::included_eof); + return; + } assert(PPCache && "Raw buffer::LexEndOfFile should return a token"); return PPCache->Lex(Result); } @@ -3234,5 +3240,21 @@ HandleDirective: } goto LexNextToken; // GCC isn't tail call eliminating. } + + if (PreprocessorLexer *PPLex = PP->getCurrentLexer()) { + // If we #include something that contributes no tokens at all, return with + // a tok::included_eof instead of recursively continuing lexing. + // This avoids a stack overflow with a sequence of many empty #includes. + PPLex->setEnableIncludedEOF(true); + PP->Lex(Result); + if (Result.isNot(tok::included_eof)) { + if (Result.isNot(tok::eof) && Result.isNot(tok::eod)) + PPLex->setEnableIncludedEOF(false); + return; + } + if (PP->isCurrentLexer(this)) + goto LexNextToken; + } + return PP->Lex(Result); } diff --git a/lib/Lex/PreprocessorLexer.cpp b/lib/Lex/PreprocessorLexer.cpp index a64c84d6bb..390d4c4523 100644 --- a/lib/Lex/PreprocessorLexer.cpp +++ b/lib/Lex/PreprocessorLexer.cpp @@ -22,7 +22,7 @@ void PreprocessorLexer::anchor() { } PreprocessorLexer::PreprocessorLexer(Preprocessor *pp, FileID fid) : PP(pp), FID(fid), InitialNumSLocEntries(0), ParsingPreprocessorDirective(false), - ParsingFilename(false), LexingRawMode(false) { + ParsingFilename(false), LexingRawMode(false), EnableIncludedEOF(false) { if (pp) InitialNumSLocEntries = pp->getSourceManager().local_sloc_entry_size(); } |