55
55
#include " clang/Basic/DiagnosticOptions.h"
56
56
#include " clang/Basic/FileEntry.h"
57
57
#include " clang/Basic/IdentifierTable.h"
58
+ #include " clang/Basic/LangStandard.h"
58
59
#include " clang/Basic/Module.h"
59
60
#include " clang/Basic/TargetInfo.h"
60
61
#include " clang/Basic/Version.h"
61
62
#include " clang/CAS/CASOptions.h"
63
+ #include " clang/CAS/IncludeTree.h"
62
64
#include " clang/CodeGen/ObjectFilePCHContainerOperations.h"
63
65
#include " clang/Frontend/CompilerInvocation.h"
64
66
#include " clang/Frontend/FrontendActions.h"
67
+ #include " clang/Frontend/IncludeTreePPActions.h"
65
68
#include " clang/Frontend/TextDiagnosticPrinter.h"
66
69
#include " clang/Frontend/Utils.h"
67
70
#include " clang/Index/IndexingAction.h"
80
83
#include " llvm/ADT/STLExtras.h"
81
84
#include " llvm/ADT/SmallVector.h"
82
85
#include " llvm/ADT/StringExtras.h"
86
+ #include " llvm/CAS/CASReference.h"
87
+ #include " llvm/CAS/ObjectStore.h"
83
88
#include " llvm/Support/CrashRecoveryContext.h"
89
+ #include " llvm/Support/Error.h"
90
+ #include " llvm/Support/ErrorHandling.h"
84
91
#include " llvm/Support/FileCollector.h"
85
92
#include " llvm/Support/FileSystem.h"
86
93
#include " llvm/Support/Memory.h"
@@ -1720,8 +1727,13 @@ bool ClangImporter::importHeader(StringRef header, ModuleDecl *adapter,
1720
1727
StringRef cachedContents, SourceLoc diagLoc) {
1721
1728
clang::FileManager &fileManager = Impl.Instance ->getFileManager ();
1722
1729
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.
1723
1734
if (headerFile && (*headerFile)->getSize () == expectedSize &&
1724
- (*headerFile)->getModificationTime () == expectedModTime) {
1735
+ (expectedModTime == 0 ||
1736
+ (*headerFile)->getModificationTime () == expectedModTime)) {
1725
1737
return importBridgingHeader (header, adapter, diagLoc, false , true );
1726
1738
}
1727
1739
@@ -1776,16 +1788,46 @@ bool ClangImporter::importBridgingHeader(StringRef header, ModuleDecl *adapter,
1776
1788
std::move (sourceBuffer), implicitImport);
1777
1789
}
1778
1790
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) {
1782
1814
auto invocation =
1783
1815
std::make_shared<clang::CompilerInvocation>(*Impl.Invocation );
1784
1816
1785
1817
invocation->getFrontendOpts ().DisableFree = false ;
1786
1818
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
+ }
1789
1831
1790
1832
invocation->getPreprocessorOpts ().resetNonModularOptions ();
1791
1833
@@ -1806,18 +1848,36 @@ std::string ClangImporter::getBridgingHeaderContents(StringRef headerPath,
1806
1848
// write to an in-memory buffer.
1807
1849
class RewriteIncludesAction : public clang ::PreprocessorFrontendAction {
1808
1850
raw_ostream &OS;
1851
+ std::optional<llvm::cas::ObjectRef> includeTreeRef;
1809
1852
1810
1853
void ExecuteAction () override {
1811
1854
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
+
1812
1869
clang::RewriteIncludesInInput (compiler.getPreprocessor (), &OS,
1813
1870
compiler.getPreprocessorOutputOpts ());
1814
1871
}
1872
+
1815
1873
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) {}
1817
1877
};
1818
1878
1819
1879
llvm::raw_string_ostream os (result);
1820
- RewriteIncludesAction action (os);
1880
+ RewriteIncludesAction action (os, includeTreeRef );
1821
1881
rewriteInstance.ExecuteAction (action);
1822
1882
});
1823
1883
@@ -2553,6 +2613,7 @@ ClangImporter::Implementation::Implementation(
2553
2613
!ctx.ClangImporterOpts.BridgingHeader.empty()),
2554
2614
DisableOverlayModules(ctx.ClangImporterOpts.DisableOverlayModules),
2555
2615
EnableClangSPI(ctx.ClangImporterOpts.EnableClangSPI),
2616
+ UseClangIncludeTree(ctx.ClangImporterOpts.UseClangIncludeTree),
2556
2617
importSymbolicCXXDecls(
2557
2618
ctx.LangOpts.hasFeature(Feature::ImportSymbolicCXXDecls)),
2558
2619
IsReadingBridgingPCH(false ),
0 commit comments