[PATCH] D75951: Keep a list of already-included pragma-once files for mods.

2020-04-14 Thread Richard Smith - zygoloid via Phabricator via cfe-commits
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.

2020-04-06 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-04-01 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-04-01 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-30 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-28 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-28 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-27 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-27 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-27 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-27 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-27 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-27 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-26 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-26 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-26 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-26 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-25 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-25 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-25 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-25 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-25 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-24 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-24 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-24 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-23 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-23 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-23 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-23 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-23 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-23 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-20 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-20 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-16 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-16 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-12 Thread James Y Knight via Phabricator via cfe-commits
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.

2020-03-11 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-11 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-11 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-11 Thread Vy Nguyen via Phabricator via cfe-commits
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.

2020-03-11 Thread Vy Nguyen via Phabricator via cfe-commits
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));
   }