2626#include < cxx/diagnostics_client.h>
2727#include < cxx/lexer.h>
2828#include < cxx/literals.h>
29+ #include < cxx/preprocessor.h>
2930#include < cxx/private/path.h>
30-
31- // fmt
32- #include < format>
33-
34- // utf8
3531#include < utf8/unchecked.h>
3632
37- // stl
38- #include < cxx/preprocessor.h>
39-
4033#include < algorithm>
4134#include < cassert>
35+ #include < format>
4236#include < forward_list>
4337#include < fstream>
4438#include < functional>
@@ -1167,8 +1161,15 @@ struct Preprocessor::Private {
11671161 TokList *loc = nullptr ;
11681162 };
11691163
1164+ struct ParsedIfDirective {
1165+ std::function<void ()> resume;
1166+ };
1167+
1168+ using ParsedDirective =
1169+ std::variant<std::monostate, ParsedIncludeDirective, ParsedIfDirective>;
1170+
11701171 [[nodiscard]] auto parseDirective (SourceFile *source, TokList *start)
1171- -> std::optional<ParsedIncludeDirective> ;
1172+ -> ParsedDirective ;
11721173
11731174 [[nodiscard]] auto parseIncludeDirective (TokList *directive, TokList *ts)
11741175 -> std::optional<ParsedIncludeDirective>;
@@ -1203,7 +1204,9 @@ struct Preprocessor::Private {
12031204 [[nodiscard]] auto copyLine (TokList *ts, bool inMacroBody = false )
12041205 -> TokList *;
12051206
1206- [[nodiscard]] auto constantExpression (TokList *ts) -> long;
1207+ [[nodiscard]] auto prepareConstantExpression (TokList *ts) -> TokList *;
1208+
1209+ [[nodiscard]] auto evaluateConstantExpression (TokList *ts) -> long;
12071210 [[nodiscard]] auto conditionalExpression (TokList *&ts) -> long;
12081211 [[nodiscard]] auto binaryExpression (TokList *&ts) -> long;
12091212 [[nodiscard]] auto binaryExpressionHelper (TokList *&ts, long lhs, int minPrec)
@@ -1672,7 +1675,10 @@ auto Preprocessor::Private::expand(
16721675 // skip the rest of the line
16731676 it = skipLine (it, last);
16741677
1675- if (auto parsedInclude = parseDirective (source, start.toTokList ())) {
1678+ auto parsedDirective = parseDirective (source, start.toTokList ());
1679+
1680+ if (auto parsedInclude =
1681+ std::get_if<ParsedIncludeDirective>(&parsedDirective)) {
16761682 NeedToResolveInclude status{
16771683 .preprocessor = *preprocessor_,
16781684 .include = parsedInclude->header ,
@@ -1692,6 +1698,10 @@ auto Preprocessor::Private::expand(
16921698 it = last;
16931699
16941700 return status;
1701+ } else if (auto directive =
1702+ std::get_if<ParsedIfDirective>(&parsedDirective)) {
1703+ // suspend and resolve the dependencies
1704+ directive->resume ();
16951705 }
16961706 } else if (skipping) {
16971707 it = skipLine (++it, last);
@@ -1707,10 +1717,10 @@ auto Preprocessor::Private::expand(
17071717}
17081718
17091719auto Preprocessor::Private::parseDirective (SourceFile *source, TokList *start)
1710- -> std::optional<ParsedIncludeDirective> {
1720+ -> ParsedDirective {
17111721 auto directive = start->next ;
17121722
1713- if (!lookat (directive, TokenKind::T_IDENTIFIER)) return std::nullopt ;
1723+ if (!lookat (directive, TokenKind::T_IDENTIFIER)) return std::monostate{} ;
17141724
17151725 dependencies_.clear ();
17161726
@@ -1725,7 +1735,11 @@ auto Preprocessor::Private::parseDirective(SourceFile *source, TokList *start)
17251735 case PreprocessorDirectiveKind::T_INCLUDE_NEXT:
17261736 case PreprocessorDirectiveKind::T_INCLUDE: {
17271737 if (skipping) break ;
1728- return parseIncludeDirective (directive, ts);
1738+ auto includeDirective = parseIncludeDirective (directive, ts);
1739+ if (includeDirective.has_value ()) {
1740+ return *includeDirective;
1741+ }
1742+ break ;
17291743 }
17301744
17311745 case PreprocessorDirectiveKind::T_DEFINE: {
@@ -1781,12 +1795,25 @@ auto Preprocessor::Private::parseDirective(SourceFile *source, TokList *start)
17811795 if (skipping) {
17821796 pushState (std::tuple (true , false ));
17831797 } else {
1784- const auto value = constantExpression (ts);
1785- if (value) {
1786- pushState (std::tuple (skipping, false ));
1787- } else {
1788- pushState (std::tuple (true , !skipping));
1789- }
1798+ auto expression = prepareConstantExpression (ts);
1799+
1800+ auto resume = [=, this ] {
1801+ // evaluate the deps
1802+ for (auto &d : dependencies_) {
1803+ auto resolved = resolve (d.include , d.isIncludeNext );
1804+ d.value = resolved.has_value ();
1805+ }
1806+
1807+ const auto value = evaluateConstantExpression (expression);
1808+
1809+ if (value) {
1810+ pushState (std::tuple (skipping, false ));
1811+ } else {
1812+ pushState (std::tuple (true , !skipping));
1813+ }
1814+ };
1815+
1816+ return ParsedIfDirective{.resume = std::move (resume)};
17901817 }
17911818
17921819 break ;
@@ -1796,12 +1823,25 @@ auto Preprocessor::Private::parseDirective(SourceFile *source, TokList *start)
17961823 if (!evaluating) {
17971824 setState (std::tuple (true , false ));
17981825 } else {
1799- const auto value = constantExpression (ts);
1800- if (value) {
1801- setState (std::tuple (!evaluating, false ));
1802- } else {
1803- setState (std::tuple (true , evaluating));
1804- }
1826+ auto expression = prepareConstantExpression (ts);
1827+
1828+ auto resume = [=, this ] {
1829+ // evaluate the deps
1830+ for (auto &d : dependencies_) {
1831+ auto resolved = resolve (d.include , d.isIncludeNext );
1832+ d.value = resolved.has_value ();
1833+ }
1834+
1835+ const auto value = evaluateConstantExpression (expression);
1836+
1837+ if (value) {
1838+ setState (std::tuple (!evaluating, false ));
1839+ } else {
1840+ setState (std::tuple (true , evaluating));
1841+ }
1842+ };
1843+
1844+ return ParsedIfDirective{.resume = std::move (resume)};
18051845 }
18061846
18071847 break ;
@@ -1899,7 +1939,7 @@ auto Preprocessor::Private::parseDirective(SourceFile *source, TokList *start)
18991939 break ;
19001940 } // switch
19011941
1902- return std::nullopt ;
1942+ return std::monostate{} ;
19031943}
19041944
19051945auto Preprocessor::Private::parseIncludeDirective (TokList *directive,
@@ -2348,18 +2388,28 @@ auto Preprocessor::Private::copyLine(TokList *ts, bool inMacroBody)
23482388 return line;
23492389}
23502390
2351- auto Preprocessor::Private::constantExpression (TokList *ts) -> long {
2391+ auto Preprocessor::Private::prepareConstantExpression (TokList *ts)
2392+ -> TokList * {
23522393 auto line = copyLine (ts);
2394+
23532395 dependencies_.clear ();
2396+
23542397 auto it = expandTokens (TokIterator{line}, TokIterator{},
23552398 /* inConditionalExpression*/ true );
2399+
2400+ auto expression = it.toTokList ();
2401+
2402+ return expression;
2403+ }
2404+
2405+ auto Preprocessor::Private::evaluateConstantExpression (TokList *ts) -> long {
23562406 // evaluate the deps
23572407 for (auto &d : dependencies_) {
23582408 auto resolved = resolve (d.include , d.isIncludeNext );
23592409 d.value = resolved.has_value ();
23602410 }
2361- auto e = it. toTokList ();
2362- return conditionalExpression (e );
2411+
2412+ return conditionalExpression (ts );
23632413}
23642414
23652415auto Preprocessor::Private::conditionalExpression (TokList *&ts) -> long {
0 commit comments