[Preamble] Stop circular inclusion of main file when building preamble

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.

llvm-svn: 360418
This commit is contained in:
Nikolai Kosjar 2019-05-10 10:25:35 +00:00
parent a2ab528c4c
commit 3c28a2dc6b
3 changed files with 15 additions and 1 deletions

View 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>">;

View 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;

View 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