Skip to content

Commit 7d0ae56

Browse files
committed
chore: Generalize search for include files
1 parent 8218f6e commit 7d0ae56

File tree

1 file changed

+46
-75
lines changed

1 file changed

+46
-75
lines changed

src/parser/cxx/preprocessor.cc

Lines changed: 46 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)