[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
rsmith added inline comments. Comment at: clang/include/clang/Lex/Preprocessor.h:749-750 +/// The set of the included headers' UID for the submodule. +std::set IncludedFiles; + A `std::set` is a very heavy object to be copying each time a module is entered / left. I think this is also putting the cost in the wrong place: ideally we want an approach whose cost scales only with the number of `#include` / `#import` directives that name a header that should only be included once, not the number of modules entered / left after such a directive is seen, so we should be tracking the state on the `HeaderFileInfo` instead of here. So, how about this: on each `HeaderFileInfo`, track the set of module IDs in which the header file has been included in a way that suppresses further inclusion. Then when we come to consider a `#include`, check to see if any of those module IDs is visible in the includer and suppress the inclusion if so. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D75951/new/ https://reviews.llvm.org/D75951 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo added a comment. jyknight@ Hi, pinging again (sorry!) Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D75951/new/ https://reviews.llvm.org/D75951 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 254384. oontvoo added a comment. Update docs. Note: The failure looks spurious ... They seemed to pass locally for me: One eg: [hi on] vyng@vyng:~/repo/llvm-project$ ./build/bin/llvm-lit -v ./clang/test/ClangScanDeps/modules-full.cpp llvm-lit: /usr/local/google/home/vyng/repo/llvm-project/llvm/utils/lit/lit/llvm/config.py:342: note: using clang: /usr/local/google/home/vyng/repo/llvm-project/build/bin/clang - Testing: 1 tests, 1 workers -- PASS: Clang :: ClangScanDeps/modules-full.cpp (1 of 1) Testing Time: 2.75s Expected Passes: 1 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/PPDirectives.cpp clang/lib/Lex/PPLexerChange.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 = +void *q = Index: clang/test/Modules/header-in-imported-module.c === --- /dev/null +++ clang/test/Modules/header-in-imported-module.c @@ -0,0 +1,15 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: %clang -x c++ -fmodules -fmodules-ts --precompile -o %t/ModuleB39206.pcm %S/Inputs/imported_module.cppm +// RUN: %clang -x c++ -fmodules -fmodules-ts -c %t/ModuleB39206.pcm -o %t/ModuleB39206.o +// RUN: %clang -x c++ -fmodules -fmodules-ts -I%S/Inputs -fmodule-file=%t/ModuleB39206.pcm -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,6 @@ +export module ModuleB39206; +#include "header_in_imported_module.h" + +#ifndef ALL_GOOD +#error "Missing macro in module decl" +#endif \ 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(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(Offset); + // Write this file UID. + LE.write(Data.HFI.UID); + auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) { if (uint32_t ModID =
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 254321. oontvoo added a comment. clean up ... Ready to review. PTAL! =) 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/PPDirectives.cpp clang/lib/Lex/PPLexerChange.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 = +void *q = Index: clang/test/Modules/header-in-imported-module.c === --- /dev/null +++ clang/test/Modules/header-in-imported-module.c @@ -0,0 +1,14 @@ +// RUN: rm -rf %t +// RUN: %clang -fmodules -x c++ -fmodules-ts --precompile -o %t/ModuleB39206.pcm %S/Inputs/imported_module.cppm +// RUN: %clang -fmodules -x c++ -fmodules-ts -c %t/ModuleB39206.pcm -o %t/ModuleB39206.o +// RUN: %clang -fmodules -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(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(Offset); + // Write this file UID. + LE.write(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 ) { +void ASTWriter::WriteHeaderSearch(HeaderSearch ) { HeaderFileInfoTrait GeneratorTrait(*this); llvm::OnDiskChainedHashTableGenerator Generator; SmallVector SavedStrings; @@ -1783,8 +1786,7 @@ // changed since it was loaded. Also skip it if
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 253623. oontvoo added a comment. Rebaase 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 = +void *q = 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(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(Offset); + // Write this file UID. + LE.write(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 ) { +void ASTWriter::WriteHeaderSearch(HeaderSearch ) { HeaderFileInfoTrait GeneratorTrait(*this); llvm::OnDiskChainedHashTableGenerator Generator; SmallVector SavedStrings; @@ -1783,8 +1786,7 @@ // changed since it was loaded. Also skip it if it's
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
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 = +void *q = 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(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(Offset); + // Write this file UID. + LE.write(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 ) { +void ASTWriter::WriteHeaderSearch(HeaderSearch ) { HeaderFileInfoTrait GeneratorTrait(*this); llvm::OnDiskChainedHashTableGenerator Generator; SmallVector SavedStrings; @@ -1783,8 +1786,7 @@ // changed since it was
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 253382. oontvoo added a comment. Update tests 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/module.map 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 = +void *q = 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/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(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(Offset); + // Write this file UID. + LE.write(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 ) { +void ASTWriter::WriteHeaderSearch(HeaderSearch ) { HeaderFileInfoTrait GeneratorTrait(*this); llvm::OnDiskChainedHashTableGenerator Generator; SmallVector 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
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 253289. oontvoo added a comment. cleanup logging 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/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/module.map 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 +#include "dummy_pragma_once.h" +#include "dummy_textual_header.h" + +void *p = +void *q = 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/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(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(Offset); + // Write this file UID. + LE.write(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 ) { +void ASTWriter::WriteHeaderSearch(HeaderSearch ) { HeaderFileInfoTrait GeneratorTrait(*this); llvm::OnDiskChainedHashTableGenerator Generator; SmallVector 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?
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 253245. oontvoo added a comment. Updated tests and get it to pass 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/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/module.map 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 +#include "dummy_pragma_once.h" +#include "dummy_textual_header.h" + +void *p = +void *q = 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/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(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(Offset); + // Write this file UID. + LE.write(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 ) { +void ASTWriter::WriteHeaderSearch(HeaderSearch ) { HeaderFileInfoTrait GeneratorTrait(*this); llvm::OnDiskChainedHashTableGenerator Generator; SmallVector 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
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 253175. oontvoo added a comment. Merge master 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/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp clang/test/Modules/Inputs/dummy_pragma_once.h clang/test/Modules/Inputs/module.map 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,5 @@ + +#include "dummy_pragma_once.h" +#include "dummy_pragma_once.h" // Re-importing should be fine + +void *p = Index: clang/test/Modules/Inputs/module.map === --- clang/test/Modules/Inputs/module.map +++ clang/test/Modules/Inputs/module.map @@ -282,6 +282,10 @@ header "dummy.h" } +module dummy_pragma_once { + header "dummy_pragma_once.h" +} + module builtin { header "builtin.h" explicit module sub { Index: clang/test/Modules/Inputs/dummy_pragma_once.h === --- /dev/null +++ clang/test/Modules/Inputs/dummy_pragma_once.h @@ -0,0 +1,3 @@ +//#pragma once | dont need this + +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(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(Offset); + // Write this file UID. + LE.write(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 ) { +void ASTWriter::WriteHeaderSearch(HeaderSearch ) { HeaderFileInfoTrait GeneratorTrait(*this); llvm::OnDiskChainedHashTableGenerator Generator; SmallVector 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
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 253162. oontvoo added a comment. Add tests 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/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp clang/test/Modules/Inputs/dummy_pragma_once.h clang/test/Modules/Inputs/module.map 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,5 @@ + +#include "dummy_pragma_once.h" +#include "dummy_pragma_once.h" // Re-importing should be fine + +void *p = Index: clang/test/Modules/Inputs/module.map === --- clang/test/Modules/Inputs/module.map +++ clang/test/Modules/Inputs/module.map @@ -282,6 +282,10 @@ header "dummy.h" } +module dummy_pragma_once { + header "dummy_pragma_once.h" +} + module builtin { header "builtin.h" explicit module sub { Index: clang/test/Modules/Inputs/dummy_pragma_once.h === --- /dev/null +++ clang/test/Modules/Inputs/dummy_pragma_once.h @@ -0,0 +1,3 @@ +//#pragma once | dont need this + +int x = 5; Index: clang/lib/Serialization/ASTWriter.cpp === --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -1619,7 +1619,7 @@ endian::Writer LE(Out, little); unsigned KeyLen = key.Filename.size() + 1 + 8 + 8; LE.write(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; @@ -1676,6 +1676,9 @@ } LE.write(Offset); + // Write this file UID. + LE.write(Data.HFI.UID); + auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) { if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) { uint32_t Value = (ModID << 2) | (unsigned)Role; @@ -1703,7 +1706,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 ) { +void ASTWriter::WriteHeaderSearch(HeaderSearch ) { HeaderFileInfoTrait GeneratorTrait(*this); llvm::OnDiskChainedHashTableGenerator Generator; SmallVector SavedStrings; @@ -1781,8 +1784,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; @@ -1799,8 +1801,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; @@ -2634,6 +2641,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; @@ -4715,6 +4741,24 @@ if (WritingModule) WriteSubmodules(WritingModule); + // Write
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 253157. oontvoo added a comment. . 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/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp Index: clang/lib/Serialization/ASTWriter.cpp === --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -1619,7 +1619,7 @@ endian::Writer LE(Out, little); unsigned KeyLen = key.Filename.size() + 1 + 8 + 8; LE.write(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; @@ -1676,6 +1676,9 @@ } LE.write(Offset); + // Write this file UID. + LE.write(Data.HFI.UID); + auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) { if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) { uint32_t Value = (ModID << 2) | (unsigned)Role; @@ -1703,7 +1706,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 ) { +void ASTWriter::WriteHeaderSearch(HeaderSearch ) { HeaderFileInfoTrait GeneratorTrait(*this); llvm::OnDiskChainedHashTableGenerator Generator; SmallVector SavedStrings; @@ -1781,8 +1784,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; @@ -1799,8 +1801,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; @@ -2634,6 +2641,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; @@ -4715,6 +4741,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
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 253155. oontvoo added a comment. Also serialise non-mods' imported headers 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/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp Index: clang/lib/Serialization/ASTWriter.cpp === --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -1619,7 +1619,7 @@ endian::Writer LE(Out, little); unsigned KeyLen = key.Filename.size() + 1 + 8 + 8; LE.write(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; @@ -1676,6 +1676,9 @@ } LE.write(Offset); + // Write this file UID. + LE.write(Data.HFI.UID); + auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) { if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) { uint32_t Value = (ModID << 2) | (unsigned)Role; @@ -1703,7 +1706,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 ) { +void ASTWriter::WriteHeaderSearch(HeaderSearch ) { HeaderFileInfoTrait GeneratorTrait(*this); llvm::OnDiskChainedHashTableGenerator Generator; SmallVector SavedStrings; @@ -1781,8 +1784,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; @@ -1799,8 +1801,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; @@ -2634,6 +2641,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; @@ -4715,6 +4741,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
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 252791. oontvoo added a comment. Handle includes/import from outer mods 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/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp Index: clang/lib/Serialization/ASTWriter.cpp === --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -1619,7 +1619,7 @@ endian::Writer LE(Out, little); unsigned KeyLen = key.Filename.size() + 1 + 8 + 8; LE.write(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; @@ -1676,6 +1676,9 @@ } LE.write(Offset); + // Write this file UID. + LE.write(Data.HFI.UID); + auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) { if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) { uint32_t Value = (ModID << 2) | (unsigned)Role; @@ -1703,7 +1706,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 ) { +void ASTWriter::WriteHeaderSearch(HeaderSearch ) { HeaderFileInfoTrait GeneratorTrait(*this); llvm::OnDiskChainedHashTableGenerator Generator; SmallVector SavedStrings; @@ -1781,8 +1784,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; @@ -1799,8 +1801,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; @@ -2634,6 +2641,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; 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,9 @@ HFI.Framework = HS->getUniqueFrameworkName(FrameworkName); } + // Read the file old UID + HFI.UID = endian::readNext(d); + assert((End - d) % 4 == 0 && "Wrong data length in HeaderFileInfo deserialization"); while (d != End) { @@ -5615,6 +5619,11 @@ } break; +case SUBMODULE_IMPORTED_HEADERS: + for (unsigned Idx = 0; Idx < Record.size(); ++Idx) { +PendingImportedHeaders[].push_back(Record[Idx]); + } + break; case SUBMODULE_EXPORTS: for (unsigned Idx = 0; Idx + 1 < Record.size(); Idx += 2) { UnresolvedModuleRef Unresolved; @@ -9271,6 +9280,37 @@ for (auto *ND : PendingMergedDefinitionsToDeduplicate)
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 252768. oontvoo added a comment. Handle textual headers 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/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp Index: clang/lib/Serialization/ASTWriter.cpp === --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -1619,7 +1619,7 @@ endian::Writer LE(Out, little); unsigned KeyLen = key.Filename.size() + 1 + 8 + 8; LE.write(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; @@ -1676,6 +1676,9 @@ } LE.write(Offset); + // Write this file UID. + LE.write(Data.HFI.UID); + auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) { if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) { uint32_t Value = (ModID << 2) | (unsigned)Role; @@ -1703,7 +1706,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 ) { +void ASTWriter::WriteHeaderSearch(HeaderSearch ) { HeaderFileInfoTrait GeneratorTrait(*this); llvm::OnDiskChainedHashTableGenerator Generator; SmallVector SavedStrings; @@ -1781,8 +1784,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; @@ -1799,8 +1801,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; @@ -2634,6 +2641,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; 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,9 @@ HFI.Framework = HS->getUniqueFrameworkName(FrameworkName); } + // Read the file old UID + HFI.UID = endian::readNext(d); + assert((End - d) % 4 == 0 && "Wrong data length in HeaderFileInfo deserialization"); while (d != End) { @@ -5615,6 +5619,11 @@ } break; +case SUBMODULE_IMPORTED_HEADERS: + for (unsigned Idx = 0; Idx < Record.size(); ++Idx) { +PendingImportedHeaders[].push_back(Record[Idx]); + } + break; case SUBMODULE_EXPORTS: for (unsigned Idx = 0; Idx + 1 < Record.size(); Idx += 2) { UnresolvedModuleRef Unresolved; @@ -9271,6 +9280,37 @@ for (auto *ND : PendingMergedDefinitionsToDeduplicate)
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 252760. oontvoo added a comment. . 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/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp Index: clang/lib/Serialization/ASTWriter.cpp === --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -1619,7 +1619,7 @@ endian::Writer LE(Out, little); unsigned KeyLen = key.Filename.size() + 1 + 8 + 8; LE.write(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; @@ -1676,6 +1676,9 @@ } LE.write(Offset); + // Write this file UID. + LE.write(Data.HFI.UID); + auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) { if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) { uint32_t Value = (ModID << 2) | (unsigned)Role; @@ -1703,7 +1706,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 ) { +void ASTWriter::WriteHeaderSearch(HeaderSearch ) { HeaderFileInfoTrait GeneratorTrait(*this); llvm::OnDiskChainedHashTableGenerator Generator; SmallVector SavedStrings; @@ -1781,8 +1784,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; @@ -1799,8 +1801,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; @@ -2634,6 +2641,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; 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,9 @@ HFI.Framework = HS->getUniqueFrameworkName(FrameworkName); } + // Read the file old UID + HFI.UID = endian::readNext(d); + assert((End - d) % 4 == 0 && "Wrong data length in HeaderFileInfo deserialization"); while (d != End) { @@ -5615,6 +5619,11 @@ } break; +case SUBMODULE_IMPORTED_HEADERS: + for (unsigned Idx = 0; Idx < Record.size(); ++Idx) { +PendingImportedHeaders[].push_back(Record[Idx]); + } + break; case SUBMODULE_EXPORTS: for (unsigned Idx = 0; Idx + 1 < Record.size(); Idx += 2) { UnresolvedModuleRef Unresolved; @@ -9271,6 +9280,37 @@ for (auto *ND : PendingMergedDefinitionsToDeduplicate)
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 252761. oontvoo added a comment. . 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/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp Index: clang/lib/Serialization/ASTWriter.cpp === --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -1619,7 +1619,7 @@ endian::Writer LE(Out, little); unsigned KeyLen = key.Filename.size() + 1 + 8 + 8; LE.write(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; @@ -1676,6 +1676,9 @@ } LE.write(Offset); + // Write this file UID. + LE.write(Data.HFI.UID); + auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) { if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) { uint32_t Value = (ModID << 2) | (unsigned)Role; @@ -1703,7 +1706,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 ) { +void ASTWriter::WriteHeaderSearch(HeaderSearch ) { HeaderFileInfoTrait GeneratorTrait(*this); llvm::OnDiskChainedHashTableGenerator Generator; SmallVector SavedStrings; @@ -1781,8 +1784,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; @@ -1799,8 +1801,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; @@ -2634,6 +2641,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; 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,9 @@ HFI.Framework = HS->getUniqueFrameworkName(FrameworkName); } + // Read the file old UID + HFI.UID = endian::readNext(d); + assert((End - d) % 4 == 0 && "Wrong data length in HeaderFileInfo deserialization"); while (d != End) { @@ -5615,6 +5619,11 @@ } break; +case SUBMODULE_IMPORTED_HEADERS: + for (unsigned Idx = 0; Idx < Record.size(); ++Idx) { +PendingImportedHeaders[].push_back(Record[Idx]); + } + break; case SUBMODULE_EXPORTS: for (unsigned Idx = 0; Idx + 1 < Record.size(); Idx += 2) { UnresolvedModuleRef Unresolved; @@ -9271,6 +9280,37 @@ for (auto *ND : PendingMergedDefinitionsToDeduplicate)
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 252738. oontvoo added a comment. ... 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/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp Index: clang/lib/Serialization/ASTWriter.cpp === --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -1619,7 +1619,7 @@ endian::Writer LE(Out, little); unsigned KeyLen = key.Filename.size() + 1 + 8 + 8; LE.write(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; @@ -1676,6 +1676,9 @@ } LE.write(Offset); + // Write this file UID. + LE.write(Data.HFI.UID); + auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) { if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) { uint32_t Value = (ModID << 2) | (unsigned)Role; @@ -1703,7 +1706,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 ) { +void ASTWriter::WriteHeaderSearch(HeaderSearch ) { HeaderFileInfoTrait GeneratorTrait(*this); llvm::OnDiskChainedHashTableGenerator Generator; SmallVector SavedStrings; @@ -1781,8 +1784,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; @@ -1799,8 +1801,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; @@ -2634,6 +2641,18 @@ 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 (const HeaderFileInfo *HFI : it->second.IncludedFiles) { + Record.push_back(HFI->UID); +} +Stream.EmitRecord(SUBMODULE_IMPORTED_HEADERS, Record); + } +} + // Emit the exports. if (!Mod->Exports.empty()) { RecordData Record; Index: clang/lib/Serialization/ASTReader.cpp === --- clang/lib/Serialization/ASTReader.cpp +++ clang/lib/Serialization/ASTReader.cpp @@ -1898,6 +1898,9 @@ HFI.Framework = HS->getUniqueFrameworkName(FrameworkName); } + // Read the file old UID + HFI.UID = endian::readNext(d); + assert((End - d) % 4 == 0 && "Wrong data length in HeaderFileInfo deserialization"); while (d != End) { @@ -5615,6 +5618,11 @@ } break; +case SUBMODULE_IMPORTED_HEADERS: + for (unsigned Idx = 0; Idx < Record.size(); ++Idx) { +PendingImportedHeaders[].push_back(Record[Idx]); + } + break; case SUBMODULE_EXPORTS: for (unsigned Idx = 0; Idx + 1 < Record.size(); Idx += 2) { UnresolvedModuleRef Unresolved; @@ -9271,6 +9279,38 @@ for (auto *ND : PendingMergedDefinitionsToDeduplicate) getContext().deduplicateMergedDefinitonsFor(ND); PendingMergedDefinitionsToDeduplicate.clear(); + + // Fix up the HeaderSearchInfo UIDs. + if (!PendingImportedHeaders.empty()) { +std::map UIDToIndex; + +// These HFIs were deserialized and assigned their "old" +// UID. +// We need to update them and populate the OldToIndex map +// for use next. +HeaderSearch = PP.getHeaderSearchInfo(); +for (unsigned Idx = 0; Idx < HS.FileInfo.size(); ++Idx) { + UIDToIndex[HS.FileInfo[Idx].UID] = Idx; + // Clear the no longer useful UID fields. + HS.FileInfo[Idx].UID = 0; +} + +
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 252735. oontvoo added a comment. 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/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp Index: clang/lib/Serialization/ASTWriter.cpp === --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -1619,7 +1619,7 @@ endian::Writer LE(Out, little); unsigned KeyLen = key.Filename.size() + 1 + 8 + 8; LE.write(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; @@ -1676,6 +1676,9 @@ } LE.write(Offset); + // Write this file UID. + LE.write(Data.HFI.UID); + auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) { if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) { uint32_t Value = (ModID << 2) | (unsigned)Role; @@ -1703,7 +1706,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 ) { +void ASTWriter::WriteHeaderSearch(HeaderSearch ) { HeaderFileInfoTrait GeneratorTrait(*this); llvm::OnDiskChainedHashTableGenerator Generator; SmallVector SavedStrings; @@ -1781,8 +1784,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; @@ -1799,8 +1801,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; @@ -2634,6 +2641,18 @@ 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 (const HeaderFileInfo *HFI : it->second.IncludedFiles) { + Record.push_back(HFI->UID); +} +Stream.EmitRecord(SUBMODULE_IMPORTED_HEADERS, Record); + } +} + // Emit the exports. if (!Mod->Exports.empty()) { RecordData Record; Index: clang/lib/Serialization/ASTReader.cpp === --- clang/lib/Serialization/ASTReader.cpp +++ clang/lib/Serialization/ASTReader.cpp @@ -1898,6 +1898,9 @@ HFI.Framework = HS->getUniqueFrameworkName(FrameworkName); } + // Read the file old UID + HFI.UID = endian::readNext(d); + assert((End - d) % 4 == 0 && "Wrong data length in HeaderFileInfo deserialization"); while (d != End) { @@ -5615,6 +5618,11 @@ } break; +case SUBMODULE_IMPORTED_HEADERS: + for (unsigned Idx = 0; Idx < Record.size(); ++Idx) { +PendingImportedHeaders[].push_back(Record[Idx]); + } + break; case SUBMODULE_EXPORTS: for (unsigned Idx = 0; Idx + 1 < Record.size(); Idx += 2) { UnresolvedModuleRef Unresolved; @@ -9271,6 +9279,38 @@ for (auto *ND : PendingMergedDefinitionsToDeduplicate) getContext().deduplicateMergedDefinitonsFor(ND); PendingMergedDefinitionsToDeduplicate.clear(); + + // Fix up the HeaderSearchInfo UIDs. + if (!PendingImportedHeaders.empty()) { +std::map UIDToIndex; + +// These HFIs were deserialized and assigned their "old" +// UID. +// We need to update them and populate the OldToIndex map +// for use next. +HeaderSearch = PP.getHeaderSearchInfo(); +for (unsigned Idx = 0; Idx < HS.FileInfo.size(); ++Idx) { + UIDToIndex[HS.FileInfo[Idx].UID] = Idx; + // Clear the no longer useful UID fields. + HS.FileInfo[Idx].UID = 0; +} + +
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 252728. oontvoo added a comment. Typo - missing ! operator 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/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp Index: clang/lib/Serialization/ASTWriter.cpp === --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -1619,7 +1619,7 @@ endian::Writer LE(Out, little); unsigned KeyLen = key.Filename.size() + 1 + 8 + 8; LE.write(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; @@ -1676,6 +1676,9 @@ } LE.write(Offset); + // Write this file UID. + LE.write(Data.HFI.UID); + auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) { if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) { uint32_t Value = (ModID << 2) | (unsigned)Role; @@ -1703,7 +1706,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 ) { +void ASTWriter::WriteHeaderSearch(HeaderSearch ) { HeaderFileInfoTrait GeneratorTrait(*this); llvm::OnDiskChainedHashTableGenerator Generator; SmallVector SavedStrings; @@ -1781,8 +1784,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; @@ -1799,8 +1801,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; @@ -2634,6 +2641,18 @@ 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 (const HeaderFileInfo *HFI : it->second.IncludedFiles) { + Record.push_back(HFI->UID); +} +Stream.EmitRecord(SUBMODULE_IMPORTED_HEADERS, Record); + } +} + // Emit the exports. if (!Mod->Exports.empty()) { RecordData Record; Index: clang/lib/Serialization/ASTReader.cpp === --- clang/lib/Serialization/ASTReader.cpp +++ clang/lib/Serialization/ASTReader.cpp @@ -1898,6 +1898,9 @@ HFI.Framework = HS->getUniqueFrameworkName(FrameworkName); } + // Read the file old UID + HFI.UID = endian::readNext(d); + assert((End - d) % 4 == 0 && "Wrong data length in HeaderFileInfo deserialization"); while (d != End) { @@ -5615,6 +5618,11 @@ } break; +case SUBMODULE_IMPORTED_HEADERS: + for (unsigned Idx = 0; Idx < Record.size(); ++Idx) { +PendingImportedHeaders[].push_back(Record[Idx]); + } + break; case SUBMODULE_EXPORTS: for (unsigned Idx = 0; Idx + 1 < Record.size(); Idx += 2) { UnresolvedModuleRef Unresolved; @@ -9271,6 +9279,38 @@ for (auto *ND : PendingMergedDefinitionsToDeduplicate) getContext().deduplicateMergedDefinitonsFor(ND); PendingMergedDefinitionsToDeduplicate.clear(); + + // Fix up the HeaderSearchInfo UIDs. + if (!PendingImportedHeaders.empty()) { +std::map UIDToIndex; + +// These HFIs were deserialized and assigned their "old" +// UID. +// We need to update them and populate the OldToIndex map +// for use next. +HeaderSearch = PP.getHeaderSearchInfo(); +for (unsigned Idx = 0; Idx < HS.FileInfo.size(); ++Idx) { + UIDToIndex[HS.FileInfo[Idx].UID] = Idx; + // Clear the no longer useful UID fields. +
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 252685. oontvoo added a comment. Handle the case where the file is first seen 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/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp Index: clang/lib/Serialization/ASTWriter.cpp === --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -1619,7 +1619,7 @@ endian::Writer LE(Out, little); unsigned KeyLen = key.Filename.size() + 1 + 8 + 8; LE.write(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; @@ -1676,6 +1676,9 @@ } LE.write(Offset); + // Write this file UID. + LE.write(Data.HFI.UID); + auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) { if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) { uint32_t Value = (ModID << 2) | (unsigned)Role; @@ -1703,7 +1706,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 ) { +void ASTWriter::WriteHeaderSearch(HeaderSearch ) { HeaderFileInfoTrait GeneratorTrait(*this); llvm::OnDiskChainedHashTableGenerator Generator; SmallVector SavedStrings; @@ -1781,8 +1784,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; @@ -1799,8 +1801,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; @@ -2634,6 +2641,18 @@ 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 (const HeaderFileInfo *HFI : it->second.IncludedFiles) { + Record.push_back(HFI->UID); +} +Stream.EmitRecord(SUBMODULE_IMPORTED_HEADERS, Record); + } +} + // Emit the exports. if (!Mod->Exports.empty()) { RecordData Record; Index: clang/lib/Serialization/ASTReader.cpp === --- clang/lib/Serialization/ASTReader.cpp +++ clang/lib/Serialization/ASTReader.cpp @@ -1898,6 +1898,9 @@ HFI.Framework = HS->getUniqueFrameworkName(FrameworkName); } + // Read the file old UID + HFI.UID = endian::readNext(d); + assert((End - d) % 4 == 0 && "Wrong data length in HeaderFileInfo deserialization"); while (d != End) { @@ -5615,6 +5618,11 @@ } break; +case SUBMODULE_IMPORTED_HEADERS: + for (unsigned Idx = 0; Idx < Record.size(); ++Idx) { +PendingImportedHeaders[].push_back(Record[Idx]); + } + break; case SUBMODULE_EXPORTS: for (unsigned Idx = 0; Idx + 1 < Record.size(); Idx += 2) { UnresolvedModuleRef Unresolved; @@ -9271,6 +9279,38 @@ for (auto *ND : PendingMergedDefinitionsToDeduplicate) getContext().deduplicateMergedDefinitonsFor(ND); PendingMergedDefinitionsToDeduplicate.clear(); + + // Fix up the HeaderSearchInfo UIDs. + if (!PendingImportedHeaders.empty()) { +std::map UIDToIndex; + +// These HFIs were deserialized and assigned their "old" +// UID. +// We need to update them and populate the OldToIndex map +// for use next. +HeaderSearch = PP.getHeaderSearchInfo(); +for (unsigned Idx = 0; Idx < HS.FileInfo.size(); ++Idx) { + UIDToIndex[HS.FileInfo[Idx].UID] = Idx; + // Clear the no longer useful UID fields. +
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo added a comment. @jyknight Actually, please hold on on the review ... still working on it Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D75951/new/ https://reviews.llvm.org/D75951 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 252371. oontvoo added a comment. clang format 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/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp Index: clang/lib/Serialization/ASTWriter.cpp === --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -1619,7 +1619,7 @@ endian::Writer LE(Out, little); unsigned KeyLen = key.Filename.size() + 1 + 8 + 8; LE.write(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; @@ -1676,6 +1676,9 @@ } LE.write(Offset); + // Write this file UID. + LE.write(Data.HFI.UID); + auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) { if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) { uint32_t Value = (ModID << 2) | (unsigned)Role; @@ -1703,7 +1706,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 ) { +void ASTWriter::WriteHeaderSearch(HeaderSearch ) { HeaderFileInfoTrait GeneratorTrait(*this); llvm::OnDiskChainedHashTableGenerator Generator; SmallVector SavedStrings; @@ -1781,8 +1784,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; @@ -1799,8 +1801,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; @@ -2634,6 +2641,18 @@ 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 (const HeaderFileInfo *HFI : it->second.IncludedFiles) { + Record.push_back(HFI->UID); +} +Stream.EmitRecord(SUBMODULE_IMPORTED_HEADERS, Record); + } +} + // Emit the exports. if (!Mod->Exports.empty()) { RecordData Record; Index: clang/lib/Serialization/ASTReader.cpp === --- clang/lib/Serialization/ASTReader.cpp +++ clang/lib/Serialization/ASTReader.cpp @@ -1898,6 +1898,9 @@ HFI.Framework = HS->getUniqueFrameworkName(FrameworkName); } + // Read the file old UID + HFI.UID = endian::readNext(d); + assert((End - d) % 4 == 0 && "Wrong data length in HeaderFileInfo deserialization"); while (d != End) { @@ -5615,6 +5618,11 @@ } break; +case SUBMODULE_IMPORTED_HEADERS: + for (unsigned Idx = 0; Idx < Record.size(); ++Idx) { +PendingImportedHeaders[].push_back(Record[Idx]); + } + break; case SUBMODULE_EXPORTS: for (unsigned Idx = 0; Idx + 1 < Record.size(); Idx += 2) { UnresolvedModuleRef Unresolved; @@ -9271,6 +9279,38 @@ for (auto *ND : PendingMergedDefinitionsToDeduplicate) getContext().deduplicateMergedDefinitonsFor(ND); PendingMergedDefinitionsToDeduplicate.clear(); + + // Fix up the HeaderSearchInfo UIDs. + if (!PendingImportedHeaders.empty()) { +std::map UIDToIndex; + +// These HFIs were deserialized and assigned their "old" +// UID. +// We need to update them and populate the OldToIndex map +// for use next. +HeaderSearch = PP.getHeaderSearchInfo(); +for (unsigned Idx = 0; Idx < HS.FileInfo.size(); ++Idx) { + UIDToIndex[HS.FileInfo[Idx].UID] = Idx; + // Clear the no longer useful UID fields. + HS.FileInfo[Idx].UID = 0; +
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo marked an inline comment as done. oontvoo added a comment. Addressed comments. PTAL. Thanks! Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D75951/new/ https://reviews.llvm.org/D75951 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 252237. oontvoo added a comment. Cleanup 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/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp Index: clang/lib/Serialization/ASTWriter.cpp === --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -1676,6 +1676,9 @@ } LE.write(Offset); + // Write this file UID. + LE.write(Data.HFI.UID); + auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) { if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) { uint32_t Value = (ModID << 2) | (unsigned)Role; @@ -1703,7 +1706,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 ) { +void ASTWriter::WriteHeaderSearch(HeaderSearch ) { HeaderFileInfoTrait GeneratorTrait(*this); llvm::OnDiskChainedHashTableGenerator Generator; SmallVector SavedStrings; @@ -1781,7 +1784,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 = +HeaderFileInfo *HFI = HS.getExistingFileInfo(File, /*WantExternal*/!Chain); if (!HFI || (HFI->isModuleHeader && !HFI->isCompilingModuleHeader)) continue; @@ -1799,8 +1802,11 @@ 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; @@ -2634,6 +2640,18 @@ 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 (const HeaderFileInfo* HFI : it->second.IncludedFiles) { + Record.push_back(HFI->UID); +} +Stream.EmitRecord(SUBMODULE_IMPORTED_HEADERS, Record); + } +} + // Emit the exports. if (!Mod->Exports.empty()) { RecordData Record; Index: clang/lib/Serialization/ASTReader.cpp === --- clang/lib/Serialization/ASTReader.cpp +++ clang/lib/Serialization/ASTReader.cpp @@ -1898,6 +1898,9 @@ HFI.Framework = HS->getUniqueFrameworkName(FrameworkName); } + // Read the file old UID + HFI.UID = endian::readNext(d); + assert((End - d) % 4 == 0 && "Wrong data length in HeaderFileInfo deserialization"); while (d != End) { @@ -5615,6 +5618,11 @@ } break; + case SUBMODULE_IMPORTED_HEADERS: +for (unsigned Idx = 0; Idx < Record.size(); ++Idx) { + PendingImportedHeaders[].push_back(Record[Idx]); +} +break; case SUBMODULE_EXPORTS: for (unsigned Idx = 0; Idx + 1 < Record.size(); Idx += 2) { UnresolvedModuleRef Unresolved; @@ -9271,6 +9279,38 @@ for (auto *ND : PendingMergedDefinitionsToDeduplicate) getContext().deduplicateMergedDefinitonsFor(ND); PendingMergedDefinitionsToDeduplicate.clear(); + + // Fix up the HeaderSearchInfo UIDs. + if (!PendingImportedHeaders.empty()) { +std::map UIDToIndex; + +// These HFIs were deserialized and assigned their "old" +// UID. +// We need to update them and populate the OldToIndex map +// for use next. +HeaderSearch = PP.getHeaderSearchInfo(); +for (unsigned Idx = 0; Idx < HS.FileInfo.size(); ++Idx) { + UIDToIndex[HS.FileInfo[Idx].UID] = Idx; + // Clear the no longer useful UID fields. + HS.FileInfo[Idx].UID = 0; +} + +const auto = PendingImportedHeaders.begin(); +for (unsigned I = 0; I < PendingImportedHeaders.size(); ++I) { + ModuleFile *ModFile = Iter[I].first; + auto = Iter[I].second; + Module *M = HS.lookupModule(ModFile->ModuleName); + + Preprocessor::SubmoduleState = PP.Submodules[M]; + for (unsigned OldUID : HeaderUIDs) { +auto IdxIt = UIDToIndex.find(OldUID); +assert(IdxIt !=
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 252205. oontvoo added a comment. Fix build errors 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/lib/Lex/HeaderSearch.cpp clang/lib/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp Index: clang/lib/Serialization/ASTWriter.cpp === --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -1599,6 +1599,8 @@ const HeaderFileInfo ArrayRef KnownHeaders; UnresolvedModule Unresolved; + uint32_t UID; + uint32_t FileIndex; }; using data_type_ref = const data_type &; @@ -1676,6 +1678,10 @@ } LE.write(Offset); + // Write this file UID and its index into the array where it was written. + LE.write(Data.UID); + LE.write(Data.FileIndex); + auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) { if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) { uint32_t Value = (ModID << 2) | (unsigned)Role; @@ -1800,7 +1806,8 @@ Filename, File->getSize(), getTimestampForOutput(File) }; HeaderFileInfoTrait::data_type Data = { - *HFI, HS.getModuleMap().findAllModulesForHeader(File), {} + *HFI, HS.getModuleMap().findAllModulesForHeader(File), {}, + File->getUID(), UID, }; Generator.insert(Key, Data, GeneratorTrait); ++NumHeaderSearchEntries; @@ -2634,6 +2641,18 @@ 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 (auto FileUID : it->second.IncludedFiles) { + Record.push_back(FileUID); +} +Stream.EmitRecord(SUBMODULE_IMPORTED_HEADERS, Record); + } +} + // Emit the exports. if (!Mod->Exports.empty()) { RecordData Record; Index: clang/lib/Serialization/ASTReader.cpp === --- clang/lib/Serialization/ASTReader.cpp +++ clang/lib/Serialization/ASTReader.cpp @@ -1898,6 +1898,13 @@ HFI.Framework = HS->getUniqueFrameworkName(FrameworkName); } + // Read the file old UID + { +HFI.UID = endian::readNext(d); +//TODO: seems the index is not needed +const uint32_t OldIndex = endian::readNext(d); + } + assert((End - d) % 4 == 0 && "Wrong data length in HeaderFileInfo deserialization"); while (d != End) { @@ -9271,6 +9278,37 @@ for (auto *ND : PendingMergedDefinitionsToDeduplicate) getContext().deduplicateMergedDefinitonsFor(ND); PendingMergedDefinitionsToDeduplicate.clear(); + + // Fix up the HeaderSearchInfo UIDs. + if (!PendingImportedHeaders.empty()){ +std::map OldToNewUID; + +// These HFIs were deserialized and assigned their "old" +// UID. +// We need to update them and populate the OldToNewUID map +// for use next. +HeaderSearch& HS = PP.getHeaderSearchInfo(); +for (unsigned NewUID = 0; NewUID < HS.FileInfo.size(); ++NewUID) { + OldToNewUID[HS.FileInfo[NewUID].UID] = NewUID; + HS.FileInfo[NewUID].UID = NewUID; +} + +const auto& Iter = PendingImportedHeaders.begin(); +for (unsigned I = 0; I < PendingImportedHeaders.size(); ++I){ + ModuleFile* ModFile = Iter[I].first; + auto& HeaderUIDs = Iter[I].second; + Module *M = HS.lookupModule(ModFile->ModuleName); + + Preprocessor::SubmoduleState& SubState = PP.Submodules[M]; + for (unsigned OldUid : HeaderUIDs) { +auto NewUIDIt = OldToNewUID.find(OldUid); +assert(NewUIDIt != OldToNewUID.end()); + +SubState.IncludedFiles.insert(NewUIDIt->second); + } +} +PendingImportedHeaders.clear(); + } } void ASTReader::diagnoseOdrViolations() { Index: clang/lib/Lex/HeaderSearch.cpp === --- clang/lib/Lex/HeaderSearch.cpp +++ clang/lib/Lex/HeaderSearch.cpp @@ -1253,60 +1253,21 @@ // Get information about this file. HeaderFileInfo = 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,
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 252206. oontvoo added a comment. Clang format 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/lib/Lex/HeaderSearch.cpp clang/lib/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp Index: clang/lib/Serialization/ASTWriter.cpp === --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -1599,6 +1599,8 @@ const HeaderFileInfo ArrayRef KnownHeaders; UnresolvedModule Unresolved; + uint32_t UID; + uint32_t FileIndex; }; using data_type_ref = const data_type &; @@ -1676,6 +1678,10 @@ } LE.write(Offset); + // Write this file UID and its index into the array where it was written. + LE.write(Data.UID); + LE.write(Data.FileIndex); + auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) { if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) { uint32_t Value = (ModID << 2) | (unsigned)Role; @@ -1800,7 +1806,9 @@ Filename, File->getSize(), getTimestampForOutput(File) }; HeaderFileInfoTrait::data_type Data = { - *HFI, HS.getModuleMap().findAllModulesForHeader(File), {} +*HFI, HS.getModuleMap().findAllModulesForHeader(File), +{}, File->getUID(), +UID, }; Generator.insert(Key, Data, GeneratorTrait); ++NumHeaderSearchEntries; @@ -2634,6 +2642,18 @@ 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 (auto FileUID : it->second.IncludedFiles) { + Record.push_back(FileUID); +} +Stream.EmitRecord(SUBMODULE_IMPORTED_HEADERS, Record); + } +} + // Emit the exports. if (!Mod->Exports.empty()) { RecordData Record; Index: clang/lib/Serialization/ASTReader.cpp === --- clang/lib/Serialization/ASTReader.cpp +++ clang/lib/Serialization/ASTReader.cpp @@ -1898,6 +1898,13 @@ HFI.Framework = HS->getUniqueFrameworkName(FrameworkName); } + // Read the file old UID + { +HFI.UID = endian::readNext(d); +// TODO: seems the index is not needed +const uint32_t OldIndex = endian::readNext(d); + } + assert((End - d) % 4 == 0 && "Wrong data length in HeaderFileInfo deserialization"); while (d != End) { @@ -9271,6 +9278,37 @@ for (auto *ND : PendingMergedDefinitionsToDeduplicate) getContext().deduplicateMergedDefinitonsFor(ND); PendingMergedDefinitionsToDeduplicate.clear(); + + // Fix up the HeaderSearchInfo UIDs. + if (!PendingImportedHeaders.empty()) { +std::map OldToNewUID; + +// These HFIs were deserialized and assigned their "old" +// UID. +// We need to update them and populate the OldToNewUID map +// for use next. +HeaderSearch = PP.getHeaderSearchInfo(); +for (unsigned NewUID = 0; NewUID < HS.FileInfo.size(); ++NewUID) { + OldToNewUID[HS.FileInfo[NewUID].UID] = NewUID; + HS.FileInfo[NewUID].UID = NewUID; +} + +const auto = PendingImportedHeaders.begin(); +for (unsigned I = 0; I < PendingImportedHeaders.size(); ++I) { + ModuleFile *ModFile = Iter[I].first; + auto = Iter[I].second; + Module *M = HS.lookupModule(ModFile->ModuleName); + + Preprocessor::SubmoduleState = PP.Submodules[M]; + for (unsigned OldUid : HeaderUIDs) { +auto NewUIDIt = OldToNewUID.find(OldUid); +assert(NewUIDIt != OldToNewUID.end()); + +SubState.IncludedFiles.insert(NewUIDIt->second); + } +} +PendingImportedHeaders.clear(); + } } void ASTReader::diagnoseOdrViolations() { Index: clang/lib/Lex/HeaderSearch.cpp === --- clang/lib/Lex/HeaderSearch.cpp +++ clang/lib/Lex/HeaderSearch.cpp @@ -1253,60 +1253,22 @@ // Get information about this file. HeaderFileInfo = 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:
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 252203. oontvoo added a comment. (hopefully) Final revision ... running out of idea for edit comment 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/lib/Lex/HeaderSearch.cpp clang/lib/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp Index: clang/lib/Serialization/ASTWriter.cpp === --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -1599,6 +1599,8 @@ const HeaderFileInfo ArrayRef KnownHeaders; UnresolvedModule Unresolved; + uint32_t UID; + uint32_t FileIndex; }; using data_type_ref = const data_type &; @@ -1676,6 +1678,10 @@ } LE.write(Offset); + // Write this file UID and its index into the array where it was written. + LE.write(Data.UID); + LE.write(Data.FileIndex); + auto EmitModule = [&](Module *M, ModuleMap::ModuleHeaderRole Role) { if (uint32_t ModID = Writer.getLocalOrImportedSubmoduleID(M)) { uint32_t Value = (ModID << 2) | (unsigned)Role; @@ -1800,7 +1806,8 @@ Filename, File->getSize(), getTimestampForOutput(File) }; HeaderFileInfoTrait::data_type Data = { - *HFI, HS.getModuleMap().findAllModulesForHeader(File), {} + *HFI, HS.getModuleMap().findAllModulesForHeader(File), {}, + File->getUID(), UID, }; Generator.insert(Key, Data, GeneratorTrait); ++NumHeaderSearchEntries; @@ -2634,6 +2641,18 @@ 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 (auto FileUID : it->second.IncludedFiles) { + Record.push_back(FileUID); +} +Stream.EmitRecord(SUBMODULE_IMPORTED_HEADERS, Record); + } +} + // Emit the exports. if (!Mod->Exports.empty()) { RecordData Record; Index: clang/lib/Serialization/ASTReader.cpp === --- clang/lib/Serialization/ASTReader.cpp +++ clang/lib/Serialization/ASTReader.cpp @@ -1898,6 +1898,13 @@ HFI.Framework = HS->getUniqueFrameworkName(FrameworkName); } + // Read the file old UID + { +HFI.UID = endian::readNext(d); +//TODO: seems the index is not needed +const uint32_t OldIndex = endian::readNext(d); + } + assert((End - d) % 4 == 0 && "Wrong data length in HeaderFileInfo deserialization"); while (d != End) { @@ -9271,6 +9278,37 @@ for (auto *ND : PendingMergedDefinitionsToDeduplicate) getContext().deduplicateMergedDefinitonsFor(ND); PendingMergedDefinitionsToDeduplicate.clear(); + + // Fix up the HeaderSearchInfo UIDs. + if (!PendingImportedHeaders.empty()){ +std::map OldToNewUID; + +// These HFIs were deserialized and assigned their "old" +// UID. +// We need to update them and populate the OldToNewUID map +// for use next. +HeaderSearch& HS = PP->getHeaderSearchInfo(); +for (unsigned NewUID = 0; NewUID < HS.FileInfo.size(); ++NewUID) { + OldToNewUID[HS.FileInfo[NewUID].UID] = NewUID; + HS.FileInfo[NewUID].UID = NewUID; +} + +auto& Iter = PendingImportedHeaders.begin(); +for (unsigned I = 0; I < PendingImportedHeaders.size(); ++I){ + ModuleFile* ModFile = Iter[I].first; + auto& HeaderUIDs = Iter[I].second; + Module *M = HS.lookupModule(ModFile->ModuleName); + + SubmoduleState& SubState = PP.Submodulels[M]; + for (unsigned OldUid : HeaderUIDs) { +auto NewUIDIt = OldToNewUID.find(OldUid); +assert(NewUIDIt != OldToNewUID.end()); + +SubState.IncludedFiles.insert(NewUIDIt->second); + } +} +PendingImportedHeaders.clear(); + } } void ASTReader::diagnoseOdrViolations() { Index: clang/lib/Lex/HeaderSearch.cpp === --- clang/lib/Lex/HeaderSearch.cpp +++ clang/lib/Lex/HeaderSearch.cpp @@ -1253,60 +1253,21 @@ // Get information about this file. HeaderFileInfo = 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 * } -// -
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 252118. oontvoo added a comment. Clear pending action. 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/ASTReader.h clang/lib/Lex/HeaderSearch.cpp clang/lib/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp Index: clang/lib/Serialization/ASTWriter.cpp === --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -1676,6 +1676,14 @@ } LE.write(Offset); + // Writes the number of importers. + LE.write(Data.HFI.Importers.size()); + if (!Data.HFI.Importers.empty()){ +for (const FileEntry* F : Data.HFI.Importers) { + LE.write(F->getUID()); +} + } + 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 @@ -1898,6 +1898,20 @@ HFI.Framework = HS->getUniqueFrameworkName(FrameworkName); } + { +const uint32_t ImportersCount = endian::readNext(d)); +if (ImportersCount > 0) { + // Read the file UIDs and temporarily save it because we don't have + // the FileEntry for these yet. + for (int i = 0; i < ImportersCount; ++i) { +HFI.ImportersUIDs.push_back(endian::readNext(d)); + } + // TODO: This is a little inefficient. But don't know of a way to + // stores only this HFI. + Reader.addPendingHeaderSearch(HS); +} + } + assert((End - d) % 4 == 0 && "Wrong data length in HeaderFileInfo deserialization"); while (d != End) { @@ -9068,7 +9082,7 @@ while (!PendingIdentifierInfos.empty() || !PendingFunctionTypes.empty() || !PendingIncompleteDeclChains.empty() || !PendingDeclChains.empty() || !PendingMacroIDs.empty() || !PendingDeclContextInfos.empty() || - !PendingUpdateRecords.empty()) { + !PendingUpdateRecords.empty() || !PendingHeaderSearch.empty()) { // If any identifiers with corresponding top-level declarations have // been loaded, load those declarations now. using TopLevelDeclsMap = @@ -9143,6 +9157,18 @@ } PendingMacroIDs.clear(); +for (auto PendingHS : PendingHeaderSearch) { + for (HeaderFileInfo& HFI : PendingHS->FileInfo){ +if (!HFI.FinishedLoadingImporters) { + for (uint32_t FUID : HFI.ImporterUIDs) { +// TODO: find the FileEntry based on UID?? + } + HFI.FinishedLoadingImporters = true; +} + } +} +PendingHeaderSearch.clear(); + // Wire up the DeclContexts for Decls that we delayed setting until // recursive loading is completed. while (!PendingDeclContextInfos.empty()) { Index: clang/lib/Lex/HeaderSearch.cpp === --- clang/lib/Lex/HeaderSearch.cpp +++ clang/lib/Lex/HeaderSearch.cpp @@ -1253,60 +1253,22 @@ // Get information about this file. HeaderFileInfo = 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
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 252117. oontvoo marked an inline comment as done. oontvoo added a comment. Add a PendingHeaderSearch set 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/ASTReader.h clang/lib/Lex/HeaderSearch.cpp clang/lib/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp Index: clang/lib/Serialization/ASTWriter.cpp === --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -1676,6 +1676,14 @@ } LE.write(Offset); + // Writes the number of importers. + LE.write(Data.HFI.Importers.size()); + if (!Data.HFI.Importers.empty()){ +for (const FileEntry* F : Data.HFI.Importers) { + LE.write(F->getUID()); +} + } + 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 @@ -1898,6 +1898,20 @@ HFI.Framework = HS->getUniqueFrameworkName(FrameworkName); } + { +const uint32_t ImportersCount = endian::readNext(d)); +if (ImportersCount > 0) { + // Read the file UIDs and temporarily save it because we don't have + // the FileEntry for these yet. + for (int i = 0; i < ImportersCount; ++i) { +HFI.ImportersUIDs.push_back(endian::readNext(d)); + } + // TODO: This is a little inefficient. But don't know of a way to + // stores only this HFI. + Reader.addPendingHeaderSearch(HS); +} + } + assert((End - d) % 4 == 0 && "Wrong data length in HeaderFileInfo deserialization"); while (d != End) { @@ -9068,7 +9082,7 @@ while (!PendingIdentifierInfos.empty() || !PendingFunctionTypes.empty() || !PendingIncompleteDeclChains.empty() || !PendingDeclChains.empty() || !PendingMacroIDs.empty() || !PendingDeclContextInfos.empty() || - !PendingUpdateRecords.empty()) { + !PendingUpdateRecords.empty() || !PendingHeaderSearch.empty()) { // If any identifiers with corresponding top-level declarations have // been loaded, load those declarations now. using TopLevelDeclsMap = @@ -9143,6 +9157,17 @@ } PendingMacroIDs.clear(); +for (auto PendingHS : PendingHeaderSearch) { + for (HeaderFileInfo& HFI : PendingHS->FileInfo){ +if (!HFI.FinishedLoadingImporters) { + for (uint32_t FUID : HFI.ImporterUIDs) { +// TODO: find the FileEntry based on UID?? + } + HFI.FinishedLoadingImporters = true; +} + } +} + // Wire up the DeclContexts for Decls that we delayed setting until // recursive loading is completed. while (!PendingDeclContextInfos.empty()) { Index: clang/lib/Lex/HeaderSearch.cpp === --- clang/lib/Lex/HeaderSearch.cpp +++ clang/lib/Lex/HeaderSearch.cpp @@ -1253,60 +1253,22 @@ // Get information about this file. HeaderFileInfo = 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 -
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 252110. oontvoo added a comment. Updated the reader to read the UIDs first, then we'll build up the Importers list at the end. 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/lib/Lex/HeaderSearch.cpp clang/lib/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp Index: clang/lib/Serialization/ASTWriter.cpp === --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -1676,6 +1676,14 @@ } LE.write(Offset); + // Writes the number of importers. + LE.write(Data.HFI.Importers.size()); + if (!Data.HFI.Importers.empty()){ +for (const FileEntry* F : Data.HFI.Importers) { + LE.write(F->getUID()); +} + } + 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 @@ -1898,6 +1898,21 @@ HFI.Framework = HS->getUniqueFrameworkName(FrameworkName); } + { +const uint32_t ImportersCount = endian::readNext(d)); +if (ImportersCount > 0) { + + // TODO: I don't think this is right because these importers + // are NOT guaranteed to be read/loaded before this header??? + // + // Read the file UIDs and temporarily save it because we don't have + // the FileEntry for these yet. + for (int i = 0; i < ImportersCount; ++i) { +HFI.ImportersUIDs.push_back(endian::readNext(d)); + } +} + } + assert((End - d) % 4 == 0 && "Wrong data length in HeaderFileInfo deserialization"); while (d != End) { Index: clang/lib/Lex/HeaderSearch.cpp === --- clang/lib/Lex/HeaderSearch.cpp +++ clang/lib/Lex/HeaderSearch.cpp @@ -1253,60 +1253,22 @@ // Get information about this file. HeaderFileInfo = 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; - }; - // 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()) - 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()) - return false; + if (FileInfo.isPragmaOnce || FileInfo.isImport) { +if (PP.isIncludeVisible(File))return false; +else { + // Mark as 'included'. + PP.setIncludeVisible(File); + + // Also record the importer. +
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 251804. oontvoo added a comment. Removed accidentally committed file. 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/lib/Lex/HeaderSearch.cpp clang/lib/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp Index: clang/lib/Serialization/ASTWriter.cpp === --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -1676,6 +1676,14 @@ } LE.write(Offset); + // Writes the number of importers. + LE.write(Data.HFI.Importers.size()); + if (!Data.HFI.Importers.empty()){ +for (const FileEntry* F : Data.HFI.Importers) { + LE.write(F->getUID()); +} + } + 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 @@ -1898,6 +1898,12 @@ HFI.Framework = HS->getUniqueFrameworkName(FrameworkName); } + { +uint32_t ImportersCount = endian::readNext(uint32_t, little>(d)); +if (ImportersCount > 0) { + // TODO: read the fileIDs and find the FileEntry* ??? +} + } assert((End - d) % 4 == 0 && "Wrong data length in HeaderFileInfo deserialization"); while (d != End) { Index: clang/lib/Lex/HeaderSearch.cpp === --- clang/lib/Lex/HeaderSearch.cpp +++ clang/lib/Lex/HeaderSearch.cpp @@ -1253,60 +1253,22 @@ // Get information about this file. HeaderFileInfo = 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; - }; - // 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()) - 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()) - return false; + if (FileInfo.isPragmaOnce || FileInfo.isImport) { +if (PP.isIncludeVisible(File))return false; +else { + // Mark as 'included'. + PP.setIncludeVisible(File); + + // Also record the importer. + FileInfo.Importers.push_back(PP.getCurrentFileLexer()->getFileEntry()); +} } // Next, check to see if the file is wrapped with #ifndef guards. If so, and Index: clang/include/clang/Lex/Preprocessor.h === --- clang/include/clang/Lex/Preprocessor.h +++ clang/include/clang/Lex/Preprocessor.h @@ -51,6 +51,7 @@ #include #include
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 251801. oontvoo marked an inline comment as done. oontvoo added a comment. Additional change: Also keep "Importers" and de/serialise these. 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/#Preprocessor.h# clang/include/clang/Lex/HeaderSearch.h clang/include/clang/Lex/Preprocessor.h clang/lib/Lex/HeaderSearch.cpp clang/lib/Serialization/ASTReader.cpp clang/lib/Serialization/ASTWriter.cpp Index: clang/lib/Serialization/ASTWriter.cpp === --- clang/lib/Serialization/ASTWriter.cpp +++ clang/lib/Serialization/ASTWriter.cpp @@ -1676,6 +1676,14 @@ } LE.write(Offset); + // Writes the number of importers. + LE.write(Data.HFI.Importers.size()); + if (!Data.HFI.Importers.empty()){ +for (const FileEntry* F : Data.HFI.Importers) { + LE.write(F->getUID()); +} + } + 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 @@ -1898,6 +1898,12 @@ HFI.Framework = HS->getUniqueFrameworkName(FrameworkName); } + { +uint32_t ImportersCount = endian::readNext(uint32_t, little>(d)); +if (ImportersCount > 0) { + // TODO: read the fileIDs and find the FileEntry* ??? +} + } assert((End - d) % 4 == 0 && "Wrong data length in HeaderFileInfo deserialization"); while (d != End) { Index: clang/lib/Lex/HeaderSearch.cpp === --- clang/lib/Lex/HeaderSearch.cpp +++ clang/lib/Lex/HeaderSearch.cpp @@ -1253,60 +1253,22 @@ // Get information about this file. HeaderFileInfo = 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; - }; - // 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()) - 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()) - return false; + if (FileInfo.isPragmaOnce || FileInfo.isImport) { +if (PP.isIncludeVisible(File))return false; +else { + // Mark as 'included'. + PP.setIncludeVisible(File); + + // Also record the importer. + FileInfo.Importers.push_back(PP.getCurrentFileLexer()->getFileEntry()); +} } // Next, check to see if the file is wrapped with #ifndef guards. If so, and Index: clang/include/clang/Lex/HeaderSearch.h === ---
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo marked an inline comment as done and an inline comment as not done. oontvoo added inline comments. Comment at: clang/lib/Lex/HeaderSearch.cpp:1266 + if (PP.isIncludeVisibleInLocalModule(File, M)) return false; + else PP.setIncludeVisibleForHeader(File, M); +} else { oontvoo wrote: > jyknight wrote: > > I wonder if this should be just using the CurSubmoduleState. Actually, is > > "M" even needed in this function at all -- why isn't everything just using > > CurSubmoduleState? (It's very likely I'm just confused about what the > > semantics of this are...). > > "Is M needed ... ?" > > Yes - I think so because if we're looking at Module header, then I *think* > the header's content will/should be visible to the submods in it. > > On the other hand (ie., the else branch), if we're looking a "regular" > header, then it should not be visible to the submods [not done - re-opening for question] Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D75951/new/ https://reviews.llvm.org/D75951 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo marked an inline comment as done. oontvoo added inline comments. Comment at: clang/lib/Lex/HeaderSearch.cpp:1266 + if (PP.isIncludeVisibleInLocalModule(File, M)) return false; + else PP.setIncludeVisibleForHeader(File, M); +} else { jyknight wrote: > I wonder if this should be just using the CurSubmoduleState. Actually, is "M" > even needed in this function at all -- why isn't everything just using > CurSubmoduleState? (It's very likely I'm just confused about what the > semantics of this are...). > "Is M needed ... ?" Yes - I think so because if we're looking at Module header, then I *think* the header's content will/should be visible to the submods in it. On the other hand (ie., the else branch), if we're looking a "regular" header, then it should not be visible to the submods Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D75951/new/ https://reviews.llvm.org/D75951 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
jyknight added a comment. I suspect we also need to support saving/loading some of this information in the serialized AST, e.g. clang/lib/Serialization/ASTWriter.cpp has code to save the HeaderInfo data, around line 1650. And around line 2174, code to save the macros per submodule. We'll also need to save the pragma-once-header-state per-submodule too, I think. Comment at: clang/lib/Lex/HeaderSearch.cpp:1264 + if (FileInfo.isPragmaOnce || FileInfo.isImport){ +if (FileInfo.isModuleHeader && M != nullptr){ + if (PP.isIncludeVisibleInLocalModule(File, M)) return false; I don't think whether the header you're trying to include is modular or not (isModuleHeader) should matter here, just whether we have a current module M or not. Comment at: clang/lib/Lex/HeaderSearch.cpp:1266 + if (PP.isIncludeVisibleInLocalModule(File, M)) return false; + else PP.setIncludeVisibleForHeader(File, M); +} else { I wonder if this should be just using the CurSubmoduleState. Actually, is "M" even needed in this function at all -- why isn't everything just using CurSubmoduleState? (It's very likely I'm just confused about what the semantics of this are...). Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D75951/new/ https://reviews.llvm.org/D75951 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 249717. oontvoo added a comment. Wrong name 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/Preprocessor.h clang/lib/Lex/HeaderSearch.cpp Index: clang/lib/Lex/HeaderSearch.cpp === --- clang/lib/Lex/HeaderSearch.cpp +++ clang/lib/Lex/HeaderSearch.cpp @@ -1253,60 +1253,21 @@ // Get information about this file. HeaderFileInfo = 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; - }; - // 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()) - 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()) - return false; + if (FileInfo.isPragmaOnce || FileInfo.isImport){ +if (FileInfo.isModuleHeader && M != nullptr){ + if (PP.isIncludeVisibleInLocalModule(File, M)) return false; + else PP.setIncludeVisibleForModule(File, M); +} else { + if(PP.isIncludeVisible(File)) return false; + else PP.setIncludeVisible(File); +} } // Next, check to see if the file is wrapped with #ifndef guards. If so, and Index: clang/include/clang/Lex/Preprocessor.h === --- clang/include/clang/Lex/Preprocessor.h +++ clang/include/clang/Lex/Preprocessor.h @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -743,6 +744,9 @@ /// The set of modules that are visible within the submodule. VisibleModuleSet VisibleModules; +/// The included header for the submodule. +std::set IncludedFiles; + // FIXME: CounterValue? // FIXME: PragmaPushMacroInfo? }; @@ -1038,6 +1042,32 @@ OnToken = std::move(F); } + void setIncludeVisible(const FileEntry *File) { +CurSubmoduleState->IncludedFiles.insert(File); + } + + bool isIncludeVisible(const FileEntry *File) { +return CurSubmoduleState->IncludedFiles.find(File) +!= CurSubmoduleState->IncludedFiles.end(); + } + + void setIncludeVisibleForModule(const FileEntry *File, Module *M) { +auto SubmoduleIter = Submodules.find(M); +// Can't find the module. Maybe something is wrong. +if (SubmoduleIter == Submodules.end()) return; + +SubmoduleIter->second.IncludedFiles.insert(File); + } + + bool isIncludeVisibleInLocalModule(const FileEntry *File, Module *M) { +auto SubmoduleIter = Submodules.find(M); +if (SubmoduleIter == Submodules.end()) return false; + +return SubmoduleIter->second.IncludedFiles.find(File) +!= SubmoduleIter->second.IncludedFiles.end(); + } + + bool isMacroDefined(StringRef Id) { return isMacroDefined((Id)); } ___ cfe-commits mailing list
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 249712. oontvoo added a comment. update 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/Preprocessor.h clang/lib/Lex/HeaderSearch.cpp Index: clang/lib/Lex/HeaderSearch.cpp === --- clang/lib/Lex/HeaderSearch.cpp +++ clang/lib/Lex/HeaderSearch.cpp @@ -1253,60 +1253,21 @@ // Get information about this file. HeaderFileInfo = 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; - }; - // 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()) - 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()) - return false; + if (FileInfo.isPragmaOnce || FileInfo.isImport){ +if (FileInfo.isModuleHeader && M != nullptr){ + if (PP.isIncludeVisibleInLocalModule(File, M)) return false; + else PP.setIncludeVisibleForHeader(File, M); +} else { + if(PP.isIncludeVisible(File)) return false; + else PP.setIncludeVisible(File); +} } // Next, check to see if the file is wrapped with #ifndef guards. If so, and Index: clang/include/clang/Lex/Preprocessor.h === --- clang/include/clang/Lex/Preprocessor.h +++ clang/include/clang/Lex/Preprocessor.h @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -743,6 +744,9 @@ /// The set of modules that are visible within the submodule. VisibleModuleSet VisibleModules; +/// The included header for the submodule. +std::set IncludedFiles; + // FIXME: CounterValue? // FIXME: PragmaPushMacroInfo? }; @@ -1038,6 +1042,32 @@ OnToken = std::move(F); } + void setIncludeVisible(const FileEntry *File) { +CurSubmoduleState->IncludedFiles.insert(File); + } + + bool isIncludeVisible(const FileEntry *File) { +return CurSubmoduleState->IncludedFiles.find(File) +!= CurSubmoduleState->IncludedFiles.end(); + } + + void setIncludeVisibleForModule(const FileEntry *File, Module *M) { +auto SubmoduleIter = Submodules.find(M); +// Can't find the module. Maybe something is wrong. +if (SubmoduleIter == Submodules.end()) return; + +SubmoduleIter->second.IncludedFiles.insert(File); + } + + bool isIncludeVisibleInLocalModule(const FileEntry *File, Module *M) { +auto SubmoduleIter = Submodules.find(M); +if (SubmoduleIter == Submodules.end()) return false; + +return SubmoduleIter->second.IncludedFiles.find(File) +!= SubmoduleIter->second.IncludedFiles.end(); + } + + bool isMacroDefined(StringRef Id) { return isMacroDefined((Id)); } ___ cfe-commits mailing list
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 249711. oontvoo added a comment. More typo correction 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/Preprocessor.h clang/lib/Lex/HeaderSearch.cpp Index: clang/lib/Lex/HeaderSearch.cpp === --- clang/lib/Lex/HeaderSearch.cpp +++ clang/lib/Lex/HeaderSearch.cpp @@ -1253,60 +1253,21 @@ // Get information about this file. HeaderFileInfo = 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; - }; - // 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()) - 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()) - return false; + if (FileInfo.isPragmaOnce || FileInfo.isImport){ +if (FileInfo.isModuleHeader && M != nullptr){ + if (PP.isIncludeVisibleInLocalModule(File, M)) return false; + else PP.setIncludeVisibleForHeader(File, M); +} else { + if(PP.isIncludeVisible(File)) return false; + else PP.setIncludeVisible(File); +} } // Next, check to see if the file is wrapped with #ifndef guards. If so, and Index: clang/include/clang/Lex/Preprocessor.h === --- clang/include/clang/Lex/Preprocessor.h +++ clang/include/clang/Lex/Preprocessor.h @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -743,6 +744,9 @@ /// The set of modules that are visible within the submodule. VisibleModuleSet VisibleModules; +/// The included header for the submodule. +std::set IncludedFiles; + // FIXME: CounterValue? // FIXME: PragmaPushMacroInfo? }; @@ -1038,6 +1042,32 @@ OnToken = std::move(F); } + void setIncludeVisible(const FileEntry *File) { +CurSubmoduleState.IncludedFiles.insert(File); + } + + bool isIncludeVisible(const FileEntry *File) { +return CurSubmoduleState->IncludedFiles.find(File) +!= CurSubmoduleState->IncludedFiles.end(); + } + + void setIncludeVisibleForModule(const FileEntry *File, Module *M) { +auto SubmoduleIter = Submodules.find(M); +// Can't find the module. Maybe something is wrong. +if (SubmoduleIter == Submodules.end()) return; + +SubmoduleIter->second.IncludedFiles.insert(File); + } + + bool isIncludeVisibleInLocalModule(const FileEntry *File, Module *M) { +auto SubmoduleIter = Submodules.find(M); +if (SubmoduleIter == Submodules.end()) return false; + +return SubmoduleIter->second.IncludedFiles.find(File) +!= SubmoduleIter->second.IncludedFiles.end(); + } + + bool isMacroDefined(StringRef Id) { return isMacroDefined((Id)); } ___ cfe-commits
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 249708. oontvoo added a comment. Updated typo 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/Preprocessor.h clang/lib/Lex/HeaderSearch.cpp Index: clang/lib/Lex/HeaderSearch.cpp === --- clang/lib/Lex/HeaderSearch.cpp +++ clang/lib/Lex/HeaderSearch.cpp @@ -1253,60 +1253,21 @@ // Get information about this file. HeaderFileInfo = 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; - }; - // 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()) - 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()) - return false; + if (FileInfo.isPragmaOnce || FileInfo.isImport){ +if (FileInfo.isModuleHeader && M != nullptr){ + if (PP.isIncludeVisibleInLocalModule(File, M)) return false; + else PP.setIncludeVisibleForHeader(File, M); +} else { + if(PP.isIncludeVisible(File)) return false; + else PP.setIncludeVisible(File); +} } // Next, check to see if the file is wrapped with #ifndef guards. If so, and Index: clang/include/clang/Lex/Preprocessor.h === --- clang/include/clang/Lex/Preprocessor.h +++ clang/include/clang/Lex/Preprocessor.h @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -743,6 +744,9 @@ /// The set of modules that are visible within the submodule. VisibleModuleSet VisibleModules; +/// The included header for the submodule. +std::set IncludedFiles; + // FIXME: CounterValue? // FIXME: PragmaPushMacroInfo? }; @@ -1038,6 +1042,32 @@ OnToken = std::move(F); } + void setIncludeVisible(const FileEntry *File) { +CurSubmoduleState.IncludedFiles.insert(File); + } + + bool isIncludeVisible(const FileEntry *File) { +return CurSubmoduleState.IncludedFiles.find(File) +!= CurSubmoduleState.IncludedFiles.end(); + } + + void setIncludeVisibleForModule(const FileEntry *File, Module *M) { +auto SubmoduleIter = Submodules.find(M); +// Can't find the module. Maybe something is wrong. +if (SubmoduleIter == Submodules.end()) return; + +SubmoduleIter->second.IncludedFiles.insert(File); + } + + bool isIncludeVisibleInLocalModule(const FileEntry *File, Module *M) { +auto SubmoduleIter = Submodules.find(M); +if (SubmoduleIter == Submodules.end()) return false; + +return SubmoduleIter->second.IncludedFiles.find(File) +!= SubmoduleIter->second.IncludedFiles.end(); + } + + bool isMacroDefined(StringRef Id) { return isMacroDefined((Id)); } ___ cfe-commits mailing list
[PATCH] D75951: Keep a list of already-included pragma-once files for mods.
oontvoo updated this revision to Diff 249690. oontvoo retitled this revision from "draft " to "draft". oontvoo added a comment. Updated 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/Preprocessor.h clang/lib/Lex/HeaderSearch.cpp Index: clang/lib/Lex/HeaderSearch.cpp === --- clang/lib/Lex/HeaderSearch.cpp +++ clang/lib/Lex/HeaderSearch.cpp @@ -1253,60 +1253,21 @@ // Get information about this file. HeaderFileInfo = 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; - }; - // 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()) - 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()) - return false; + if (FileInfo.isPragmaOnce || FileInfo.isImport){ +if (FileInfo.isModuleHeader && M != nullptr){ + if (PP.isIncludeVisibleInLocalModule(File, M)) return false; + else PP.setIncludeVisibleForHeader(File, M); +} else { + if(PP.isIncludeVisible(File)) return false; + else PP.setIncludeVisible(File); +} } // Next, check to see if the file is wrapped with #ifndef guards. If so, and Index: clang/include/clang/Lex/Preprocessor.h === --- clang/include/clang/Lex/Preprocessor.h +++ clang/include/clang/Lex/Preprocessor.h @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -743,6 +744,9 @@ /// The set of modules that are visible within the submodule. VisibleModuleSet VisibleModules; +/// The included header for the submodule. +std::set IncludedFiles; + // FIXME: CounterValue? // FIXME: PragmaPushMacroInfo? }; @@ -1038,6 +1042,32 @@ OnToken = std::move(F); } + void setIncludeVisible(const FileEntry *File) { +CurSubmoduleState.IncludedFiles.insert(File); + } + + bool isIncludeVisible(const FileEntry *File) { +return CurSubmoduleState.IncludedFiles.find(File) +!= CurSubmoduleState.IncludedFiles.end(); + } + + void setIncludeVisibleForModule(const FileEntry *File, Module *M) { +auto SubmoduleIter = Submodules.Find(M); +// Can't find the module. Maybe something is wrong. +if (SubmoduleIter == Submodules.end()) return; + +SubmoduleIter->second.IncludedFiles.insert(File); + } + + bool isIncludeVisibleInLocalModule(const FileEntry *File, Module *M) { +auto SubmoduleIter = Submodules.Find(M); +if (SubmoduleIter == Submodules.end()) return false; + +return SubmoduleIter->second.IncludedFiles.find(File) +!= SubmoduleIter->second.IncludedFiles.end(); + } + + bool isMacroDefined(StringRef Id) { return isMacroDefined((Id)); }