28
28
#include " clang/Tooling/DependencyScanning/ModuleDepCollector.h"
29
29
#include " clang/Tooling/DependencyScanning/ScanAndUpdateArgs.h"
30
30
#include " clang/Tooling/Tooling.h"
31
+ #include " llvm/ADT/IntrusiveRefCntPtr.h"
31
32
#include " llvm/ADT/ScopeExit.h"
32
33
#include " llvm/CAS/CASProvidingFileSystem.h"
33
34
#include " llvm/CAS/CachingOnDiskFileSystem.h"
34
35
#include " llvm/CAS/ObjectStore.h"
35
36
#include " llvm/Support/Allocator.h"
36
37
#include " llvm/Support/Error.h"
38
+ #include " llvm/Support/MemoryBuffer.h"
37
39
#include " llvm/Support/PrefixMapper.h"
38
40
#include " llvm/TargetParser/Host.h"
39
41
#include < optional>
@@ -744,20 +746,43 @@ DependencyScanningWorker::getOrCreateFileManager() const {
744
746
return new FileManager (FileSystemOptions (), BaseFS);
745
747
}
746
748
747
- llvm::Error DependencyScanningWorker::computeDependencies (
748
- StringRef WorkingDirectory, const std::vector<std::string> &CommandLine,
749
- DependencyConsumer &Consumer, DependencyActionController &Controller,
750
- std::optional<StringRef> ModuleName) {
749
+ static std::unique_ptr<DiagnosticOptions>
750
+ createDiagOptions (const std::vector<std::string> &CommandLine) {
751
751
std::vector<const char *> CLI;
752
752
for (const std::string &Arg : CommandLine)
753
753
CLI.push_back (Arg.c_str ());
754
754
auto DiagOpts = CreateAndPopulateDiagOpts (CLI);
755
755
sanitizeDiagOpts (*DiagOpts);
756
+ return DiagOpts;
757
+ }
756
758
759
+ llvm::Error DependencyScanningWorker::computeDependencies (
760
+ StringRef WorkingDirectory, const std::vector<std::string> &CommandLine,
761
+ DependencyConsumer &Consumer, DependencyActionController &Controller,
762
+ std::optional<llvm::MemoryBufferRef> TUBuffer) {
757
763
// Capture the emitted diagnostics and report them to the client
758
764
// in the case of a failure.
759
765
std::string DiagnosticOutput;
760
766
llvm::raw_string_ostream DiagnosticsOS (DiagnosticOutput);
767
+ auto DiagOpts = createDiagOptions (CommandLine);
768
+ TextDiagnosticPrinter DiagPrinter (DiagnosticsOS, DiagOpts.release ());
769
+
770
+ if (computeDependencies (WorkingDirectory, CommandLine, Consumer, Controller,
771
+ DiagPrinter, TUBuffer))
772
+ return llvm::Error::success ();
773
+ return llvm::make_error<llvm::StringError>(DiagnosticsOS.str (),
774
+ llvm::inconvertibleErrorCode ());
775
+ }
776
+
777
+ llvm::Error DependencyScanningWorker::computeDependencies (
778
+ StringRef WorkingDirectory, const std::vector<std::string> &CommandLine,
779
+ DependencyConsumer &Consumer, DependencyActionController &Controller,
780
+ StringRef ModuleName) {
781
+ // Capture the emitted diagnostics and report them to the client
782
+ // in the case of a failure.
783
+ std::string DiagnosticOutput;
784
+ llvm::raw_string_ostream DiagnosticsOS (DiagnosticOutput);
785
+ auto DiagOpts = createDiagOptions (CommandLine);
761
786
TextDiagnosticPrinter DiagPrinter (DiagnosticsOS, DiagOpts.release ());
762
787
763
788
if (computeDependencies (WorkingDirectory, CommandLine, Consumer, Controller,
@@ -828,59 +853,18 @@ static bool createAndRunToolInvocation(
828
853
return true ;
829
854
}
830
855
831
- bool DependencyScanningWorker::computeDependencies (
856
+ bool DependencyScanningWorker::scanDependencies (
832
857
StringRef WorkingDirectory, const std::vector<std::string> &CommandLine,
833
858
DependencyConsumer &Consumer, DependencyActionController &Controller,
834
- DiagnosticConsumer &DC, std::optional<StringRef> ModuleName) {
835
- // Reset what might have been modified in the previous worker invocation.
836
- BaseFS->setCurrentWorkingDirectory (WorkingDirectory);
837
-
838
- std::optional<std::vector<std::string>> ModifiedCommandLine;
839
- llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> ModifiedFS;
840
-
841
- // If we're scanning based on a module name alone, we don't expect the client
842
- // to provide us with an input file. However, the driver really wants to have
843
- // one. Let's just make it up to make the driver happy.
844
- if (ModuleName) {
845
- auto OverlayFS =
846
- llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(BaseFS);
847
- auto InMemoryFS =
848
- llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
849
- InMemoryFS->setCurrentWorkingDirectory (WorkingDirectory);
850
-
851
- SmallString<128 > FakeInputPath;
852
- // TODO: We should retry the creation if the path already exists.
853
- llvm::sys::fs::createUniquePath (*ModuleName + " -%%%%%%%%.input" ,
854
- FakeInputPath,
855
- /* MakeAbsolute=*/ false );
856
- InMemoryFS->addFile (FakeInputPath, 0 , llvm::MemoryBuffer::getMemBuffer (" " ));
857
-
858
- llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> InMemoryOverlay =
859
- InMemoryFS;
860
- // If we are using a CAS but not dependency CASFS, we need to provide the
861
- // fake input file in a CASProvidingFS for include-tree.
862
- if (CAS && !DepCASFS)
863
- InMemoryOverlay =
864
- llvm::cas::createCASProvidingFileSystem (CAS, std::move (InMemoryFS));
865
-
866
- OverlayFS->pushOverlay (InMemoryOverlay);
867
- ModifiedFS = OverlayFS;
868
- ModifiedCommandLine = CommandLine;
869
- ModifiedCommandLine->emplace_back (FakeInputPath);
870
- }
871
-
872
- const std::vector<std::string> &FinalCommandLine =
873
- ModifiedCommandLine ? *ModifiedCommandLine : CommandLine;
874
- auto &FinalFS = ModifiedFS ? ModifiedFS : BaseFS;
875
-
859
+ DiagnosticConsumer &DC, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS,
860
+ std::optional<StringRef> ModuleName) {
876
861
auto FileMgr =
877
- llvm::makeIntrusiveRefCnt<FileManager>(FileSystemOptions{}, FinalFS );
862
+ llvm::makeIntrusiveRefCnt<FileManager>(FileSystemOptions{}, FS );
878
863
879
- std::vector<const char *> FinalCCommandLine (FinalCommandLine .size (), nullptr );
880
- llvm::transform (FinalCommandLine, FinalCCommandLine .begin (),
864
+ std::vector<const char *> CCommandLine (CommandLine .size (), nullptr );
865
+ llvm::transform (CommandLine, CCommandLine .begin (),
881
866
[](const std::string &Str) { return Str.c_str (); });
882
-
883
- auto DiagOpts = CreateAndPopulateDiagOpts (FinalCCommandLine);
867
+ auto DiagOpts = CreateAndPopulateDiagOpts (CCommandLine);
884
868
sanitizeDiagOpts (*DiagOpts);
885
869
IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
886
870
CompilerInstance::createDiagnostics (DiagOpts.release (), &DC,
@@ -902,12 +886,12 @@ bool DependencyScanningWorker::computeDependencies(
902
886
/* DiagGenerationAsCompilation=*/ false , getCASOpts (),
903
887
ModuleName);
904
888
bool Success = false ;
905
- if (FinalCommandLine [1 ] == " -cc1" ) {
906
- Success = createAndRunToolInvocation (FinalCommandLine , Action, *FileMgr,
889
+ if (CommandLine [1 ] == " -cc1" ) {
890
+ Success = createAndRunToolInvocation (CommandLine , Action, *FileMgr,
907
891
PCHContainerOps, *Diags, Consumer);
908
892
} else {
909
893
Success = forEachDriverJob (
910
- FinalCommandLine , *Diags, *FileMgr, [&](const driver::Command &Cmd) {
894
+ CommandLine , *Diags, *FileMgr, [&](const driver::Command &Cmd) {
911
895
if (StringRef (Cmd.getCreator ().getName ()) != " clang" ) {
912
896
// Non-clang command. Just pass through to the dependency
913
897
// consumer.
@@ -935,10 +919,89 @@ bool DependencyScanningWorker::computeDependencies(
935
919
936
920
if (Success && !Action.hasScanned ())
937
921
Diags->Report (diag::err_fe_expected_compiler_job)
938
- << llvm::join (FinalCommandLine , " " );
922
+ << llvm::join (CommandLine , " " );
939
923
return Success && Action.hasScanned ();
940
924
}
941
925
926
+ bool DependencyScanningWorker::computeDependencies (
927
+ StringRef WorkingDirectory, const std::vector<std::string> &CommandLine,
928
+ DependencyConsumer &Consumer, DependencyActionController &Controller,
929
+ DiagnosticConsumer &DC, std::optional<llvm::MemoryBufferRef> TUBuffer) {
930
+ // Reset what might have been modified in the previous worker invocation.
931
+ BaseFS->setCurrentWorkingDirectory (WorkingDirectory);
932
+
933
+ std::optional<std::vector<std::string>> ModifiedCommandLine;
934
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> ModifiedFS;
935
+
936
+ // If we're scanning based on a module name alone, we don't expect the client
937
+ // to provide us with an input file. However, the driver really wants to have
938
+ // one. Let's just make it up to make the driver happy.
939
+ if (TUBuffer) {
940
+ auto OverlayFS =
941
+ llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(BaseFS);
942
+ auto InMemoryFS =
943
+ llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
944
+ InMemoryFS->setCurrentWorkingDirectory (WorkingDirectory);
945
+ auto InputPath = TUBuffer->getBufferIdentifier ();
946
+ InMemoryFS->addFile (
947
+ InputPath, 0 ,
948
+ llvm::MemoryBuffer::getMemBufferCopy (TUBuffer->getBuffer ()));
949
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> InMemoryOverlay =
950
+ InMemoryFS;
951
+ // If we are using a CAS but not dependency CASFS, we need to provide the
952
+ // fake input file in a CASProvidingFS for include-tree.
953
+ if (CAS && !DepCASFS)
954
+ InMemoryOverlay =
955
+ llvm::cas::createCASProvidingFileSystem (CAS, std::move (InMemoryFS));
956
+
957
+ OverlayFS->pushOverlay (InMemoryOverlay);
958
+ ModifiedFS = OverlayFS;
959
+ ModifiedCommandLine = CommandLine;
960
+ ModifiedCommandLine->emplace_back (InputPath);
961
+ }
962
+
963
+ const std::vector<std::string> &FinalCommandLine =
964
+ ModifiedCommandLine ? *ModifiedCommandLine : CommandLine;
965
+ auto &FinalFS = ModifiedFS ? ModifiedFS : BaseFS;
966
+
967
+ return scanDependencies (WorkingDirectory, FinalCommandLine, Consumer,
968
+ Controller, DC, FinalFS, /* ModuleName=*/ std::nullopt);
969
+ }
970
+
971
+ bool DependencyScanningWorker::computeDependencies (
972
+ StringRef WorkingDirectory, const std::vector<std::string> &CommandLine,
973
+ DependencyConsumer &Consumer, DependencyActionController &Controller,
974
+ DiagnosticConsumer &DC, StringRef ModuleName) {
975
+ // Reset what might have been modified in the previous worker invocation.
976
+ BaseFS->setCurrentWorkingDirectory (WorkingDirectory);
977
+
978
+ // If we're scanning based on a module name alone, we don't expect the client
979
+ // to provide us with an input file. However, the driver really wants to have
980
+ // one. Let's just make it up to make the driver happy.
981
+ auto OverlayFS =
982
+ llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(BaseFS);
983
+ auto InMemoryFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
984
+ InMemoryFS->setCurrentWorkingDirectory (WorkingDirectory);
985
+ SmallString<128 > FakeInputPath;
986
+ // TODO: We should retry the creation if the path already exists.
987
+ llvm::sys::fs::createUniquePath (ModuleName + " -%%%%%%%%.input" , FakeInputPath,
988
+ /* MakeAbsolute=*/ false );
989
+ InMemoryFS->addFile (FakeInputPath, 0 , llvm::MemoryBuffer::getMemBuffer (" " ));
990
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> InMemoryOverlay = InMemoryFS;
991
+ // If we are using a CAS but not dependency CASFS, we need to provide the
992
+ // fake input file in a CASProvidingFS for include-tree.
993
+ if (CAS && !DepCASFS)
994
+ InMemoryOverlay =
995
+ llvm::cas::createCASProvidingFileSystem (CAS, std::move (InMemoryFS));
996
+
997
+ OverlayFS->pushOverlay (InMemoryOverlay);
998
+ auto ModifiedCommandLine = CommandLine;
999
+ ModifiedCommandLine.emplace_back (FakeInputPath);
1000
+
1001
+ return scanDependencies (WorkingDirectory, ModifiedCommandLine, Consumer,
1002
+ Controller, DC, OverlayFS, ModuleName);
1003
+ }
1004
+
942
1005
DependencyActionController::~DependencyActionController () {}
943
1006
944
1007
void DependencyScanningWorker::computeDependenciesFromCompilerInvocation (
0 commit comments