r317308 - [preamble] Also record the "skipping" state of the preprocessor
Erik Verbruggen via cfe-commits
cfe-commits at lists.llvm.org
Fri Nov 3 02:40:08 PDT 2017
Author: erikjv
Date: Fri Nov 3 02:40:07 2017
New Revision: 317308
URL: http://llvm.org/viewvc/llvm-project?rev=317308&view=rev
Log:
[preamble] Also record the "skipping" state of the preprocessor
When a preamble ends in a conditional preprocessor block that is being
skipped, the preprocessor needs to continue skipping that block when
the preamble is used.
This fixes PR34570.
Added:
cfe/trunk/test/Index/preamble-conditionals-skipping.cpp
Modified:
cfe/trunk/include/clang/Lex/Preprocessor.h
cfe/trunk/lib/Lex/PPDirectives.cpp
cfe/trunk/lib/Lex/Preprocessor.cpp
cfe/trunk/lib/Serialization/ASTReader.cpp
cfe/trunk/lib/Serialization/ASTWriter.cpp
cfe/trunk/test/Index/preamble-conditionals-inverted.cpp
Modified: cfe/trunk/include/clang/Lex/Preprocessor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/Preprocessor.h?rev=317308&r1=317307&r2=317308&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/Preprocessor.h (original)
+++ cfe/trunk/include/clang/Lex/Preprocessor.h Fri Nov 3 02:40:07 2017
@@ -286,6 +286,23 @@ class Preprocessor {
/// This is used when loading a precompiled preamble.
std::pair<int, bool> SkipMainFilePreamble;
+public:
+ struct PreambleSkipInfo {
+ PreambleSkipInfo(SourceLocation HashTokenLoc, SourceLocation IfTokenLoc,
+ bool FoundNonSkipPortion, bool FoundElse,
+ SourceLocation ElseLoc)
+ : HashTokenLoc(HashTokenLoc), IfTokenLoc(IfTokenLoc),
+ FoundNonSkipPortion(FoundNonSkipPortion), FoundElse(FoundElse),
+ ElseLoc(ElseLoc) {}
+
+ SourceLocation HashTokenLoc;
+ SourceLocation IfTokenLoc;
+ bool FoundNonSkipPortion;
+ bool FoundElse;
+ SourceLocation ElseLoc;
+ };
+
+private:
class PreambleConditionalStackStore {
enum State {
Off = 0,
@@ -319,6 +336,12 @@ class Preprocessor {
bool hasRecordedPreamble() const { return !ConditionalStack.empty(); }
+ bool reachedEOFWhileSkipping() const { return SkipInfo.hasValue(); }
+
+ void clearSkipInfo() { SkipInfo.reset(); }
+
+ llvm::Optional<PreambleSkipInfo> SkipInfo;
+
private:
SmallVector<PPConditionalInfo, 4> ConditionalStack;
State ConditionalStackState;
@@ -1839,7 +1862,7 @@ private:
/// \p FoundElse is false, then \#else directives are ok, if not, then we have
/// already seen one so a \#else directive is a duplicate. When this returns,
/// the caller can lex the first valid token.
- void SkipExcludedConditionalBlock(const Token &HashToken,
+ void SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
SourceLocation IfTokenLoc,
bool FoundNonSkipPortion, bool FoundElse,
SourceLocation ElseLoc = SourceLocation());
@@ -2019,9 +2042,15 @@ public:
PreambleConditionalStack.setStack(s);
}
- void setReplayablePreambleConditionalStack(ArrayRef<PPConditionalInfo> s) {
+ void setReplayablePreambleConditionalStack(ArrayRef<PPConditionalInfo> s,
+ llvm::Optional<PreambleSkipInfo> SkipInfo) {
PreambleConditionalStack.startReplaying();
PreambleConditionalStack.setStack(s);
+ PreambleConditionalStack.SkipInfo = SkipInfo;
+ }
+
+ llvm::Optional<PreambleSkipInfo> getPreambleSkipInfo() const {
+ return PreambleConditionalStack.SkipInfo;
}
private:
Modified: cfe/trunk/lib/Lex/PPDirectives.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPDirectives.cpp?rev=317308&r1=317307&r2=317308&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPDirectives.cpp (original)
+++ cfe/trunk/lib/Lex/PPDirectives.cpp Fri Nov 3 02:40:07 2017
@@ -350,7 +350,7 @@ void Preprocessor::CheckEndOfDirective(c
/// If ElseOk is true, then \#else directives are ok, if not, then we have
/// already seen one so a \#else directive is a duplicate. When this returns,
/// the caller can lex the first valid token.
-void Preprocessor::SkipExcludedConditionalBlock(const Token &HashToken,
+void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
SourceLocation IfTokenLoc,
bool FoundNonSkipPortion,
bool FoundElse,
@@ -358,8 +358,11 @@ void Preprocessor::SkipExcludedCondition
++NumSkipped;
assert(!CurTokenLexer && CurPPLexer && "Lexing a macro, not a file?");
- CurPPLexer->pushConditionalLevel(IfTokenLoc, /*isSkipping*/false,
- FoundNonSkipPortion, FoundElse);
+ if (PreambleConditionalStack.reachedEOFWhileSkipping())
+ PreambleConditionalStack.clearSkipInfo();
+ else
+ CurPPLexer->pushConditionalLevel(IfTokenLoc, /*isSkipping*/ false,
+ FoundNonSkipPortion, FoundElse);
if (CurPTHLexer) {
PTHSkipExcludedConditionalBlock();
@@ -385,6 +388,9 @@ void Preprocessor::SkipExcludedCondition
// 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);
break;
}
@@ -554,7 +560,7 @@ void Preprocessor::SkipExcludedCondition
if (Callbacks)
Callbacks->SourceRangeSkipped(
- SourceRange(HashToken.getLocation(), CurPPLexer->getSourceLocation()),
+ SourceRange(HashTokenLoc, CurPPLexer->getSourceLocation()),
Tok.getLocation());
}
@@ -2676,7 +2682,8 @@ void Preprocessor::HandleIfdefDirective(
if (MacroNameTok.is(tok::eod)) {
// Skip code until we get to #endif. This helps with recovery by not
// emitting an error when the #endif is reached.
- SkipExcludedConditionalBlock(HashToken, DirectiveTok.getLocation(),
+ SkipExcludedConditionalBlock(HashToken.getLocation(),
+ DirectiveTok.getLocation(),
/*Foundnonskip*/ false, /*FoundElse*/ false);
return;
}
@@ -2725,7 +2732,8 @@ void Preprocessor::HandleIfdefDirective(
/*foundelse*/false);
} else {
// No, skip the contents of this block.
- SkipExcludedConditionalBlock(HashToken, DirectiveTok.getLocation(),
+ SkipExcludedConditionalBlock(HashToken.getLocation(),
+ DirectiveTok.getLocation(),
/*Foundnonskip*/ false,
/*FoundElse*/ false);
}
@@ -2772,7 +2780,7 @@ void Preprocessor::HandleIfDirective(Tok
/*foundnonskip*/true, /*foundelse*/false);
} else {
// No, skip the contents of this block.
- SkipExcludedConditionalBlock(HashToken, IfToken.getLocation(),
+ SkipExcludedConditionalBlock(HashToken.getLocation(), IfToken.getLocation(),
/*Foundnonskip*/ false,
/*FoundElse*/ false);
}
@@ -2837,7 +2845,8 @@ void Preprocessor::HandleElseDirective(T
}
// Finally, skip the rest of the contents of this block.
- SkipExcludedConditionalBlock(HashToken, CI.IfLoc, /*Foundnonskip*/ true,
+ SkipExcludedConditionalBlock(HashToken.getLocation(), CI.IfLoc,
+ /*Foundnonskip*/ true,
/*FoundElse*/ true, Result.getLocation());
}
@@ -2881,7 +2890,7 @@ void Preprocessor::HandleElifDirective(T
}
// Finally, skip the rest of the contents of this block.
- SkipExcludedConditionalBlock(HashToken, CI.IfLoc, /*Foundnonskip*/ true,
- /*FoundElse*/ CI.FoundElse,
- ElifToken.getLocation());
+ SkipExcludedConditionalBlock(
+ HashToken.getLocation(), CI.IfLoc, /*Foundnonskip*/ true,
+ /*FoundElse*/ CI.FoundElse, ElifToken.getLocation());
}
Modified: cfe/trunk/lib/Lex/Preprocessor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/Preprocessor.cpp?rev=317308&r1=317307&r2=317308&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/Preprocessor.cpp (original)
+++ cfe/trunk/lib/Lex/Preprocessor.cpp Fri Nov 3 02:40:07 2017
@@ -550,6 +550,13 @@ void Preprocessor::replayPreambleConditi
"CurPPLexer is null when calling replayPreambleConditionalStack.");
CurPPLexer->setConditionalLevels(PreambleConditionalStack.getStack());
PreambleConditionalStack.doneReplaying();
+ if (PreambleConditionalStack.reachedEOFWhileSkipping())
+ SkipExcludedConditionalBlock(
+ PreambleConditionalStack.SkipInfo->HashTokenLoc,
+ PreambleConditionalStack.SkipInfo->IfTokenLoc,
+ PreambleConditionalStack.SkipInfo->FoundNonSkipPortion,
+ PreambleConditionalStack.SkipInfo->FoundElse,
+ PreambleConditionalStack.SkipInfo->ElseLoc);
}
}
Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=317308&r1=317307&r2=317308&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Fri Nov 3 02:40:07 2017
@@ -2995,8 +2995,20 @@ ASTReader::ReadASTBlock(ModuleFile &F, u
case PP_CONDITIONAL_STACK:
if (!Record.empty()) {
+ unsigned Idx = 0, End = Record.size() - 1;
+ bool ReachedEOFWhileSkipping = Record[Idx++];
+ llvm::Optional<Preprocessor::PreambleSkipInfo> SkipInfo;
+ if (ReachedEOFWhileSkipping) {
+ SourceLocation HashToken = ReadSourceLocation(F, Record, Idx);
+ SourceLocation IfTokenLoc = ReadSourceLocation(F, Record, Idx);
+ bool FoundNonSkipPortion = Record[Idx++];
+ bool FoundElse = Record[Idx++];
+ SourceLocation ElseLoc = ReadSourceLocation(F, Record, Idx);
+ SkipInfo.emplace(HashToken, IfTokenLoc, FoundNonSkipPortion,
+ FoundElse, ElseLoc);
+ }
SmallVector<PPConditionalInfo, 4> ConditionalStack;
- for (unsigned Idx = 0, N = Record.size() - 1; Idx < N; /* in loop */) {
+ while (Idx < End) {
auto Loc = ReadSourceLocation(F, Record, Idx);
bool WasSkipping = Record[Idx++];
bool FoundNonSkip = Record[Idx++];
@@ -3004,7 +3016,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, u
ConditionalStack.push_back(
{Loc, WasSkipping, FoundNonSkip, FoundElse});
}
- PP.setReplayablePreambleConditionalStack(ConditionalStack);
+ PP.setReplayablePreambleConditionalStack(ConditionalStack, SkipInfo);
}
break;
Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=317308&r1=317307&r2=317308&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Fri Nov 3 02:40:07 2017
@@ -2407,6 +2407,17 @@ void ASTWriter::WritePreprocessor(const
if (PP.isRecordingPreamble() && PP.hasRecordedPreamble()) {
assert(!IsModule);
+ auto SkipInfo = PP.getPreambleSkipInfo();
+ if (SkipInfo.hasValue()) {
+ Record.push_back(true);
+ AddSourceLocation(SkipInfo->HashTokenLoc, Record);
+ AddSourceLocation(SkipInfo->IfTokenLoc, Record);
+ Record.push_back(SkipInfo->FoundNonSkipPortion);
+ Record.push_back(SkipInfo->FoundElse);
+ AddSourceLocation(SkipInfo->ElseLoc, Record);
+ } else {
+ Record.push_back(false);
+ }
for (const auto &Cond : PP.getPreambleConditionalStack()) {
AddSourceLocation(Cond.IfLoc, Record);
Record.push_back(Cond.WasSkipping);
Modified: cfe/trunk/test/Index/preamble-conditionals-inverted.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/preamble-conditionals-inverted.cpp?rev=317308&r1=317307&r2=317308&view=diff
==============================================================================
--- cfe/trunk/test/Index/preamble-conditionals-inverted.cpp (original)
+++ cfe/trunk/test/Index/preamble-conditionals-inverted.cpp Fri Nov 3 02:40:07 2017
@@ -3,6 +3,8 @@
// RUN: | FileCheck %s --implicit-check-not "error:"
#ifdef FOO_H
-void foo();
+void foo() {}
#endif
+
+int foo() { return 0; }
Added: cfe/trunk/test/Index/preamble-conditionals-skipping.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/preamble-conditionals-skipping.cpp?rev=317308&view=auto
==============================================================================
--- cfe/trunk/test/Index/preamble-conditionals-skipping.cpp (added)
+++ cfe/trunk/test/Index/preamble-conditionals-skipping.cpp Fri Nov 3 02:40:07 2017
@@ -0,0 +1,16 @@
+// 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 "error:"
+
+#ifdef MYCPLUSPLUS
+extern "C" {
+#endif
+
+#ifdef MYCPLUSPLUS
+}
+#endif
+
+int main()
+{
+ return 0;
+}
More information about the cfe-commits
mailing list