[PATCH] D53866: [Preamble] Fix preamble for circular #includes
Nikolai Kosjar via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 30 07:12:14 PDT 2018
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;
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D53866.171689.patch
Type: text/x-patch
Size: 2491 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20181030/fdecebc2/attachment.bin>
More information about the cfe-commits
mailing list