5252#include " clang/Basic/TargetInfo.h"
5353#include " clang/Basic/Version.h"
5454#include " clang/CodeGen/ObjectFilePCHContainerOperations.h"
55+ #include " clang/Driver/Driver.h"
5556#include " clang/Frontend/FrontendActions.h"
5657#include " clang/Frontend/Utils.h"
5758#include " clang/Index/IndexingAction.h"
@@ -875,19 +876,27 @@ getClangInvocationFileMapping(ASTContext &ctx) {
875876 if (!triple.isOSLinux ())
876877 return {};
877878
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 );
883892
884893 // Currently only a modulemap for libstdc++ is injected.
885894 if (!ctx.LangOpts .EnableCXXInterop )
886895 return {};
887896
888897 Path actualModuleMapPath;
889898 Path buffer;
890- if (auto path = getLibStdCxxModuleMapPath (searchPathOpts , triple, buffer))
899+ if (auto path = getLibStdCxxModuleMapPath (ctx. SearchPathOpts , triple, buffer))
891900 actualModuleMapPath = path.getValue ();
892901 else
893902 return {};
@@ -905,48 +914,26 @@ getClangInvocationFileMapping(ASTContext &ctx) {
905914 llvm::sys::path::remove_filename (actualHeaderPath);
906915 llvm::sys::path::append (actualHeaderPath, " libstdcxx.h" );
907916
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))
911923 return {};
912924
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 {};
940929
941- Path injectedHeaderPath = cxxStdlibDir;
942- llvm::sys::path::append (injectedHeaderPath, " libstdcxx.h" );
930+ Path injectedHeaderPath ( cxxStdlibDir) ;
931+ llvm::sys::path::append (injectedHeaderPath, " libstdcxx.h" );
943932
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+ };
950937}
951938
952939bool ClangImporter::canReadPCH (StringRef PCHFilename) {
0 commit comments