@@ -1035,62 +1035,86 @@ struct Preprocessor::Private {
10351035
10361036 [[nodiscard]] auto checkPragmaOnceProtected (TokList *ts) const -> bool;
10371037
1038- [[nodiscard]] auto resolve (const Include &include, bool next) const
1039- -> std::optional<fs::path> {
1040- if (!canResolveFiles_) return std::nullopt ;
1038+ struct Resolve {
1039+ const Private *d;
1040+ bool wantNextInlude;
1041+ bool didFindCurrentPath = false ;
1042+ std::optional<fs::path> firstMatch;
10411043
1042- struct Resolve {
1043- const Private *d;
1044- bool next;
1045-
1046- Resolve (const Private *d, bool next) : d(d), next(next) {}
1047-
1048- [[nodiscard]] auto operator ()(const SystemInclude &include) const
1049- -> std::optional<fs::path> {
1050- bool hit = false ;
1051- for (const auto &includePath :
1052- d->systemIncludePaths_ | std::views::reverse) {
1053- const auto path = fs::path (includePath) / include.fileName ;
1054- if (d->fileExists (path)) {
1055- if (!next || hit) return path;
1056- hit = true ;
1057- }
1058- }
1059- return {};
1060- }
1044+ Resolve (const Private *d, bool next) : d(d), wantNextInlude(next) {}
10611045
1062- [[nodiscard]] auto operator ()(const QuoteInclude &include) const
1063- -> std::optional<fs::path> {
1064- bool hit = false ;
1046+ [[nodiscard]] auto search (auto view, const std::string &headerName)
1047+ -> std::optional<fs::path> {
1048+ auto transformToIncludePath = std::views::transform (
1049+ [&](const fs::path &path) { return path / headerName; });
10651050
1066- if (auto path = d->currentPath_ / include.fileName ;
1067- d->fileExists (path)) {
1068- if (!next) return path;
1069- hit = true ;
1070- }
1051+ auto filterExistingFiles = std::views::filter (
1052+ [&](const fs::path &path) { return d->fileExists (path); });
10711053
1072- for (const auto &includePath :
1073- d-> quoteIncludePaths_ | std::views::reverse) {
1074- const auto path = fs:: path(includePath) / include. fileName ;
1075- if (d-> fileExists (path)) {
1076- if (!next || hit) return path;
1077- hit = true ;
1078- }
1054+ for (const auto &path : view | transformToIncludePath |
1055+ filterExistingFiles | std::views::reverse) {
1056+ firstMatch = path;
1057+
1058+ if (wantNextInlude && path == d-> currentPath_ ) {
1059+ didFindCurrentPath = true ;
1060+ continue ;
10791061 }
10801062
1081- for (const auto &includePath :
1082- d->systemIncludePaths_ | std::views::reverse) {
1083- const auto path = fs::path (includePath) / include.fileName ;
1084- if (d->fileExists (path)) {
1085- if (!next || hit) return path;
1086- hit = true ;
1087- }
1063+ if (wantNextInlude && !didFindCurrentPath) {
1064+ continue ;
10881065 }
1089- return {};
1066+
1067+ return path;
1068+ }
1069+
1070+ return std::nullopt ;
1071+ }
1072+
1073+ [[nodiscard]] auto operator ()(const QuoteInclude &include)
1074+ -> std::optional<fs::path> {
1075+ const auto &headerName = include.fileName ;
1076+
1077+ // search in the current path
1078+ if (auto p = search (std::views::single (d->currentPath_ ), headerName)) {
1079+ return p;
1080+ }
1081+
1082+ // search in the quote include paths
1083+ if (auto p = search (d->quoteIncludePaths_ , headerName)) {
1084+ return p;
10901085 }
1091- };
10921086
1093- return std::visit (Resolve (this , next), include);
1087+ // fallback to system include paths
1088+ if (auto p = search (d->systemIncludePaths_ , headerName)) {
1089+ return p;
1090+ }
1091+
1092+ if (wantNextInlude && !didFindCurrentPath) {
1093+ return firstMatch;
1094+ }
1095+
1096+ return std::nullopt ;
1097+ }
1098+
1099+ [[nodiscard]] auto operator ()(const SystemInclude &include)
1100+ -> std::optional<fs::path> {
1101+ if (auto p = search (d->systemIncludePaths_ , include.fileName )) {
1102+ return p;
1103+ }
1104+
1105+ if (wantNextInlude && !didFindCurrentPath) {
1106+ return firstMatch;
1107+ }
1108+
1109+ return std::nullopt ;
1110+ }
1111+ };
1112+
1113+ [[nodiscard]] auto resolve (const Include &include, bool next) const
1114+ -> std::optional<fs::path> {
1115+ if (!canResolveFiles_) return std::nullopt ;
1116+
1117+ return std::visit (Resolve{this , next}, include);
10941118 }
10951119
10961120 [[nodiscard]] auto isDefined (const std::string_view &id) const -> bool {
@@ -2979,6 +3003,9 @@ auto Preprocessor::systemIncludePaths() const
29793003}
29803004
29813005void Preprocessor::addSystemIncludePath (std::string path) {
3006+ while (path.length () > 1 && path.ends_with (fs::path::preferred_separator)) {
3007+ path.pop_back ();
3008+ }
29823009 d->systemIncludePaths_ .push_back (std::move (path));
29833010}
29843011
0 commit comments