nik created this revision. Herald added subscribers: cfe-commits, arphaman.
If a header file was processed for the second time, we could end up with a wrong conditional stack and skipped ranges: In the particular example, if the header guard is evaluated the second time and it is decided to skip the conditional block, the corresponding "#endif" is never seen since the preamble does not include it and we end up in the Tok.is(tok::eof) case with a wrong conditional stack. Fix this by resetting the conditional state in such a case. Repository: rC Clang https://reviews.llvm.org/D53866 Files: lib/Lex/PPDirectives.cpp test/Index/preamble-cyclic-include.cpp Index: test/Index/preamble-cyclic-include.cpp =================================================================== --- /dev/null +++ test/Index/preamble-cyclic-include.cpp @@ -0,0 +1,8 @@ +// RUN: env CINDEXTEST_EDITING=1 c-index-test -test-annotate-tokens=%s:4:1:8:1 %s 2>&1 | FileCheck %s +// CHECK-NOT: error: unterminated conditional directive +// CHECK-NOT: Skipping: [4:1 - 8:7] +#ifndef A_H +#define A_H +# include "preamble-cyclic-include.cpp" +int bar(); +#endif Index: lib/Lex/PPDirectives.cpp =================================================================== --- lib/Lex/PPDirectives.cpp +++ lib/Lex/PPDirectives.cpp @@ -361,6 +361,14 @@ } } +static bool isMainFileIncludedAgain(const SourceManager &sourceManager, + HeaderSearch &headerSearch, + const FileEntry *fileEntry) { + return sourceManager.translateFile(fileEntry) == + sourceManager.getMainFileID() && + headerSearch.getFileInfo(fileEntry).NumIncludes > 1; +} + /// SkipExcludedConditionalBlock - We just read a \#if or related directive and /// decided that the subsequent tokens are in the \#if'd out portion of the /// file. Lex the rest of the file, until we see an \#endif. If @@ -377,6 +385,8 @@ ++NumSkipped; assert(!CurTokenLexer && CurPPLexer && "Lexing a macro, not a file?"); + const auto InitialConditionalStack = CurPPLexer->ConditionalStack; + if (PreambleConditionalStack.reachedEOFWhileSkipping()) PreambleConditionalStack.clearSkipInfo(); else @@ -407,9 +417,16 @@ // We don't emit errors for unterminated conditionals here, // Lexer::LexEndOfFile can do that propertly. // Just return and let the caller lex after this #include. - if (PreambleConditionalStack.isRecording()) - PreambleConditionalStack.SkipInfo.emplace( - HashTokenLoc, IfTokenLoc, FoundNonSkipPortion, FoundElse, ElseLoc); + if (PreambleConditionalStack.isRecording()) { + if (isMainFileIncludedAgain(getSourceManager(), HeaderInfo, + CurLexer->getFileEntry())) { + CurPPLexer->ConditionalStack = InitialConditionalStack; + } else { + PreambleConditionalStack.SkipInfo.emplace(HashTokenLoc, IfTokenLoc, + FoundNonSkipPortion, + FoundElse, ElseLoc); + } + } break; }
Index: test/Index/preamble-cyclic-include.cpp =================================================================== --- /dev/null +++ test/Index/preamble-cyclic-include.cpp @@ -0,0 +1,8 @@ +// RUN: env CINDEXTEST_EDITING=1 c-index-test -test-annotate-tokens=%s:4:1:8:1 %s 2>&1 | FileCheck %s +// CHECK-NOT: error: unterminated conditional directive +// CHECK-NOT: Skipping: [4:1 - 8:7] +#ifndef A_H +#define A_H +# include "preamble-cyclic-include.cpp" +int bar(); +#endif Index: lib/Lex/PPDirectives.cpp =================================================================== --- lib/Lex/PPDirectives.cpp +++ lib/Lex/PPDirectives.cpp @@ -361,6 +361,14 @@ } } +static bool isMainFileIncludedAgain(const SourceManager &sourceManager, + HeaderSearch &headerSearch, + const FileEntry *fileEntry) { + return sourceManager.translateFile(fileEntry) == + sourceManager.getMainFileID() && + headerSearch.getFileInfo(fileEntry).NumIncludes > 1; +} + /// SkipExcludedConditionalBlock - We just read a \#if or related directive and /// decided that the subsequent tokens are in the \#if'd out portion of the /// file. Lex the rest of the file, until we see an \#endif. If @@ -377,6 +385,8 @@ ++NumSkipped; assert(!CurTokenLexer && CurPPLexer && "Lexing a macro, not a file?"); + const auto InitialConditionalStack = CurPPLexer->ConditionalStack; + if (PreambleConditionalStack.reachedEOFWhileSkipping()) PreambleConditionalStack.clearSkipInfo(); else @@ -407,9 +417,16 @@ // We don't emit errors for unterminated conditionals here, // Lexer::LexEndOfFile can do that propertly. // Just return and let the caller lex after this #include. - if (PreambleConditionalStack.isRecording()) - PreambleConditionalStack.SkipInfo.emplace( - HashTokenLoc, IfTokenLoc, FoundNonSkipPortion, FoundElse, ElseLoc); + if (PreambleConditionalStack.isRecording()) { + if (isMainFileIncludedAgain(getSourceManager(), HeaderInfo, + CurLexer->getFileEntry())) { + CurPPLexer->ConditionalStack = InitialConditionalStack; + } else { + PreambleConditionalStack.SkipInfo.emplace(HashTokenLoc, IfTokenLoc, + FoundNonSkipPortion, + FoundElse, ElseLoc); + } + } break; }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits