[PATCH] D53866: [Preamble] Fix preamble for circular #includes

2018-12-05 Thread Nikolai Kosjar via Phabricator via cfe-commits
nik marked 2 inline comments as done.
nik added inline comments.



Comment at: include/clang/Lex/Preprocessor.h:391
   } PreambleConditionalStack;
+  bool PreambleGenerationFailed = false;
 

ilya-biryukov wrote:
> There's a mechanism to handle preamble with errors, see 
> `PreprocessorOpts::AllowPCHWithCompilerErrors`.
> Maybe rely on it and avoid adding a different one?
I'm not sure how to make use of AllowPCHWithCompilerErrors. It's clearly meant 
as an input/readonly option - do you suggest setting that one to "false" in 
case we detect the cyclic include (and later checking for it...)? That feels a 
bit hacky. Have you meant something else?



Comment at: lib/Lex/PPDirectives.cpp:1945
+// Generate a fatal error to skip further processing.
+Diag(FilenameTok.getLocation(), diag::err_pp_error_opening_file) << ""
+ << "";

ilya-biryukov wrote:
> Maybe add a new error or find a more appropriate existing one to reuse?
> "Error opening file", especially without any arguments does not provide 
> enough context to figure out what went wrong.
> Maybe add a new error or find a more appropriate existing one to reuse?

As stated above, introducing a new diagnostic that the user will never face 
feels wrong, but that's just a preference. If you prefer a dedicated 
diagnostics, that's fine for me.

Checking the existing ones, there are not many fatal errors to choose from:

  err_pp_file_not_found
  err_pp_through_header_not_found
  err_pp_through_header_not_seen
  err_pp_pragma_hdrstop_not_seen
  err_pp_error_opening_file

The last one looks the best for me.

> "Error opening file", especially without any arguments does not provide 
> enough context to figure out what went wrong.

I've added some arguments which might be useful for debugging.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53866/new/

https://reviews.llvm.org/D53866



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53866: [Preamble] Fix preamble for circular #includes

2018-12-05 Thread Nikolai Kosjar via Phabricator via cfe-commits
nik updated this revision to Diff 176826.
nik added a comment.

Addressed comments.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53866/new/

https://reviews.llvm.org/D53866

Files:
  include/clang/Lex/Preprocessor.h
  include/clang/Serialization/ASTWriter.h
  lib/Frontend/PrecompiledPreamble.cpp
  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,9 @@
+// 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
@@ -1933,6 +1933,20 @@
 return;
   }
 
+  // Check whether it makes sense to continue preamble generation. We can't
+  // generate a consistent preamble with regard to the conditional stack if the
+  // main file is included again as due to the preamble bounds some directives
+  // (e.g. #endif of a header guard) will never be seen. Since this will lead 
to
+  // confusing errors, abort the preamble generation.
+  if (File && PreambleConditionalStack.isRecording() &&
+  SourceMgr.translateFile(File) == SourceMgr.getMainFileID()) {
+PreambleGenerationFailed = true;
+// Generate a fatal error to skip further processing.
+Diag(FilenameTok.getLocation(), diag::err_pp_error_opening_file)
+<< Filename << "Main file can't include itself for preamble.";
+return;
+  }
+
   // Should we enter the source file? Set to false if either the source file is
   // known to have no effect beyond its effect on module visibility -- that is,
   // if it's got an include guard that is already defined or is a modular 
header
Index: lib/Frontend/PrecompiledPreamble.cpp
===
--- lib/Frontend/PrecompiledPreamble.cpp
+++ lib/Frontend/PrecompiledPreamble.cpp
@@ -170,6 +170,9 @@
   }
 
   void HandleTranslationUnit(ASTContext ) override {
+if (getPreprocessor().preambleGenerationFailed())
+  return;
+
 PCHGenerator::HandleTranslationUnit(Ctx);
 if (!hasEmittedPCH())
   return;
Index: include/clang/Serialization/ASTWriter.h
===
--- include/clang/Serialization/ASTWriter.h
+++ include/clang/Serialization/ASTWriter.h
@@ -979,6 +979,7 @@
   ASTWriter () { return Writer; }
   const ASTWriter () const { return Writer; }
   SmallVectorImpl () const { return Buffer->Data; }
+  const Preprocessor () const { return PP; }
 
 public:
   PCHGenerator(const Preprocessor , StringRef OutputFile, StringRef 
isysroot,
Index: include/clang/Lex/Preprocessor.h
===
--- include/clang/Lex/Preprocessor.h
+++ include/clang/Lex/Preprocessor.h
@@ -388,6 +388,7 @@
 SmallVector ConditionalStack;
 State ConditionalStackState = Off;
   } PreambleConditionalStack;
+  bool PreambleGenerationFailed = false;
 
   /// The current top of the stack that we're lexing from if
   /// not expanding a macro and we are lexing directly from source code.
@@ -2159,6 +2160,10 @@
   Module *M,
   SourceLocation MLoc);
 
