@@ -1010,97 +1010,77 @@ struct Preprocessor::Private {
10101010 [[nodiscard]] auto checkPragmaOnceProtected (TokList *ts) const -> bool;
10111011
10121012 struct Resolve {
1013- enum struct Mode {
1014- kFirst ,
1015- kAll ,
1016- };
1017-
10181013 const Private *d;
10191014 bool wantNextInlude;
10201015 bool didFindCurrentPath = false ;
10211016 std::optional<fs::path> firstMatch;
1022- Mode mode;
1023- std::vector<std::string> candidates;
1017+ std::array<std::string, 1 > currentPaths;
10241018
10251019 Resolve (const Resolve &other) = delete ;
10261020 auto operator =(const Resolve &other) -> Resolve & = delete ;
10271021
1028- Resolve (const Private *d, bool next, Mode mode = Mode::kFirst )
1029- : d(d), wantNextInlude(next), mode(mode) {}
1030-
1031- [[nodiscard]] auto search (auto view, const std::string &headerName)
1032- -> std::optional<std::string> {
1033- auto transformToIncludePath = std::views::transform (
1034- [&](const fs::path &path) { return path / headerName; });
1035-
1036- auto filterExistingFiles = std::views::filter (
1037- [&](const fs::path &path) { return d->fileExists (path); });
1038-
1039- for (const auto &path : view | transformToIncludePath |
1040- filterExistingFiles | std::views::reverse) {
1041- firstMatch = path;
1042-
1043- if (wantNextInlude && path == d->currentPath_ ) {
1044- didFindCurrentPath = true ;
1045- continue ;
1046- }
1047-
1048- if (wantNextInlude && !didFindCurrentPath) {
1049- continue ;
1050- }
1051-
1052- if (mode == Mode::kFirst ) return path.string ();
1053-
1054- candidates.push_back (path.string ());
1055- }
1022+ Resolve (const Private *d, bool next)
1023+ : d(d), wantNextInlude(next), currentPaths{{d->currentPath_ }} {}
10561024
1057- return std::nullopt ;
1058- }
1025+ using SearchPaths = std::vector<std::span<const std::string>>;
10591026
1060- [[nodiscard]] auto operator ()(const QuoteInclude &include)
1027+ [[nodiscard]] auto operator ()(const Include &include)
10611028 -> std::optional<std::string> {
1062- const auto &headerName = include.fileName ;
1063-
10641029 // search in the current path
1065- if (auto p = search (std::views::single (d->currentPath_ ), headerName);
1066- mode == Mode::kFirst && p) {
1067- return p;
1068- }
1030+ auto header = getHeaderName (include);
10691031
1070- // search in the quote include paths
1071- if (auto p = search (d->quoteIncludePaths_ , headerName);
1072- mode == Mode::kFirst && p) {
1073- return p;
1032+ SearchPaths searchPaths;
1033+
1034+ if (std::holds_alternative<QuoteInclude>(include)) {
1035+ searchPaths = userHeaderSearchPaths ();
1036+ } else {
1037+ searchPaths = systemHeaderSearchPaths ();
10741038 }
10751039
1076- // fallback to system include paths
1077- if (auto p = search (d->systemIncludePaths_ , headerName);
1078- mode == Mode::kFirst && p) {
1040+ if (auto p = search (searchPaths | std::views::join, header)) {
10791041 return p;
10801042 }
10811043
10821044 if (wantNextInlude && !didFindCurrentPath) {
1083- if (mode == Mode::kFirst )
1084- return firstMatch->string ();
1085- else {
1086- candidates.push_back (firstMatch->string ());
1087- }
1045+ return firstMatch;
10881046 }
10891047
10901048 return std::nullopt ;
10911049 }
10921050
1093- [[nodiscard]] auto operator ()(const SystemInclude &include)
1051+ [[nodiscard]] auto userHeaderSearchPaths () -> SearchPaths {
1052+ std::vector<std::span<const std::string>> paths;
1053+ paths.push_back (currentPaths);
1054+ paths.push_back (d->quoteIncludePaths_ );
1055+ paths.push_back (d->systemIncludePaths_ );
1056+ return paths;
1057+ }
1058+
1059+ [[nodiscard]] auto systemHeaderSearchPaths () -> SearchPaths {
1060+ std::vector<std::span<const std::string>> paths;
1061+ paths.push_back (d->systemIncludePaths_ );
1062+ return paths;
1063+ }
1064+
1065+ [[nodiscard]] auto search (auto view, const std::string &headerName)
10941066 -> std::optional<std::string> {
1095- if (auto p = search (d->systemIncludePaths_ , include.fileName )) {
1096- return p;
1097- }
1067+ auto transformToIncludePath = std::views::transform (
1068+ [&](const fs::path &path) { return path / headerName; });
10981069
1099- if (wantNextInlude && !didFindCurrentPath) {
1100- if (mode == Mode::kFirst )
1101- return firstMatch->string ();
1102- else
1103- candidates.push_back (firstMatch->string ());
1070+ auto filterExistingFiles = std::views::filter (
1071+ [&](const fs::path &path) { return d->fileExists (path); });
1072+
1073+ for (const auto &path : view | transformToIncludePath |
1074+ filterExistingFiles | std::views::reverse) {
1075+ if (!wantNextInlude) return path.string ();
1076+
1077+ firstMatch = path;
1078+
1079+ if (path == d->currentPath_ ) {
1080+ didFindCurrentPath = true ;
1081+ } else if (didFindCurrentPath) {
1082+ return path.string ();
1083+ }
11041084 }
11051085
11061086 return std::nullopt ;
@@ -1111,7 +1091,7 @@ struct Preprocessor::Private {
11111091 -> std::optional<std::string> {
11121092 if (!canResolveFiles_) return std::nullopt ;
11131093
1114- return std::visit ( Resolve{this , next}, include);
1094+ return Resolve{this , next}( include);
11151095 }
11161096
11171097 [[nodiscard]] auto isDefined (const std::string_view &id) const -> bool {
@@ -1797,15 +1777,6 @@ auto Preprocessor::Private::expand(
17971777 .loc = parsedInclude->loc ,
17981778 };
17991779
1800- nextState.candidates = [=, this ]() -> std::vector<std::string> {
1801- auto resolve =
1802- Resolve{this , parsedInclude->includeNext , Resolve::Mode::kAll };
1803-
1804- (void )std::visit (resolve, parsedInclude->header );
1805-
1806- return resolve.candidates ;
1807- };
1808-
18091780 // suspend the current file and start processing the continuation
18101781 buffers_.push_back (Buffer{
18111782 .source = source,
0 commit comments