5555#include " clang/Basic/DiagnosticOptions.h"
5656#include " clang/Basic/FileEntry.h"
5757#include " clang/Basic/IdentifierTable.h"
58+ #include " clang/Basic/LangStandard.h"
5859#include " clang/Basic/Module.h"
5960#include " clang/Basic/TargetInfo.h"
6061#include " clang/Basic/Version.h"
6162#include " clang/CAS/CASOptions.h"
63+ #include " clang/CAS/IncludeTree.h"
6264#include " clang/CodeGen/ObjectFilePCHContainerOperations.h"
6365#include " clang/Frontend/CompilerInvocation.h"
6466#include " clang/Frontend/FrontendActions.h"
67+ #include " clang/Frontend/IncludeTreePPActions.h"
6568#include " clang/Frontend/TextDiagnosticPrinter.h"
6669#include " clang/Frontend/Utils.h"
6770#include " clang/Index/IndexingAction.h"
8083#include " llvm/ADT/STLExtras.h"
8184#include " llvm/ADT/SmallVector.h"
8285#include " llvm/ADT/StringExtras.h"
86+ #include " llvm/CAS/CASReference.h"
87+ #include " llvm/CAS/ObjectStore.h"
8388#include " llvm/Support/CrashRecoveryContext.h"
89+ #include " llvm/Support/Error.h"
90+ #include " llvm/Support/ErrorHandling.h"
8491#include " llvm/Support/FileCollector.h"
8592#include " llvm/Support/FileSystem.h"
8693#include " llvm/Support/Memory.h"
@@ -1720,8 +1727,13 @@ bool ClangImporter::importHeader(StringRef header, ModuleDecl *adapter,
17201727 StringRef cachedContents, SourceLoc diagLoc) {
17211728 clang::FileManager &fileManager = Impl.Instance ->getFileManager ();
17221729 auto headerFile = fileManager.getFile (header, /* OpenFile=*/ true );
1730+ // Prefer importing the header directly if the header content matches by
1731+ // checking size and mod time. This allows correct import if some no-modular
1732+ // headers are already imported into clang importer. If mod time is zero, then
1733+ // the module should be built from CAS and there is no mod time to verify.
17231734 if (headerFile && (*headerFile)->getSize () == expectedSize &&
1724- (*headerFile)->getModificationTime () == expectedModTime) {
1735+ (expectedModTime == 0 ||
1736+ (*headerFile)->getModificationTime () == expectedModTime)) {
17251737 return importBridgingHeader (header, adapter, diagLoc, false , true );
17261738 }
17271739
@@ -1776,16 +1788,46 @@ bool ClangImporter::importBridgingHeader(StringRef header, ModuleDecl *adapter,
17761788 std::move (sourceBuffer), implicitImport);
17771789}
17781790
1779- std::string ClangImporter::getBridgingHeaderContents (StringRef headerPath,
1780- off_t &fileSize,
1781- time_t &fileModTime) {
1791+ static llvm::Expected<llvm::cas::ObjectRef>
1792+ setupIncludeTreeInput (clang::CompilerInvocation &invocation,
1793+ StringRef headerPath, StringRef pchIncludeTree) {
1794+ auto DB = invocation.getCASOpts ().getOrCreateDatabases ();
1795+ if (!DB)
1796+ return DB.takeError ();
1797+ auto CAS = DB->first ;
1798+ auto ID = CAS->parseID (pchIncludeTree);
1799+ if (!ID)
1800+ return ID.takeError ();
1801+ auto includeTreeRef = CAS->getReference (*ID);
1802+ if (!includeTreeRef)
1803+ return llvm::cas::ObjectStore::createUnknownObjectError (*ID);
1804+
1805+ invocation.getFrontendOpts ().Inputs .push_back (clang::FrontendInputFile (
1806+ *includeTreeRef, headerPath, clang::Language::ObjC));
1807+
1808+ return *includeTreeRef;
1809+ }
1810+
1811+ std::string ClangImporter::getBridgingHeaderContents (
1812+ StringRef headerPath, off_t &fileSize, time_t &fileModTime,
1813+ StringRef pchIncludeTree) {
17821814 auto invocation =
17831815 std::make_shared<clang::CompilerInvocation>(*Impl.Invocation );
17841816
17851817 invocation->getFrontendOpts ().DisableFree = false ;
17861818 invocation->getFrontendOpts ().Inputs .clear ();
1787- invocation->getFrontendOpts ().Inputs .push_back (
1788- clang::FrontendInputFile (headerPath, clang::Language::ObjC));
1819+
1820+ std::optional<llvm::cas::ObjectRef> includeTreeRef;
1821+ if (pchIncludeTree.empty ())
1822+ invocation->getFrontendOpts ().Inputs .push_back (
1823+ clang::FrontendInputFile (headerPath, clang::Language::ObjC));
1824+ else if (auto err =
1825+ setupIncludeTreeInput (*invocation, headerPath, pchIncludeTree)
1826+ .moveInto (includeTreeRef)) {
1827+ Impl.diagnose ({}, diag::err_rewrite_bridging_header,
1828+ toString (std::move (err)));
1829+ return " " ;
1830+ }
17891831
17901832 invocation->getPreprocessorOpts ().resetNonModularOptions ();
17911833
@@ -1806,18 +1848,36 @@ std::string ClangImporter::getBridgingHeaderContents(StringRef headerPath,
18061848 // write to an in-memory buffer.
18071849 class RewriteIncludesAction : public clang ::PreprocessorFrontendAction {
18081850 raw_ostream &OS;
1851+ std::optional<llvm::cas::ObjectRef> includeTreeRef;
18091852
18101853 void ExecuteAction () override {
18111854 clang::CompilerInstance &compiler = getCompilerInstance ();
1855+ // If the input is include tree, setup the IncludeTreePPAction.
1856+ if (includeTreeRef) {
1857+ auto IncludeTreeRoot = clang::cas::IncludeTreeRoot::get (
1858+ compiler.getOrCreateObjectStore (), *includeTreeRef);
1859+ if (!IncludeTreeRoot)
1860+ llvm::report_fatal_error (IncludeTreeRoot.takeError ());
1861+ auto PPCachedAct =
1862+ clang::createPPActionsFromIncludeTree (*IncludeTreeRoot);
1863+ if (!PPCachedAct)
1864+ llvm::report_fatal_error (PPCachedAct.takeError ());
1865+ compiler.getPreprocessor ().setPPCachedActions (
1866+ std::move (*PPCachedAct));
1867+ }
1868+
18121869 clang::RewriteIncludesInInput (compiler.getPreprocessor (), &OS,
18131870 compiler.getPreprocessorOutputOpts ());
18141871 }
1872+
18151873 public:
1816- explicit RewriteIncludesAction (raw_ostream &os) : OS(os) {}
1874+ explicit RewriteIncludesAction (
1875+ raw_ostream &os, std::optional<llvm::cas::ObjectRef> includeTree)
1876+ : OS(os), includeTreeRef(includeTree) {}
18171877 };
18181878
18191879 llvm::raw_string_ostream os (result);
1820- RewriteIncludesAction action (os);
1880+ RewriteIncludesAction action (os, includeTreeRef );
18211881 rewriteInstance.ExecuteAction (action);
18221882 });
18231883
@@ -2553,6 +2613,7 @@ ClangImporter::Implementation::Implementation(
25532613 !ctx.ClangImporterOpts.BridgingHeader.empty()),
25542614 DisableOverlayModules(ctx.ClangImporterOpts.DisableOverlayModules),
25552615 EnableClangSPI(ctx.ClangImporterOpts.EnableClangSPI),
2616+ UseClangIncludeTree(ctx.ClangImporterOpts.UseClangIncludeTree),
25562617 importSymbolicCXXDecls(
25572618 ctx.LangOpts.hasFeature(Feature::ImportSymbolicCXXDecls)),
25582619 IsReadingBridgingPCH(false ),
0 commit comments