+  bool preambleGenerationFailed() const {
+return PreambleGenerationFailed;
+  }
+
   bool isRecordingPreamble() const {
 return PreambleConditionalStack.isRecording();
   }


Index: test/Index/preamble-cyclic-include.cpp
===
--- /dev/null
+++ test/Index/preamble-cyclic-include.cpp
@@ -0,0 +1,9 @@
+// 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
@@ -1933,6 +1933,20 @@
 return;
   }
 
+  // Check whether it makes sense to continue preamble generation. We can't
+  // generate a consistent preamble with regard to the conditional stack if the
+  // main file is included again as due to the preamble bounds some directives
+  // (e.g. #endif of a header guard) will never be seen. Since this will lead to
+  // confusing errors, abort the preamble generation.
+  if (File && PreambleConditionalStack.isRecording() &&
+  

[PATCH] D53866: [Preamble] Fix preamble for circular #includes

2018-12-04 Thread Ilya Biryukov via Phabricator via cfe-commits
ilya-biryukov added inline comments.



Comment at: include/clang/Lex/Preprocessor.h:391
   } PreambleConditionalStack;
+  bool PreambleGenerationFailed = false;
 

There's a mechanism to handle preamble with errors, see 
`PreprocessorOpts::AllowPCHWithCompilerErrors`.
Maybe rely on it and avoid adding a different one?



Comment at: lib/Lex/PPDirectives.cpp:1945
+// Generate a fatal error to skip further processing.
+Diag(FilenameTok.getLocation(), diag::err_pp_error_opening_file) << ""
+ << "";

Maybe add a new error or find a more appropriate existing one to reuse?
"Error opening file", especially without any arguments does not provide enough 
context to figure out what went wrong.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53866/new/

https://reviews.llvm.org/D53866



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53866: [Preamble] Fix preamble for circular #includes

2018-12-03 Thread Nikolai Kosjar via Phabricator via cfe-commits
nik added a comment.

Ping.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53866/new/

https://reviews.llvm.org/D53866



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53866: [Preamble] Fix preamble for circular #includes

2018-11-26 Thread Nikolai Kosjar via Phabricator via cfe-commits
nik updated this revision to Diff 175210.
nik added a comment.

> Maybe produce a **fatal** error in the preprocessor? That seems to be the 
> simplest option: the preprocessor is aware it's building the preamble and 
> there's definitely some logic to produce fatal errors in other cases (include 
> not found).
>  A fatal error currently aborts other stages of the compilation pipeline and 
> producing one would make the run of the compiler that tries to produce the 
> preamble fail, giving the empty preamble as a result.

Done. I'm using diag::err_pp_error_opening_file as introducing an new 
artificial diagnostic error that the user will never see feels wrong.

Note that a preamble is generated for fatal errors like an unresolved #include 
and I think that's fine. As such, I need a way to propagate the error up to 
PrecompilePreambleConsumer to avoid writing the preamble. I've done that with 
an extra flag in Preprocessor. An alternative might be to put it into 
PreambleConditionalStackStore (as state? and rename that class to something 
more general?) - what do you think?


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D53866/new/

https://reviews.llvm.org/D53866

Files:
  include/clang/Lex/Preprocessor.h
  include/clang/Serialization/ASTWriter.h
  lib/Frontend/PrecompiledPreamble.cpp
  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,9 @@
+// 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
@@ -1933,6 +1933,20 @@
 return;
   }
 
+  // Check whether it makes sense to continue preamble generation. We can't
+  // generate a consistent preamble with regard to the conditional stack if the
+  // main file is included again as due to the preamble bounds some directives
+  // (e.g. #endif of a header guard) will never be seen. Since this will lead 
to
+  // confusing errors, abort the preamble generation.
+  if (File && PreambleConditionalStack.isRecording() &&
+  SourceMgr.translateFile(File) == SourceMgr.getMainFileID()) {
+PreambleGenerationFailed = true;
+// Generate a fatal error to skip further processing.
+Diag(FilenameTok.getLocation(), diag::err_pp_error_opening_file) << ""
+ << "";
+return;
+  }
+
   // Should we enter the source file? Set to false if either the source file is
   // known to have no effect beyond its effect on module visibility -- that is,
   // if it's got an include guard that is already defined or is a modular 
