1818namespace mrdocs {
1919
2020Optional<std::string>
21- getCompilerVerboseOutput (llvm::StringRef compilerPath)
21+ getCompilerVerboseOutput (llvm::StringRef compilerPath)
2222{
2323 if ( ! llvm::sys::fs::exists (compilerPath))
2424 {
2525 return std::nullopt ;
2626 }
2727
2828 llvm::SmallString<128 > outputPath;
29- if (auto ec = llvm::sys::fs::createTemporaryFile (" compiler-info" , " txt" , outputPath))
29+ if (auto ec = llvm::sys::fs::createTemporaryFile (" compiler-info" , " txt" , outputPath))
3030 {
3131 return std::nullopt ;
3232 }
@@ -35,7 +35,7 @@ getCompilerVerboseOutput(llvm::StringRef compilerPath)
3535 std::vector<llvm::StringRef> const args = {compilerPath, " -v" , " -E" , " -x" , " c++" , " -" };
3636 llvm::ArrayRef<llvm::StringRef> emptyEnv;
3737 int const result = ExecuteAndWaitWithLogging (compilerPath, args, emptyEnv, redirects);
38- if (result != 0 )
38+ if (result != 0 )
3939 {
4040 llvm::sys::fs::remove (outputPath);
4141 return std::nullopt ;
@@ -51,26 +51,26 @@ getCompilerVerboseOutput(llvm::StringRef compilerPath)
5151 return bufferOrError.get ()->getBuffer ().str ();
5252}
5353
54- std::vector<std::string>
55- parseIncludePaths (std::string const & compilerOutput)
54+ std::vector<std::string>
55+ parseIncludePaths (std::string const & compilerOutput)
5656{
5757 std::vector<std::string> includePaths;
5858 std::istringstream stream (compilerOutput);
5959 std::string line;
6060 bool capture = false ;
6161
62- while (std::getline (stream, line))
62+ while (std::getline (stream, line))
6363 {
64- if (line.find (" #include <...> search starts here:" ) != std::string::npos)
64+ if (line.find (" #include <...> search starts here:" ) != std::string::npos)
6565 {
6666 capture = true ;
6767 continue ;
6868 }
69- if (line.find (" End of search list." ) != std::string::npos)
69+ if (line.find (" End of search list." ) != std::string::npos)
7070 {
7171 break ;
7272 }
73- if (capture)
73+ if (capture)
7474 {
7575 line.erase (0 , line.find_first_not_of (" " ));
7676 includePaths.push_back (line);
@@ -80,8 +80,30 @@ parseIncludePaths(std::string const& compilerOutput)
8080 return includePaths;
8181}
8282
83- std::unordered_map<std::string, std::vector<std::string>>
84- getCompilersDefaultIncludeDir (clang::tooling::CompilationDatabase const & compDb, bool useSystemStdlib)
83+ namespace {
84+
85+ // Try to get include paths from a compiler found by name in PATH.
86+ // Returns the include paths if successful, empty vector otherwise.
87+ std::vector<std::string>
88+ tryCompilerByName (llvm::StringRef name)
89+ {
90+ auto found = llvm::sys::findProgramByName (name);
91+ if (!found)
92+ {
93+ return {};
94+ }
95+ auto output = getCompilerVerboseOutput (*found);
96+ if (!output)
97+ {
98+ return {};
99+ }
100+ return parseIncludePaths (*output);
101+ }
102+
103+ } // anonymous namespace
104+
105+ std::unordered_map<std::string, std::vector<std::string>>
106+ getCompilersDefaultIncludeDir (clang::tooling::CompilationDatabase const & compDb, bool useSystemStdlib)
85107{
86108 if (!useSystemStdlib)
87109 {
@@ -100,14 +122,30 @@ getCompilersDefaultIncludeDir(clang::tooling::CompilationDatabase const& compDb,
100122 continue ;
101123 }
102124
103- std::vector<std::string> includePaths;
104- auto const compilerOutput = getCompilerVerboseOutput (compilerPath);
105- if (! compilerOutput)
125+ // Try the compiler specified in the compilation database
126+ auto compilerOutput = getCompilerVerboseOutput (compilerPath);
127+ if (compilerOutput)
106128 {
107- res.emplace (compilerPath, includePaths);
129+ auto includePaths = parseIncludePaths (*compilerOutput);
130+ res.emplace (compilerPath, std::move (includePaths));
108131 continue ;
109132 }
110- includePaths = parseIncludePaths (*compilerOutput);
133+
134+ // The compiler from the database wasn't found.
135+ // Try common fallback compilers to discover system
136+ // include paths.
137+ static constexpr std::string_view fallbackCompilers[] = {
138+ " g++" , " gcc" , " clang++" , " clang" , " c++"
139+ };
140+ std::vector<std::string> includePaths;
141+ for (auto const & fallback : fallbackCompilers)
142+ {
143+ includePaths = tryCompilerByName (fallback);
144+ if (!includePaths.empty ())
145+ {
146+ break ;
147+ }
148+ }
111149 res.emplace (compilerPath, std::move (includePaths));
112150 }
113151 }
@@ -116,4 +154,3 @@ getCompilersDefaultIncludeDir(clang::tooling::CompilationDatabase const& compDb,
116154}
117155
118156} // mrdocs
119-
0 commit comments