52
52
#include " clang/Basic/TargetInfo.h"
53
53
#include " clang/Basic/Version.h"
54
54
#include " clang/CodeGen/ObjectFilePCHContainerOperations.h"
55
+ #include " clang/Driver/Driver.h"
55
56
#include " clang/Frontend/FrontendActions.h"
56
57
#include " clang/Frontend/Utils.h"
57
58
#include " clang/Index/IndexingAction.h"
@@ -875,19 +876,27 @@ getClangInvocationFileMapping(ASTContext &ctx) {
875
876
if (!triple.isOSLinux ())
876
877
return {};
877
878
878
- SearchPathOptions &searchPathOpts = ctx.SearchPathOpts ;
879
-
880
- Path sdkPath (searchPathOpts.getSDKPath ());
881
- if (sdkPath.empty ())
882
- sdkPath = " /" ;
879
+ auto clangDiags = clang::CompilerInstance::createDiagnostics (
880
+ new clang::DiagnosticOptions ());
881
+ clang::driver::Driver clangDriver (ctx.ClangImporterOpts .clangPath ,
882
+ triple.str (), *clangDiags);
883
+ auto cxxStdlibDirs =
884
+ clangDriver.getLibStdCxxIncludePaths (llvm::opt::InputArgList (), triple);
885
+ if (cxxStdlibDirs.empty ()) {
886
+ ctx.Diags .diagnose (SourceLoc (), diag::libstdcxx_not_found, triple.str ());
887
+ return {};
888
+ }
889
+ Path cxxStdlibDir (cxxStdlibDirs.front ());
890
+ // VFS does not allow mapping paths that contain `../` or `./`.
891
+ llvm::sys::path::remove_dots (cxxStdlibDir, /* remove_dot_dot=*/ true );
883
892
884
893
// Currently only a modulemap for libstdc++ is injected.
885
894
if (!ctx.LangOpts .EnableCXXInterop )
886
895
return {};
887
896
888
897
Path actualModuleMapPath;
889
898
Path buffer;
890
- if (auto path = getLibStdCxxModuleMapPath (searchPathOpts , triple, buffer))
899
+ if (auto path = getLibStdCxxModuleMapPath (ctx. SearchPathOpts , triple, buffer))
891
900
actualModuleMapPath = path.getValue ();
892
901
else
893
902
return {};
@@ -905,48 +914,26 @@ getClangInvocationFileMapping(ASTContext &ctx) {
905
914
llvm::sys::path::remove_filename (actualHeaderPath);
906
915
llvm::sys::path::append (actualHeaderPath, " libstdcxx.h" );
907
916
908
- Path cxxStdlibsRoot (sdkPath);
909
- llvm::sys::path::append (cxxStdlibsRoot, " usr" , " include" , " c++" );
910
- if (!llvm::sys::fs::exists (cxxStdlibsRoot))
917
+ // Inject a modulemap into VFS for the libstdc++ directory.
918
+ // Only inject the module map if the module does not already exist at
919
+ // {sysroot}/usr/include/module.{map,modulemap}.
920
+ Path injectedModuleMapLegacyPath (cxxStdlibDir);
921
+ llvm::sys::path::append (injectedModuleMapLegacyPath, " module.map" );
922
+ if (llvm::sys::fs::exists (injectedModuleMapLegacyPath))
911
923
return {};
912
924
913
- // Collect all installed versions of libstdc++. We currently have no way to
914
- // know which libstdc++ version will be used for this Clang invocation.
915
- // TODO: extract this information from the Clang driver.
916
- SmallVector<Path, 1 > cxxStdlibDirs;
917
- std::error_code errorCode;
918
- for (llvm::vfs::directory_iterator
919
- iter = ctx.SourceMgr .getFileSystem ()->dir_begin (cxxStdlibsRoot,
920
- errorCode),
921
- endIter;
922
- !errorCode && iter != endIter; iter = iter.increment (errorCode)) {
923
- cxxStdlibDirs.push_back (Path (iter->path ()));
924
- }
925
-
926
- SmallVector<std::pair<std::string, std::string>, 16 > result;
927
- // Inject a modulemap into the VFS for each of the libstdc++ versions.
928
- for (const Path &cxxStdlibDir : cxxStdlibDirs) {
929
- // Only inject the module map if the module does not already exist at
930
- // {sysroot}/usr/include/module.{map,modulemap}.
931
- Path injectedModuleMapLegacyPath (cxxStdlibDir);
932
- llvm::sys::path::append (injectedModuleMapLegacyPath, " module.map" );
933
- if (llvm::sys::fs::exists (injectedModuleMapLegacyPath))
934
- continue ;
935
-
936
- Path injectedModuleMapPath = cxxStdlibDir;
937
- llvm::sys::path::append (injectedModuleMapPath, " module.modulemap" );
938
- if (llvm::sys::fs::exists (injectedModuleMapPath))
939
- continue ;
925
+ Path injectedModuleMapPath (cxxStdlibDir);
926
+ llvm::sys::path::append (injectedModuleMapPath, " module.modulemap" );
927
+ if (llvm::sys::fs::exists (injectedModuleMapPath))
928
+ return {};
940
929
941
- Path injectedHeaderPath = cxxStdlibDir;
942
- llvm::sys::path::append (injectedHeaderPath, " libstdcxx.h" );
930
+ Path injectedHeaderPath ( cxxStdlibDir) ;
931
+ llvm::sys::path::append (injectedHeaderPath, " libstdcxx.h" );
943
932
944
- result.push_back (
945
- {std::string (injectedModuleMapPath), std::string (actualModuleMapPath)});
946
- result.push_back (
947
- {std::string (injectedHeaderPath), std::string (actualHeaderPath)});
948
- }
949
- return result;
933
+ return {
934
+ {std::string (injectedModuleMapPath), std::string (actualModuleMapPath)},
935
+ {std::string (injectedHeaderPath), std::string (actualHeaderPath)},
936
+ };
950
937
}
951
938
952
939
bool ClangImporter::canReadPCH (StringRef PCHFilename) {
0 commit comments