header
Index: lib/Frontend/PrecompiledPreamble.cpp
===
--- lib/Frontend/PrecompiledPreamble.cpp
+++ lib/Frontend/PrecompiledPreamble.cpp
@@ -170,6 +170,9 @@
   }
 
   void HandleTranslationUnit(ASTContext ) override {
+if (getPreprocessor().preambleGenerationFailed())
+  return;
+
 PCHGenerator::HandleTranslationUnit(Ctx);
 if (!hasEmittedPCH())
   return;
Index: include/clang/Serialization/ASTWriter.h
===
--- include/clang/Serialization/ASTWriter.h
+++ include/clang/Serialization/ASTWriter.h
@@ -979,6 +979,7 @@
   ASTWriter () { return Writer; }
   const ASTWriter () const { return Writer; }
   SmallVectorImpl () const { return Buffer->Data; }
+  const Preprocessor () const { return PP; }
 
 public:
   PCHGenerator(const Preprocessor , StringRef OutputFile, StringRef 
isysroot,
Index: include/clang/Lex/Preprocessor.h
===
--- include/clang/Lex/Preprocessor.h
+++ include/clang/Lex/Preprocessor.h
@@ -388,6 +388,7 @@
 SmallVector ConditionalStack;
 State ConditionalStackState = Off;
   } PreambleConditionalStack;
+  bool PreambleGenerationFailed = false;
 
   /// The current top of the stack that we're lexing from if
   /// not expanding a macro and we are lexing directly from source code.
@@ -2159,6 +2160,10 @@
   Module *M,
   SourceLocation MLoc);
 
+  bool preambleGenerationFailed() const {
+return PreambleGenerationFailed;
+  }
+
   bool isRecordingPreamble() const {
 return PreambleConditionalStack.isRecording();
   }


Index: test/Index/preamble-cyclic-include.cpp
===
--- 

[PATCH] D53866: [Preamble] Fix preamble for circular #includes

2018-11-19 Thread Ilya Biryukov via Phabricator via cfe-commits
ilya-biryukov added a comment.

In https://reviews.llvm.org/D53866#1301086, @nik wrote:

> I still don't have feedback for a real world case except "unintentional 
> #include". Unfortunately, in real world cases the cyclic include might be not 
> obvious at all.
>  @ilya: As far as I understand you prefer to make the preamble generation 
> rather fail as long as we don't have more information. How do you suggest to 
> implement this? I see that Clang->getPreprocessor().addPPCallbacks() is 
> called in PrecompiledPreamble::Build(). Adding a custom PPCallbacks there 
> that overrides "void InclusionDirective()" might be enough to detect the 
> cyclic #include and to set a flag that is checked before 
> PrecompiledPreamble::Build() returns - BuildPreambleError could get a new 
> enumerator. Is there a better way to do this? For example, it would be 
> desirable to not only observe this case, but then to also stop/abort/skip all 
> the further parsing that is done for the preamble only as it's pointless then.


Maybe produce a **fatal** error in the preprocessor? That seems to be the 
simplest option: the preprocessor is aware it's building the preamble and 
there's definitely some logic to produce fatal errors in other cases (include 
not found).
A fatal error currently aborts other stages of the compilation pipeline and 
producing one would make the run of the compiler that tries to produce the 
preamble fail, giving the empty preamble as a result.


Repository:
  rC Clang

https://reviews.llvm.org/D53866



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53866: [Preamble] Fix preamble for circular #includes

2018-11-16 Thread Nikolai Kosjar via Phabricator via cfe-commits
nik added a comment.

I still don't have feedback for a real world case except "unintentional 
#include". Unfortunately, in real world cases the cyclic include might be not 
obvious at all.

@ilya: As far as I understand you prefer to make the preamble generation rather 
fail as long as we don't have more information. How do you suggest to implement 
this? I see that Clang->getPreprocessor().addPPCallbacks() is called in 
PrecompiledPreamble::Build(). Adding a custom PPCallbacks there that overrides 
"void InclusionDirective()" might be enough to detect the cyclic #include and 
to set a flag that is checked before PrecompiledPreamble::Build() returns - 
BuildPreambleError could get a new enumerator. Is there a better way to do 
this? For example, it would be desirable to not only observe this case, but 
then to also stop/abort/skip all the further parsing that is done for the 
preamble only as it's pointless then.


