vsapsai updated this revision to Diff 352326.
vsapsai added a comment.
Split out smaller parts as separate reviews.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D104344/new/
https://reviews.llvm.org/D104344
Files:
clang/include/clang/Lex/HeaderSearch.h
clang/include/clang/Serialization/ASTBitCodes.h
clang/lib/Lex/PPDirectives.cpp
clang/lib/Serialization/ASTReader.cpp
clang/lib/Serialization/ASTWriter.cpp
clang/test/Modules/Inputs/import-nonmodular/Modularized.framework/Headers/Invisible.h
clang/test/Modules/Inputs/import-nonmodular/Modularized.framework/Headers/Visible.h
clang/test/Modules/Inputs/import-nonmodular/Modularized.framework/Modules/module.modulemap
clang/test/Modules/Inputs/import-nonmodular/Unmodularized.framework/Headers/Unmodularized.h
clang/test/Modules/import-nonmodular.m
Index: clang/test/Modules/import-nonmodular.m
===================================================================
--- /dev/null
+++ clang/test/Modules/import-nonmodular.m
@@ -0,0 +1,18 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fsyntax-only -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -F %S/Inputs/import-nonmodular %s -verify
+// expected-no-diagnostics
+
+// Test non-modular headers are not skipped even if they are imported by
+// non-imported submodules of an imported module. Dependency graph is
+//
+// Unmodularized.h
+// ^ ^
+// | |
+// Modularized.Visible | Modularized.Invisible
+// ^ |
+// \ |
+// import-nonmodular.m
+
+#import <Modularized/Visible.h>
+#import <Unmodularized/Unmodularized.h>
+void test(UnmodularizedStruct *s) {}
Index: clang/test/Modules/Inputs/import-nonmodular/Unmodularized.framework/Headers/Unmodularized.h
===================================================================
--- /dev/null
+++ clang/test/Modules/Inputs/import-nonmodular/Unmodularized.framework/Headers/Unmodularized.h
@@ -0,0 +1,2 @@
+typedef struct UnmodularizedStruct {
+} UnmodularizedStruct;
Index: clang/test/Modules/Inputs/import-nonmodular/Modularized.framework/Modules/module.modulemap
===================================================================
--- /dev/null
+++ clang/test/Modules/Inputs/import-nonmodular/Modularized.framework/Modules/module.modulemap
@@ -0,0 +1,11 @@
+framework module Modularized {
+ module Visible {
+ header "Visible.h"
+ export *
+ }
+
+ module Invisible {
+ header "Invisible.h"
+ export *
+ }
+}
Index: clang/test/Modules/Inputs/import-nonmodular/Modularized.framework/Headers/Visible.h
===================================================================
--- /dev/null
+++ clang/test/Modules/Inputs/import-nonmodular/Modularized.framework/Headers/Visible.h
@@ -0,0 +1 @@
+// Empty.
Index: clang/test/Modules/Inputs/import-nonmodular/Modularized.framework/Headers/Invisible.h
===================================================================
--- /dev/null
+++ clang/test/Modules/Inputs/import-nonmodular/Modularized.framework/Headers/Invisible.h
@@ -0,0 +1 @@
+#import <Unmodularized/Unmodularized.h>
Index: clang/lib/Serialization/ASTWriter.cpp
===================================================================
--- clang/lib/Serialization/ASTWriter.cpp
+++ clang/lib/Serialization/ASTWriter.cpp
@@ -1668,7 +1668,10 @@
std::pair<unsigned, unsigned>
EmitKeyDataLength(raw_ostream& Out, key_type_ref key, data_type_ref Data) {
unsigned KeyLen = key.Filename.size() + 1 + 8 + 8;
- unsigned DataLen = 1 + 2 + 4 + 4;
+ unsigned DataLen = 1 + 4 + 4 + 4;
+ for (auto ModuleIncluder : Data.HFI.ModuleIncludersMap)
+ if (Writer.getLocalOrImportedSubmoduleID(ModuleIncluder.first))
+ DataLen += 4;
for (auto ModInfo : Data.KnownHeaders)
if (Writer.getLocalOrImportedSubmoduleID(ModInfo.getModule()))
DataLen += 4;
@@ -1695,12 +1698,10 @@
endian::Writer LE(Out, little);
uint64_t Start = Out.tell(); (void)Start;
- unsigned char Flags = (Data.HFI.isImport << 5)
- | (Data.HFI.isPragmaOnce << 4)
- | (Data.HFI.DirInfo << 1)
- | Data.HFI.IndexHeaderMapHeader;
+ unsigned char Flags = (Data.HFI.isPragmaOnce << 4) |
+ (Data.HFI.DirInfo << 1) |
+ Data.HFI.IndexHeaderMapHeader;
LE.write<uint8_t>(Flags);
- LE.write<uint16_t>(Data.HFI.NumIncludes);
if (!Data.HFI.ControllingMacro)
LE.write<uint32_t>(Data.HFI.ControllingMacroID);
@@ -1723,6 +1724,18 @@
}
LE.write<uint32_t>(Offset);
+ for (auto ModuleIncluder : Data.HFI.ModuleIncludersMap) {
+ if (uint32_t ModID =
+ Writer.getLocalOrImportedSubmoduleID(ModuleIncluder.first)) {
+ uint32_t Value = (ModID << 1) | (bool)ModuleIncluder.second;
+ assert((Value >> 1) == ModID && "overflow in header module info");
+ LE.write<uint32_t>(Value);
+ }
+ }
+ // Using a stop value because cannot tell ahead of time how many includers
+ // are local or imported submodules.
+ LE.write<uint32_t>(0);
+
auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) {
if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) {
uint32_t Value = (ModID << 2) | (unsigned)Role;
Index: clang/lib/Serialization/ASTReader.cpp
===================================================================
--- clang/lib/Serialization/ASTReader.cpp
+++ clang/lib/Serialization/ASTReader.cpp
@@ -1887,14 +1887,9 @@
HeaderFileInfo HFI;
unsigned Flags = *d++;
// FIXME: Refactor with mergeHeaderFileInfo in HeaderSearch.cpp.
- HFI.isImport |= (Flags >> 5) & 0x01;
HFI.isPragmaOnce |= (Flags >> 4) & 0x01;
HFI.DirInfo = (Flags >> 1) & 0x07;
HFI.IndexHeaderMapHeader = Flags & 0x01;
- // FIXME: Find a better way to handle this. Maybe just store a
- // "has been included" flag?
- HFI.NumIncludes = std::max(endian::readNext<uint16_t, little, unaligned>(d),
- HFI.NumIncludes);
HFI.ControllingMacroID = Reader.getGlobalIdentifierID(
M, endian::readNext<uint32_t, little, unaligned>(d));
if (unsigned FrameworkOffset =
@@ -1905,6 +1900,23 @@
HFI.Framework = HS->getUniqueFrameworkName(FrameworkName);
}
+ while (true) {
+ uint32_t LocalSMID = endian::readNext<uint32_t, little, unaligned>(d);
+ if (!LocalSMID)
+ break;
+ bool IsImport = static_cast<bool>(LocalSMID & 1);
+ LocalSMID >>= 1;
+
+ SubmoduleID GlobalSMID = Reader.getGlobalSubmoduleID(M, LocalSMID);
+ Module *Mod = Reader.getSubmodule(GlobalSMID);
+ HFI.ModuleIncludersMap[Mod] = IsImport;
+ // Update isImport and NumIncludes based on including module.
+ if (Mod->NameVisibility == Module::NameVisibilityKind::AllVisible) {
+ HFI.isImport |= IsImport;
+ ++HFI.NumIncludes;
+ }
+ }
+
assert((End - d) % 4 == 0 &&
"Wrong data length in HeaderFileInfo deserialization");
while (d != End) {
@@ -1930,6 +1942,13 @@
HFI.isModuleHeader |= !(HeaderRole & ModuleMap::TextualHeader);
}
+ serialization::ModuleKind PrimaryModuleKind =
+ Reader.getModuleManager().getPrimaryModule().Kind;
+ if ((PrimaryModuleKind == MK_PCH) || (PrimaryModuleKind == MK_Preamble)) {
+ // Treat preprocessor/preamble header as included at least once.
+ ++HFI.NumIncludes;
+ }
+
// This HeaderFileInfo was externally loaded.
HFI.External = true;
HFI.IsValid = true;
Index: clang/lib/Lex/PPDirectives.cpp
===================================================================
--- clang/lib/Lex/PPDirectives.cpp
+++ clang/lib/Lex/PPDirectives.cpp
@@ -2144,6 +2144,15 @@
Action = (SuggestedModule && !getLangOpts().CompilingPCH) ? Import : Skip;
}
+ if (File) {
+ // Store extra data for inclusion from a modular header.
+ Module *RequestingModule = getModuleForLocation(HashLoc);
+ if (RequestingModule) {
+ HeaderInfo.MarkFileIncludedFromModule(&File->getFileEntry(),
+ RequestingModule, EnterOnce);
+ }
+ }
+
// 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
Index: clang/include/clang/Serialization/ASTBitCodes.h
===================================================================
--- clang/include/clang/Serialization/ASTBitCodes.h
+++ clang/include/clang/Serialization/ASTBitCodes.h
@@ -41,7 +41,7 @@
/// Version 4 of AST files also requires that the version control branch and
/// revision match exactly, since there is no backward compatibility of
/// AST files at this time.
-const unsigned VERSION_MAJOR = 13;
+const unsigned VERSION_MAJOR = 14;
/// AST file minor version number supported by this version of
/// Clang.
Index: clang/include/clang/Lex/HeaderSearch.h
===================================================================
--- clang/include/clang/Lex/HeaderSearch.h
+++ clang/include/clang/Lex/HeaderSearch.h
@@ -110,6 +110,10 @@
/// of the framework.
StringRef Framework;
+ /// Stores modules including this header.
+ /// Bool represents if the header was included or imported.
+ llvm::DenseMap<const Module *, bool> ModuleIncludersMap;
+
HeaderFileInfo()
: isImport(false), isPragmaOnce(false), DirInfo(SrcMgr::C_User),
External(false), isModuleHeader(false), isCompilingModuleHeader(false),
@@ -457,6 +461,11 @@
ModuleMap::ModuleHeaderRole Role,
bool isCompilingModuleHeader);
+ void MarkFileIncludedFromModule(const FileEntry *File, const Module *M,
+ bool isImport) {
+ getFileInfo(File).ModuleIncludersMap[M] |= isImport;
+ }
+
/// Increment the count for the number of times the specified
/// FileEntry has been entered.
void IncrementIncludeCount(const FileEntry *File) {
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits