]> granicus.if.org Git - clang/commitdiff
[Preamble] Stop circular inclusion of main file when building preamble
authorNikolai Kosjar <nikolai.kosjar@qt.io>
Fri, 10 May 2019 10:25:35 +0000 (10:25 +0000)
committerNikolai Kosjar <nikolai.kosjar@qt.io>
Fri, 10 May 2019 10:25:35 +0000 (10:25 +0000)
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.

Detect the circular inclusion, emit a diagnostic and stop processing the
inclusion.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@360418 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticLexKinds.td
lib/Basic/SourceManager.cpp
lib/Lex/PPDirectives.cpp

index 5c567f21320959abbd01a6dba5aaba8d16a89190..dd5e2af3d27fb164c8dc90d78e7ad891b1cb3281 100644 (file)
@@ -426,6 +426,8 @@ def note_pp_framework_without_header : Note<
   "did not find header '%0' in framework '%1' (loaded from '%2')">;
 def err_pp_error_opening_file : Error<
   "error opening file '%0': %1">, DefaultFatal;
+def err_pp_including_mainfile_in_preamble : Error<
+  "main file cannot be included recursively when building a preamble">;
 def err_pp_empty_filename : Error<"empty filename">;
 def err_pp_include_too_deep : Error<"#include nested too deeply">;
 def err_pp_expects_filename : Error<"expected \"FILENAME\" or <FILENAME>">;
index 0ffad1bc475f2d97cec8010155edfdac2224be03..712cbb0d0ead8f215b8ecaf33b13e57adc15cf8b 100644 (file)
@@ -1582,7 +1582,7 @@ FileID SourceManager::translateFile(const FileEntry *SourceFile) const {
     if (MainSLoc.isFile()) {
       const ContentCache *MainContentCache
         = MainSLoc.getFile().getContentCache();
-      if (!MainContentCache) {
+      if (!MainContentCache || !MainContentCache->OrigEntry) {
         // Can't do anything
       } else if (MainContentCache->OrigEntry == SourceFile) {
         FirstFID = MainFileID;
index 5d5cae5fd0f88404a0dab0c9774b06cb6411bfba..193388650d20b79809f058d3face9feba041a056 100644 (file)
@@ -1871,6 +1871,18 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
     return {ImportAction::None};
   }
 
+  // Check for circular inclusion of the main file.
+  // 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, avoid the inclusion.
+  if (File && PreambleConditionalStack.isRecording() &&
+      SourceMgr.translateFile(File) == SourceMgr.getMainFileID()) {
+    Diag(FilenameTok.getLocation(),
+         diag::err_pp_including_mainfile_in_preamble);
+    return {ImportAction::None};
+  }
+
   // Should we enter the source file? Set to Skip 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, set to Import if it