Repository:
  rC Clang

https://reviews.llvm.org/D53866



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53866: [Preamble] Fix preamble for circular #includes

2018-11-01 Thread Nikolai Kosjar via Phabricator via cfe-commits
nik added a comment.

I've only the minimal example at hand right know - I'm waiting for feedback 
about the real world case.


Repository:
  rC Clang

https://reviews.llvm.org/D53866



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53866: [Preamble] Fix preamble for circular #includes

2018-10-31 Thread Ilya Biryukov via Phabricator via cfe-commits
ilya-biryukov added a comment.

In https://reviews.llvm.org/D53866#1282582, @yvvan wrote:

> @ilya-biryukov 
>  As far as I understand the problem the same thing happens when you are in 
> the header a.h which includes b.h and b.h includes a.h at the same time. So 
> you get this recursion indirectly and very often because that's why include 
> guards are there.


Cycles in include graphs are almost always unintentional and must be broken 
apart, there are very few cases where you actually want this.
E.g. in your example, since 'b.h' includes 'a.h' it needs something from 'a.h'. 
But if you include 'b.h' while processing the preamble of 'a.h', the 
declarations inside 'a.h' are not yet visible and that would result in (at 
times obscure and hard to read) compiler errors when parsing 'b.h'.
(Assuming a.h and b.h are normal headers and the use-case does not involve 
doing various preprocessor tricks)

In those cases it usually works by accident (e.g. when 'b.h' included 'a.h', 
but never actually used anything declared in 'a.h').


Repository:
  rC Clang

https://reviews.llvm.org/D53866



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53866: [Preamble] Fix preamble for circular #includes

2018-10-31 Thread Ivan Donchevskii via Phabricator via cfe-commits
yvvan added a comment.

@ilya-biryukov 
As far as I understand the problem the same thing happens when you are in the 
header a.h which includes b.h and b.h includes a.h at the same time. So you get 
this recursion indirectly and very often because that's why include guards are 
there.


Repository:
  rC Clang

https://reviews.llvm.org/D53866



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53866: [Preamble] Fix preamble for circular #includes

2018-10-31 Thread Ilya Biryukov via Phabricator via cfe-commits
ilya-biryukov added a comment.

> Because this case can be detected and handled without loosing the benefits of 
> the preamble.

The cases where recursive includes make sense are incredibly rare in practice. 
Most of the time, recursively including the same file is unintentional should 
be considered a bug and fixed.
Producing a warning that the file is being recursively included (along with an 
include chain that caused a recursive inclusion) seems to provide more benefit 
than preamble, especially when this is unintentional (I would argue that's the 
majority of the cases).

> If we are in preamble-generation-mode and the main file #includes itself, 
> then it should see the full file content of the file, not the truncated 
> preamble version of it.
>  Would this be more consistent?

Yes, but I can't see an easy way to make it happen. And I don't think we want a 
complex fix for something bizzare that very rarely happens in practice.


Repository:
  rC Clang

https://reviews.llvm.org/D53866



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53866: [Preamble] Fix preamble for circular #includes

2018-10-31 Thread Nikolai Kosjar via Phabricator via cfe-commits
nik added a comment.

In https://reviews.llvm.org/D53866#1281978, @ilya-biryukov wrote:

> Why does resetting the conditional stack is the right thing to do here?


Because this case can be detected and handled without loosing the benefits of 
the preamble.

> Failing to build the preamble in that case seems like the best thing we could 
> do. WDYT?

See above - we would not have the benefits of the preamble anymore.

>   I can see how it can hide the problem, but can't come up with with a 
> consistent model to handle the fact that the file contents were trimmed.

If we are in preamble-generation-mode and the main file #includes itself, then 
it should see the full file content of the file, not the truncated preamble 
version of it.
Would this be more consistent?


Repository:
  rC Clang

https://reviews.llvm.org/D53866



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53866: [Preamble] Fix preamble for circular #includes

2018-10-31 Thread Ilya Biryukov via Phabricator via cfe-commits
ilya-biryukov added a comment.

Why does resetting the conditional stack is the right thing to do here?
I can see how it can hide the problem, but can't come up with with a consistent 
model to handle the fact that the file contents were trimmed.

Failing to build the preamble in that case seems like the best thing we could 
do. WDYT?


Repository:
  rC Clang

https://reviews.llvm.org/D53866



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53866: [Preamble] Fix preamble for circular #includes

2018-10-30 Thread Nikolai Kosjar via Phabricator via cfe-commits
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 ,
+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 ,
+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(
-