From 7d0ae5650398e0e015d466ebec65db0ad88d3d98 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 12 Nov 2024 18:55:10 +0100 Subject: [PATCH 1/3] chore: Generalize search for include files --- src/parser/cxx/preprocessor.cc | 121 +++++++++++++-------------------- 1 file changed, 46 insertions(+), 75 deletions(-) diff --git a/src/parser/cxx/preprocessor.cc b/src/parser/cxx/preprocessor.cc index 80d3c7a4..9551223c 100644 --- a/src/parser/cxx/preprocessor.cc +++ b/src/parser/cxx/preprocessor.cc @@ -1010,97 +1010,77 @@ struct Preprocessor::Private { [[nodiscard]] auto checkPragmaOnceProtected(TokList *ts) const -> bool; struct Resolve { - enum struct Mode { - kFirst, - kAll, - }; - const Private *d; bool wantNextInlude; bool didFindCurrentPath = false; std::optional firstMatch; - Mode mode; - std::vector candidates; + std::array currentPaths; Resolve(const Resolve &other) = delete; auto operator=(const Resolve &other) -> Resolve & = delete; - Resolve(const Private *d, bool next, Mode mode = Mode::kFirst) - : d(d), wantNextInlude(next), mode(mode) {} - - [[nodiscard]] auto search(auto view, const std::string &headerName) - -> std::optional { - auto transformToIncludePath = std::views::transform( - [&](const fs::path &path) { return path / headerName; }); - - auto filterExistingFiles = std::views::filter( - [&](const fs::path &path) { return d->fileExists(path); }); - - for (const auto &path : view | transformToIncludePath | - filterExistingFiles | std::views::reverse) { - firstMatch = path; - - if (wantNextInlude && path == d->currentPath_) { - didFindCurrentPath = true; - continue; - } - - if (wantNextInlude && !didFindCurrentPath) { - continue; - } - - if (mode == Mode::kFirst) return path.string(); - - candidates.push_back(path.string()); - } + Resolve(const Private *d, bool next) + : d(d), wantNextInlude(next), currentPaths{{d->currentPath_}} {} - return std::nullopt; - } + using SearchPaths = std::vector>; - [[nodiscard]] auto operator()(const QuoteInclude &include) + [[nodiscard]] auto operator()(const Include &include) -> std::optional { - const auto &headerName = include.fileName; - // search in the current path - if (auto p = search(std::views::single(d->currentPath_), headerName); - mode == Mode::kFirst && p) { - return p; - } + auto header = getHeaderName(include); - // search in the quote include paths - if (auto p = search(d->quoteIncludePaths_, headerName); - mode == Mode::kFirst && p) { - return p; + SearchPaths searchPaths; + + if (std::holds_alternative(include)) { + searchPaths = userHeaderSearchPaths(); + } else { + searchPaths = systemHeaderSearchPaths(); } - // fallback to system include paths - if (auto p = search(d->systemIncludePaths_, headerName); - mode == Mode::kFirst && p) { + if (auto p = search(searchPaths | std::views::join, header)) { return p; } if (wantNextInlude && !didFindCurrentPath) { - if (mode == Mode::kFirst) - return firstMatch->string(); - else { - candidates.push_back(firstMatch->string()); - } + return firstMatch; } return std::nullopt; } - [[nodiscard]] auto operator()(const SystemInclude &include) + [[nodiscard]] auto userHeaderSearchPaths() -> SearchPaths { + std::vector> paths; + paths.push_back(currentPaths); + paths.push_back(d->quoteIncludePaths_); + paths.push_back(d->systemIncludePaths_); + return paths; + } + + [[nodiscard]] auto systemHeaderSearchPaths() -> SearchPaths { + std::vector> paths; + paths.push_back(d->systemIncludePaths_); + return paths; + } + + [[nodiscard]] auto search(auto view, const std::string &headerName) -> std::optional { - if (auto p = search(d->systemIncludePaths_, include.fileName)) { - return p; - } + auto transformToIncludePath = std::views::transform( + [&](const fs::path &path) { return path / headerName; }); - if (wantNextInlude && !didFindCurrentPath) { - if (mode == Mode::kFirst) - return firstMatch->string(); - else - candidates.push_back(firstMatch->string()); + auto filterExistingFiles = std::views::filter( + [&](const fs::path &path) { return d->fileExists(path); }); + + for (const auto &path : view | transformToIncludePath | + filterExistingFiles | std::views::reverse) { + if (!wantNextInlude) return path.string(); + + firstMatch = path; + + if (path == d->currentPath_) { + didFindCurrentPath = true; + } else if (didFindCurrentPath) { + return path.string(); + } } return std::nullopt; @@ -1111,7 +1091,7 @@ struct Preprocessor::Private { -> std::optional { if (!canResolveFiles_) return std::nullopt; - return std::visit(Resolve{this, next}, include); + return Resolve{this, next}(include); } [[nodiscard]] auto isDefined(const std::string_view &id) const -> bool { @@ -1797,15 +1777,6 @@ auto Preprocessor::Private::expand( .loc = parsedInclude->loc, }; - nextState.candidates = [=, this]() -> std::vector { - auto resolve = - Resolve{this, parsedInclude->includeNext, Resolve::Mode::kAll}; - - (void)std::visit(resolve, parsedInclude->header); - - return resolve.candidates; - }; - // suspend the current file and start processing the continuation buffers_.push_back(Buffer{ .source = source, From 0629fbe78d97766bb52841ceb5055231d9e0fe0b Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 12 Nov 2024 18:04:04 +0000 Subject: [PATCH 2/3] chore: Update macOS runner version to 15 Signed-off-by: Roberto Raggi --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8c25a3cd..f0c7760b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -130,7 +130,7 @@ jobs: retention-days: 1 build-macos: - runs-on: macos-14 + runs-on: macos-15 steps: - uses: actions/checkout@v4 From d70c04f12d00b1f08a7a5306f38ce8425b204791 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Tue, 12 Nov 2024 18:14:51 +0000 Subject: [PATCH 3/3] chore: Use std::span for include paths in preprocessor Signed-off-by: Roberto Raggi --- src/parser/cxx/preprocessor.cc | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/parser/cxx/preprocessor.cc b/src/parser/cxx/preprocessor.cc index 9551223c..0f622405 100644 --- a/src/parser/cxx/preprocessor.cc +++ b/src/parser/cxx/preprocessor.cc @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -1019,8 +1020,9 @@ struct Preprocessor::Private { Resolve(const Resolve &other) = delete; auto operator=(const Resolve &other) -> Resolve & = delete; - Resolve(const Private *d, bool next) - : d(d), wantNextInlude(next), currentPaths{{d->currentPath_}} {} + Resolve(const Private *d, bool next) : d(d), wantNextInlude(next) { + currentPaths[0] = d->currentPath_.string(); + } using SearchPaths = std::vector>; @@ -1041,8 +1043,8 @@ struct Preprocessor::Private { return p; } - if (wantNextInlude && !didFindCurrentPath) { - return firstMatch; + if (wantNextInlude && !didFindCurrentPath && firstMatch.has_value()) { + return firstMatch->string(); } return std::nullopt; @@ -1050,15 +1052,15 @@ struct Preprocessor::Private { [[nodiscard]] auto userHeaderSearchPaths() -> SearchPaths { std::vector> paths; - paths.push_back(currentPaths); - paths.push_back(d->quoteIncludePaths_); - paths.push_back(d->systemIncludePaths_); + paths.push_back(std::span(currentPaths)); + paths.push_back(std::span(d->quoteIncludePaths_)); + paths.push_back(std::span(d->systemIncludePaths_)); return paths; } [[nodiscard]] auto systemHeaderSearchPaths() -> SearchPaths { std::vector> paths; - paths.push_back(d->systemIncludePaths_); + paths.push_back(std::span(d->systemIncludePaths_)); return paths; }