oontvoo updated this revision to Diff 253388.
oontvoo added a comment.
Add more tests (From Bug 39206)
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D75951/new/
https://reviews.llvm.org/D75951
Files:
clang/include/clang/Lex/HeaderSearch.h
clang/include/clang/Lex/Preprocessor.h
clang/include/clang/Serialization/ASTBitCodes.h
clang/include/clang/Serialization/ASTReader.h
clang/include/clang/Serialization/ASTWriter.h
clang/lib/Lex/HeaderSearch.cpp
clang/lib/Lex/Preprocessor.cpp
clang/lib/Serialization/ASTReader.cpp
clang/lib/Serialization/ASTWriter.cpp
clang/test/Modules/Inputs/dummy_pragma_once.h
clang/test/Modules/Inputs/dummy_textual_header.h
clang/test/Modules/Inputs/header_in_imported_module.h
clang/test/Modules/Inputs/imported_module.cppm
clang/test/Modules/Inputs/module.map
clang/test/Modules/header-in-imported-module.c
clang/test/Modules/import-pragma-once.c
Index: clang/test/Modules/import-pragma-once.c
===================================================================
--- /dev/null
+++ clang/test/Modules/import-pragma-once.c
@@ -0,0 +1,8 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fimplicit-module-maps -I%S/Inputs -verify -x c %s
+// expected-no-diagnostics
+#include "dummy_pragma_once.h"
+#include "dummy_textual_header.h"
+
+void *p = &x;
+void *q = &y;
Index: clang/test/Modules/header-in-imported-module.c
===================================================================
--- /dev/null
+++ clang/test/Modules/header-in-imported-module.c
@@ -0,0 +1,16 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fimplicit-module-maps -I%S/Inputs -verify -x c++ %s
+//
+// RUN: %clang_cc1 -x c++ -fmodules-ts --precompile -o %t/ModuleB39206.pcm %S/Inputs/imported_module.cppm
+// RUN: %clang_cc1 -x c++ -fmodules-ts -c %t/ModuleB39206.pcm -o %t/ModuleB39206.o
+// RUN: %clang_cc1 -x c++ -fmodules-ts -fmodule-file=%t/ModuleB39206.pcm -verify -c %s
+// expected-no-diagnostics
+
+// Bug 39206
+
+#include "header_in_imported_module.h"
+module ModuleB39206;
+
+#ifndef ALL_GOOD
+#error "missing macro in impl"
+#endif
Index: clang/test/Modules/Inputs/module.map
===================================================================
--- clang/test/Modules/Inputs/module.map
+++ clang/test/Modules/Inputs/module.map
@@ -282,6 +282,11 @@
header "dummy.h"
}
+module dummy_pragma_once {
+ header "dummy_pragma_once.h"
+ textual header "dummy_textual_header.h"
+}
+
module builtin {
header "builtin.h"
explicit module sub {
Index: clang/test/Modules/Inputs/imported_module.cppm
===================================================================
--- /dev/null
+++ clang/test/Modules/Inputs/imported_module.cppm
@@ -0,0 +1,5 @@
+export module ModuleB39206;
+#include "header.h"
+
+#ifndef ALL_GOOD
+#error "Missing macro in module decl"
\ No newline at end of file
Index: clang/test/Modules/Inputs/header_in_imported_module.h
===================================================================
--- /dev/null
+++ clang/test/Modules/Inputs/header_in_imported_module.h
@@ -0,0 +1,3 @@
+#pragma once
+
+#define ALL_GOOD
Index: clang/test/Modules/Inputs/dummy_textual_header.h
===================================================================
--- /dev/null
+++ clang/test/Modules/Inputs/dummy_textual_header.h
@@ -0,0 +1,2 @@
+#pragma once
+int y = 6;
Index: clang/test/Modules/Inputs/dummy_pragma_once.h
===================================================================
--- /dev/null
+++ clang/test/Modules/Inputs/dummy_pragma_once.h
@@ -0,0 +1,3 @@
+#include "dummy_textual_header.h"
+
+int x = 5;
Index: clang/lib/Serialization/ASTWriter.cpp
===================================================================
--- clang/lib/Serialization/ASTWriter.cpp
+++ clang/lib/Serialization/ASTWriter.cpp
@@ -1621,7 +1621,7 @@
endian::Writer LE(Out, little);
unsigned KeyLen = key.Filename.size() + 1 + 8 + 8;
LE.write<uint16_t>(KeyLen);
- unsigned DataLen = 1 + 2 + 4 + 4;
+ unsigned DataLen = 1 + 2 + 4 + 4 + 4;
for (auto ModInfo : Data.KnownHeaders)
if (Writer.getLocalOrImportedSubmoduleID(ModInfo.getModule()))
DataLen += 4;
@@ -1678,6 +1678,9 @@
}
LE.write<uint32_t>(Offset);
+ // Write this file UID.
+ LE.write<uint32_t>(Data.HFI.UID);
+
auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) {
if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) {
uint32_t Value = (ModID << 2) | (unsigned)Role;
@@ -1705,7 +1708,7 @@
/// Write the header search block for the list of files that
///
/// \param HS The header search structure to save.
-void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) {
+void ASTWriter::WriteHeaderSearch(HeaderSearch &HS) {
HeaderFileInfoTrait GeneratorTrait(*this);
llvm::OnDiskChainedHashTableGenerator<HeaderFileInfoTrait> Generator;
SmallVector<const char *, 4> SavedStrings;
@@ -1783,8 +1786,7 @@
// changed since it was loaded. Also skip it if it's for a modular header
// from a different module; in that case, we rely on the module(s)
// containing the header to provide this information.
- const HeaderFileInfo *HFI =
- HS.getExistingFileInfo(File, /*WantExternal*/!Chain);
+ HeaderFileInfo *HFI = HS.getExistingFileInfo(File, /*WantExternal*/ !Chain);
if (!HFI || (HFI->isModuleHeader && !HFI->isCompilingModuleHeader))
continue;
@@ -1801,8 +1803,13 @@
HeaderFileInfoTrait::key_type Key = {
Filename, File->getSize(), getTimestampForOutput(File)
};
+ // Set the UID for this HFI so that its importers could use it
+ // when serializing.
+ HFI->UID = UID;
HeaderFileInfoTrait::data_type Data = {
- *HFI, HS.getModuleMap().findAllModulesForHeader(File), {}
+ *HFI,
+ HS.getModuleMap().findAllModulesForHeader(File),
+ {},
};
Generator.insert(Key, Data, GeneratorTrait);
++NumHeaderSearchEntries;
@@ -2636,6 +2643,25 @@
Stream.EmitRecord(SUBMODULE_IMPORTS, Record);
}
+ // Emit the imported header's UIDs.
+ {
+ auto it = PP->Submodules.find(Mod);
+ if (it != PP->Submodules.end() && !it->second.IncludedFiles.empty()) {
+ RecordData Record;
+ for (unsigned UID : it->second.IncludedFiles) {
+ // Only save it if the header is actually import/pragma once.
+ // FIXME When we first see a header, it always goes into the mod's
+ // list of included, regardless of whether it was pragma-once or not.
+ // Maybe better to fix that earlier?
+ auto HFI = PP->getHeaderSearchInfo().FileInfo[UID];
+ if (HFI.isImport || HFI.isPragmaOnce) {
+ Record.push_back(HFI.UID);
+ }
+ }
+ Stream.EmitRecord(SUBMODULE_IMPORTED_HEADERS, Record);
+ }
+ }
+
// Emit the exports.
if (!Mod->Exports.empty()) {
RecordData Record;
@@ -4722,6 +4748,24 @@
if (WritingModule)
WriteSubmodules(WritingModule);
+ // Write the imported headers, only for the precompiled header (ie, no
+ // modules) because the modules will have emitted their own imported headers.
+ if ((!WritingModule || PP.Submodules.empty()) &&
+ !PP.CurSubmoduleState->IncludedFiles.empty()) {
+ RecordData Record;
+ for (unsigned UID : PP.CurSubmoduleState->IncludedFiles) {
+ // Only save it if the header is actually import/pragma once.
+ // FIXME When we first see a header, it always goes into the
+ // list of included, regardless of whether it was pragma-once or not.
+ // Maybe better to fix that earlier?
+ auto HFI = PP.getHeaderSearchInfo().FileInfo[UID];
+ if (HFI.isImport || HFI.isPragmaOnce) {
+ Record.push_back(HFI.UID);
+ }
+ }
+ Stream.EmitRecord(PP_IMPORTED_HEADERS, Record);
+ }
+
// We need to have information about submodules to correctly deserialize
// decls from OpenCLExtensionDecls block
WriteOpenCLExtensionDecls(SemaRef);
Index: clang/lib/Serialization/ASTReader.cpp
===================================================================
--- clang/lib/Serialization/ASTReader.cpp
+++ clang/lib/Serialization/ASTReader.cpp
@@ -1,3 +1,4 @@
+
//===- ASTReader.cpp - AST File Reader ------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
@@ -1898,6 +1899,10 @@
HFI.Framework = HS->getUniqueFrameworkName(FrameworkName);
}
+ // Read the file old UID
+ HFI.UID = endian::readNext<uint32_t, little, unaligned>(d);
+ HFI.UIDSet = true;
+
assert((End - d) % 4 == 0 &&
"Wrong data length in HeaderFileInfo deserialization");
while (d != End) {
@@ -3081,6 +3086,7 @@
case HEADER_SEARCH_TABLE:
case IMPORTED_MODULES:
case MACRO_OFFSET:
+ case PP_IMPORTED_HEADERS:
break;
default:
continue;
@@ -3530,6 +3536,12 @@
break;
}
+ case PP_IMPORTED_HEADERS: {
+ for (unsigned Idx = 0; Idx < Record.size(); ++Idx) {
+ PendingImportedHeaders.push_back(Record[Idx]);
+ }
+ break;
+ }
case DECL_UPDATE_OFFSETS:
if (Record.size() % 2 != 0) {
Error("invalid DECL_UPDATE_OFFSETS block in AST file");
@@ -5620,6 +5632,11 @@
}
break;
+ case SUBMODULE_IMPORTED_HEADERS:
+ for (unsigned Idx = 0; Idx < Record.size(); ++Idx) {
+ PendingImportedHeadersForModules[&F].push_back(Record[Idx]);
+ }
+ break;
case SUBMODULE_EXPORTS:
for (unsigned Idx = 0; Idx + 1 < Record.size(); Idx += 2) {
UnresolvedModuleRef Unresolved;
@@ -6165,12 +6182,15 @@
HeaderFileInfo ASTReader::GetHeaderFileInfo(const FileEntry *FE) {
HeaderFileInfoVisitor Visitor(FE);
ModuleMgr.visit(Visitor);
+
if (Optional<HeaderFileInfo> HFI = Visitor.getHeaderFileInfo())
return *HFI;
return HeaderFileInfo();
}
+void ASTReader::ResolvePendings() { resolvePendingImportedHeaders(); }
+
void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) {
using DiagState = DiagnosticsEngine::DiagState;
SmallVector<DiagState *, 32> DiagStates;
@@ -9289,6 +9309,84 @@
for (auto *ND : PendingMergedDefinitionsToDeduplicate)
getContext().deduplicateMergedDefinitonsFor(ND);
PendingMergedDefinitionsToDeduplicate.clear();
+
+ // Have to be done last because we need the modules
+ // and other PP info.
+ resolvePendingImportedHeaders();
+}
+
+void ASTReader::resolvePendingImportedHeaders() {
+ if (PP.getHeaderSearchInfo().FileInfo.empty()) {
+ return;
+ }
+
+ if (!PendingImportedHeadersForModules.empty() ||
+ !PendingImportedHeaders.empty()) {
+ // They cannot be both non-empty!
+ assert(PendingImportedHeadersForModules.empty() !=
+ PendingImportedHeaders.empty());
+
+ std::map<unsigned, unsigned> UIDToIndex;
+
+ // These HFIs were deserialized and assigned their "old"
+ // UID.
+ // We need to update them and populate the OldToIndex map
+ // for use next.
+ HeaderSearch &HS = PP.getHeaderSearchInfo();
+ for (unsigned Idx = 0; Idx < HS.FileInfo.size(); ++Idx) {
+ if (!HS.FileInfo[Idx].UIDSet)
+ continue;
+
+ UIDToIndex[HS.FileInfo[Idx].UID] = Idx;
+ }
+ if (UIDToIndex.empty())
+ return;
+
+ const auto &Iter = PendingImportedHeadersForModules.begin();
+ bool Unresolved = false;
+ for (unsigned I = 0; I < PendingImportedHeadersForModules.size(); ++I) {
+ ModuleFile *ModFile = Iter[I].first;
+ auto &HeaderUIDs = Iter[I].second;
+ Module *M = HS.lookupModule(ModFile->ModuleName);
+
+ Preprocessor::SubmoduleState &SubState = PP.Submodules[M];
+ std::set<unsigned> Remaining;
+ for (unsigned OldUID : HeaderUIDs) {
+ auto IdxIt = UIDToIndex.find(OldUID);
+ if (IdxIt == UIDToIndex.end()) {
+ Unresolved = true;
+ Remaining.insert(OldUID);
+ continue;
+ }
+ SubState.IncludedFiles.insert(IdxIt->second);
+ }
+ HeaderUIDs.clear();
+ for (unsigned UID : Remaining) {
+ HeaderUIDs.push_back(UID);
+ }
+ }
+ if (!Unresolved)
+ PendingImportedHeadersForModules.clear();
+
+ if (!PendingImportedHeaders.empty()) {
+ std::set<unsigned> Remaining;
+ for (unsigned OldUID : PendingImportedHeaders) {
+ auto IdxIt = UIDToIndex.find(OldUID);
+ if (IdxIt == UIDToIndex.end()) {
+ Remaining.insert(OldUID);
+ continue;
+ }
+
+ PP.CurSubmoduleState->IncludedFiles.insert(IdxIt->second);
+ }
+ if (Remaining.size() < PendingImportedHeaders.size()) {
+ PendingImportedHeaders.clear();
+ for (unsigned UID : Remaining) {
+ PendingImportedHeaders.push_back(UID);
+ }
+ }
+ }
+ }
}
void ASTReader::diagnoseOdrViolations() {
Index: clang/lib/Lex/Preprocessor.cpp
===================================================================
--- clang/lib/Lex/Preprocessor.cpp
+++ clang/lib/Lex/Preprocessor.cpp
@@ -554,8 +554,10 @@
// Tell the header info that the main file was entered. If the file is later
// #imported, it won't be re-entered.
- if (const FileEntry *FE = SourceMgr.getFileEntryForID(MainFileID))
+ if (const FileEntry *FE = SourceMgr.getFileEntryForID(MainFileID)) {
HeaderInfo.IncrementIncludeCount(FE);
+ setIncludeVisible(HeaderInfo.getFileInfo(FE).UID);
+ }
}
// Preprocess Predefines to populate the initial preprocessor state.
Index: clang/lib/Lex/HeaderSearch.cpp
===================================================================
--- clang/lib/Lex/HeaderSearch.cpp
+++ clang/lib/Lex/HeaderSearch.cpp
@@ -1156,6 +1156,9 @@
if (HFI.Framework.empty())
HFI.Framework = OtherHFI.Framework;
+
+ HFI.UID = OtherHFI.UID;
+ HFI.UIDSet = OtherHFI.UIDSet;
}
/// getFileInfo - Return the HeaderFileInfo structure for the specified
@@ -1165,7 +1168,10 @@
FileInfo.resize(FE->getUID() + 1);
HeaderFileInfo *HFI = &FileInfo[FE->getUID()];
- // FIXME: Use a generation count to check whether this is really up to date.
+ if (!HFI->UIDSet) {
+ HFI->UID = FE->getUID();
+ }
+
if (ExternalSource && !HFI->Resolved) {
HFI->Resolved = true;
auto ExternalHFI = ExternalSource->GetHeaderFileInfo(FE);
@@ -1182,9 +1188,8 @@
return *HFI;
}
-const HeaderFileInfo *
-HeaderSearch::getExistingFileInfo(const FileEntry *FE,
- bool WantExternal) const {
+HeaderFileInfo *HeaderSearch::getExistingFileInfo(const FileEntry *FE,
+ bool WantExternal) const {
// If we have an external source, ensure we have the latest information.
// FIXME: Use a generation count to check whether this is really up to date.
HeaderFileInfo *HFI;
@@ -1196,6 +1201,8 @@
}
HFI = &FileInfo[FE->getUID()];
+ if (!HFI->UIDSet)
+ HFI->UID = FE->getUID();
if (!WantExternal && (!HFI->IsValid || HFI->External))
return nullptr;
if (!HFI->Resolved) {
@@ -1250,63 +1257,77 @@
bool ModulesEnabled, Module *M) {
++NumIncluded; // Count # of attempted #includes.
+ // Make sure everything is up to date.
+ ModMap.resolveHeaderDirectives(File);
+
+ const bool SeenBefore =
+ getExistingFileInfo(File, /*WantExernal=*/true) != nullptr;
+
// Get information about this file.
HeaderFileInfo &FileInfo = getFileInfo(File);
- // FIXME: this is a workaround for the lack of proper modules-aware support
- // for #import / #pragma once
- auto TryEnterImported = [&]() -> bool {
- if (!ModulesEnabled)
- return false;
- // Ensure FileInfo bits are up to date.
- ModMap.resolveHeaderDirectives(File);
- // Modules with builtins are special; multiple modules use builtins as
- // modular headers, example:
- //
- // module stddef { header "stddef.h" export * }
- //
- // After module map parsing, this expands to:
- //
- // module stddef {
- // header "/path_to_builtin_dirs/stddef.h"
- // textual "stddef.h"
- // }
- //
- // It's common that libc++ and system modules will both define such
- // submodules. Make sure cached results for a builtin header won't
- // prevent other builtin modules to potentially enter the builtin header.
- // Note that builtins are header guarded and the decision to actually
- // enter them is postponed to the controlling macros logic below.
- bool TryEnterHdr = false;
- if (FileInfo.isCompilingModuleHeader && FileInfo.isModuleHeader)
- TryEnterHdr = File->getDir() == ModMap.getBuiltinDir() &&
- ModuleMap::isBuiltinHeader(
- llvm::sys::path::filename(File->getName()));
-
- // Textual headers can be #imported from different modules. Since ObjC
- // headers find in the wild might rely only on #import and do not contain
- // controlling macros, be conservative and only try to enter textual headers
- // if such macro is present.
- if (!FileInfo.isModuleHeader &&
- FileInfo.getControllingMacro(ExternalLookup))
- TryEnterHdr = true;
- return TryEnterHdr;
- };
+ // Resolve any pendings before we do calculations.
+ if (ExternalSource) {
+ ExternalSource->ResolvePendings();
+ }
+
+#ifdef DLOG_HDRS
+ llvm::errs() << "\n***** " << File->getName()
+ << " | FileInfo.UID_set = " << FileInfo.UID << "_"
+ << FileInfo.UIDSet << " | M = " << M << " | seenBefore "
+ << SeenBefore << " | FileInfoo.Resolved = " << FileInfo.Resolved
+ << " | isCompileModHeader " << FileInfo.isCompilingModuleHeader
+ << " | isModHeader " << FileInfo.isModuleHeader
+ << " | isPragmaOnce " << FileInfo.isPragmaOnce << " | isImport "
+ << (isImport || FileInfo.isImport) << " | Prev included "
+ << FileInfo.NumIncludes << " | In file: ";
+
+ if (PP.getCurrentFileLexer() == nullptr ||
+ PP.getCurrentFileLexer()->getFileEntry() == nullptr) {
+ llvm::errs() << " <unknown>";
+ } else {
+ llvm::errs() << PP.getCurrentFileLexer()->getFileEntry()->getName();
+ }
+
+ llvm::errs() << " | should enter = ";
+#endif // DLOG_HDRS
- // If this is a #import directive, check that we have not already imported
- // this header.
if (isImport) {
// If this has already been imported, don't import it again.
FileInfo.isImport = true;
+ }
- // Has this already been #import'ed or #include'd?
- if (FileInfo.NumIncludes && !TryEnterImported())
+ if (!SeenBefore || FileInfo.NumIncludes == 0 || FileInfo.isPragmaOnce ||
+ FileInfo.isImport) {
+ if (PP.isIncludeVisible(FileInfo.UID)) {
+#ifdef DLOG_HDRS
+ llvm::errs() << "false (already included)\n";
+#endif // DLOG_HDRS
return false;
- } else {
- // Otherwise, if this is a #include of a file that was previously #import'd
- // or if this is the second #include of a #pragma once file, ignore it.
- if (FileInfo.isImport && !TryEnterImported())
+ } else if (FileInfo.isModuleHeader && FileInfo.isCompilingModuleHeader &&
+ PP.isIncludeVisibleFromOuterModule(FileInfo.UID)) {
+#ifdef DLOG_HDRS
+ llvm::errs() << "false (visible from outer modudle)\n";
+#endif // DLOG_HDRs
return false;
+ } else {
+ // Mark as 'included'.
+ PP.setIncludeVisible(FileInfo.UID);
+
+ // FIXME: This is kind of hack to handle textual-header in ObjC
+ // Textual headers can be #imported from different modules.
+ // ObjC headers rely only on #import and do not contain
+ // controlling macros. Hence we won't enter the header if
+ // macro is absent.
+ if (isImport && FileInfo.NumIncludes &&
+ (FileInfo.isModuleHeader ||
+ !FileInfo.getControllingMacro(ExternalLookup))) {
+#ifdef DLOG_HDRS
+ llvm::errs() << "false (objc textual header)\n";
+#endif // DLOG_HDRS
+ return false;
+ }
+ }
}
// Next, check to see if the file is wrapped with #ifndef guards. If so, and
@@ -1319,12 +1340,18 @@
if (M ? PP.isMacroDefinedInLocalModule(ControllingMacro, M)
: PP.isMacroDefined(ControllingMacro)) {
++NumMultiIncludeFileOptzn;
+#ifdef DLOG_HDRS
+ llvm::errs() << "false(has macro)\n";
+#endif // DLOG_HDRs
return false;
}
}
// Increment the number of times this file has been included.
++FileInfo.NumIncludes;
+#ifdef DLOG_HDRS
+ llvm::errs() << "true\n";
+#endif // DLOG_HDRs
return true;
}
Index: clang/include/clang/Serialization/ASTWriter.h
===================================================================
--- clang/include/clang/Serialization/ASTWriter.h
+++ clang/include/clang/Serialization/ASTWriter.h
@@ -463,7 +463,7 @@
void WriteSourceManagerBlock(SourceManager &SourceMgr,
const Preprocessor &PP);
void WritePreprocessor(const Preprocessor &PP, bool IsModule);
- void WriteHeaderSearch(const HeaderSearch &HS);
+ void WriteHeaderSearch(HeaderSearch &HS);
void WritePreprocessorDetail(PreprocessingRecord &PPRec);
void WriteSubmodules(Module *WritingModule);
Index: clang/include/clang/Serialization/ASTReader.h
===================================================================
--- clang/include/clang/Serialization/ASTReader.h
+++ clang/include/clang/Serialization/ASTReader.h
@@ -736,6 +736,15 @@
/// IDs have not yet been deserialized to the global IDs of those macros.
PendingMacroIDsMap PendingMacroIDs;
+ /// Mapping from ModuleFile to a list of its imported headers' (old) UID.
+ /// These UIDs are yet to be mapped to their corresponding HeaderFileInfo
+ using PendingImportedHeadersMap =
+ llvm::MapVector<ModuleFile *, SmallVector<unsigned, 8>>;
+ PendingImportedHeadersMap PendingImportedHeadersForModules;
+
+ /// List of a PCH imported headers' (old)UID.
+ SmallVector<unsigned, 8> PendingImportedHeaders;
+
using GlobalPreprocessedEntityMapType =
ContinuousRangeMap<unsigned, ModuleFile *, 4>;
@@ -1416,6 +1425,8 @@
void PassInterestingDeclsToConsumer();
void PassInterestingDeclToConsumer(Decl *D);
+ void resolvePendingImportedHeaders();
+
void finishPendingActions();
void diagnoseOdrViolations();
@@ -1722,6 +1733,8 @@
/// Read the header file information for the given file entry.
HeaderFileInfo GetHeaderFileInfo(const FileEntry *FE) override;
+ void ResolvePendings() override;
+
void ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag);
/// Returns the number of source locations found in the chain.
Index: clang/include/clang/Serialization/ASTBitCodes.h
===================================================================
--- clang/include/clang/Serialization/ASTBitCodes.h
+++ clang/include/clang/Serialization/ASTBitCodes.h
@@ -654,6 +654,9 @@
/// Record code for the Decls to be checked for deferred diags.
DECLS_TO_CHECK_FOR_DEFERRED_DIAGS = 64,
+
+ /// List of imported headers' UID for a PCH
+ PP_IMPORTED_HEADERS = 65,
};
/// Record types used within a source manager block.
@@ -784,6 +787,9 @@
/// Specifies the name of the module that will eventually
/// re-export the entities in this module.
SUBMODULE_EXPORT_AS = 17,
+
+ // Specifies the headers' UID imported by this submodule.
+ SUBMODULE_IMPORTED_HEADERS = 18,
};
/// Record types used within a comments block.
Index: clang/include/clang/Lex/Preprocessor.h
===================================================================
--- clang/include/clang/Lex/Preprocessor.h
+++ clang/include/clang/Lex/Preprocessor.h
@@ -51,6 +51,7 @@
#include <cstdint>
#include <map>
#include <memory>
+#include <set>
#include <string>
#include <utility>
#include <vector>
@@ -128,6 +129,8 @@
class Preprocessor {
friend class VAOptDefinitionContext;
friend class VariadicMacroScopeGuard;
+ friend class ASTWriter;
+ friend class ASTReader;
llvm::unique_function<void(const clang::Token &)> OnToken;
std::shared_ptr<PreprocessorOptions> PPOpts;
@@ -735,6 +738,7 @@
};
SmallVector<BuildingSubmoduleInfo, 8> BuildingSubmoduleStack;
+ // struct HeaderFileInfo;
/// Information about a submodule's preprocessor state.
struct SubmoduleState {
/// The macros for the submodule.
@@ -743,6 +747,9 @@
/// The set of modules that are visible within the submodule.
VisibleModuleSet VisibleModules;
+ /// The set of the included headers for the submodule.
+ std::set<unsigned> IncludedFiles;
+
// FIXME: CounterValue?
// FIXME: PragmaPushMacroInfo?
};
@@ -1038,6 +1045,24 @@
OnToken = std::move(F);
}
+ void setIncludeVisible(unsigned UID) {
+ CurSubmoduleState->IncludedFiles.insert(UID);
+ }
+
+ bool isIncludeVisibleFromOuterModule(unsigned UID) {
+ if (BuildingSubmoduleStack.empty())
+ return false;
+
+ auto OuterState = BuildingSubmoduleStack.back().OuterSubmoduleState;
+ return OuterState->IncludedFiles.find(UID) !=
+ OuterState->IncludedFiles.end();
+ }
+
+ bool isIncludeVisible(unsigned UID) {
+ return CurSubmoduleState->IncludedFiles.find(UID) !=
+ CurSubmoduleState->IncludedFiles.end();
+ }
+
bool isMacroDefined(StringRef Id) {
return isMacroDefined(&Identifiers.get(Id));
}
Index: clang/include/clang/Lex/HeaderSearch.h
===================================================================
--- clang/include/clang/Lex/HeaderSearch.h
+++ clang/include/clang/Lex/HeaderSearch.h
@@ -110,10 +110,14 @@
/// of the framework.
StringRef Framework;
+ /// The file UID used during [de]serialization.
+ unsigned UIDSet = false; // DO not serialize this.
+ unsigned UID = 0;
+
HeaderFileInfo()
: isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User),
External(false), isModuleHeader(false), isCompilingModuleHeader(false),
- Resolved(false), IndexHeaderMapHeader(false), IsValid(false) {}
+ Resolved(false), IndexHeaderMapHeader(false), IsValid(false) {}
/// Retrieve the controlling macro for this header file, if
/// any.
@@ -140,6 +144,8 @@
/// \c External bit set. If the file entry is not known, return a
/// default-constructed \c HeaderFileInfo.
virtual HeaderFileInfo GetHeaderFileInfo(const FileEntry *FE) = 0;
+
+ virtual void ResolvePendings() = 0;
};
/// This structure is used to record entries in our framework cache.
@@ -157,6 +163,8 @@
/// by a \#include or \#include_next, (sub-)framework lookup, etc.
class HeaderSearch {
friend class DirectoryLookup;
+ friend class ASTReader;
+ friend class ASTWriter;
/// Header-search options used to initialize this header search.
std::shared_ptr<HeaderSearchOptions> HSOpts;
@@ -664,8 +672,8 @@
/// if it has ever been filled in.
/// \param WantExternal Whether the caller wants purely-external header file
/// info (where \p External is true).
- const HeaderFileInfo *getExistingFileInfo(const FileEntry *FE,
- bool WantExternal = true) const;
+ HeaderFileInfo *getExistingFileInfo(const FileEntry *FE,
+ bool WantExternal = true) const;
// Used by external tools
using search_dir_iterator = std::vector<DirectoryLookup>::const_iterator;
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits