@@ -731,6 +731,15 @@ struct Preprocessor::Private {
731731 std::function<std::string(std::string)> readFile_;
732732 std::function<void (const std::string &, int )> willIncludeHeader_;
733733 std::vector<Buffer> buffers_;
734+ struct Dep {
735+ std::string_view local;
736+ Include include;
737+ bool isIncludeNext = false ;
738+ int value = 0 ;
739+ };
740+ std::vector<Dep> dependencies_;
741+ int localCount_ = 0 ;
742+
734743 int counter_ = 0 ;
735744 int includeDepth_ = 0 ;
736745 bool omitLineMarkers_ = false ;
@@ -1379,6 +1388,15 @@ void Preprocessor::Private::initialize() {
13791388 return cons (tk, ts);
13801389 };
13811390
1391+ auto replaceWithLocal = [this ](const Tok *token, std::string_view local,
1392+ TokList *ts) {
1393+ auto tk = gen (TokenKind::T_PP_INTERNAL_VARIABLE, local);
1394+ tk->sourceFile = token->sourceFile ;
1395+ tk->space = token->space ;
1396+ tk->bol = token->bol ;
1397+ return cons (tk, ts);
1398+ };
1399+
13821400 adddBuiltinFunctionMacro (
13831401 " __has_feature" ,
13841402 [this , replaceWithBoolLiteral](
@@ -1435,7 +1453,7 @@ void Preprocessor::Private::initialize() {
14351453 return replaceWithBoolLiteral (macroId, enabled, ts);
14361454 });
14371455
1438- auto hasInclude = [this , replaceWithBoolLiteral](
1456+ auto hasInclude = [this , replaceWithLocal, replaceWithBoolLiteral](
14391457 const MacroExpansionContext &context) -> TokList * {
14401458 auto ts = context.ts ;
14411459
@@ -1478,9 +1496,11 @@ void Preprocessor::Private::initialize() {
14781496 include = SystemInclude (std::move (fn));
14791497 }
14801498
1481- const auto value = resolve (include, isIncludeNext);
1499+ std::string_view local = string (std::format (" @{}" , localCount_++));
1500+
1501+ dependencies_.push_back ({local, include, isIncludeNext});
14821502
1483- return replaceWithBoolLiteral (macroName, value. has_value () , rest);
1503+ return replaceWithLocal (macroName, local , rest);
14841504 };
14851505
14861506 adddBuiltinFunctionMacro (" __has_include" , hasInclude);
@@ -1710,6 +1730,8 @@ auto Preprocessor::Private::parseDirective(SourceFile *source, TokList *start)
17101730
17111731 if (!lookat (directive, TokenKind::T_IDENTIFIER)) return std::nullopt ;
17121732
1733+ dependencies_.clear ();
1734+
17131735 const auto directiveKind = classifyDirective (directive->tok ->text .data (),
17141736 directive->tok ->text .length ());
17151737
@@ -2344,8 +2366,14 @@ auto Preprocessor::Private::copyLine(TokList *ts, bool inMacroBody)
23442366
23452367auto Preprocessor::Private::constantExpression (TokList *ts) -> long {
23462368 auto line = copyLine (ts);
2369+ dependencies_.clear ();
23472370 auto it = expandTokens (TokIterator{line}, TokIterator{},
23482371 /* inConditionalExpression*/ true );
2372+ // evaluate the deps
2373+ for (auto &d : dependencies_) {
2374+ auto resolved = resolve (d.include , d.isIncludeNext );
2375+ d.value = resolved.has_value ();
2376+ }
23492377 auto e = it.toTokList ();
23502378 return conditionalExpression (e);
23512379}
@@ -2527,6 +2555,13 @@ auto Preprocessor::Private::primaryExpression(TokList *&ts) -> long {
25272555 auto result = conditionalExpression (ts);
25282556 expect (ts, TokenKind::T_RPAREN);
25292557 return result;
2558+ } else if (tk->is (TokenKind::T_PP_INTERNAL_VARIABLE)) {
2559+ for (const auto &dep : dependencies_) {
2560+ if (dep.local == tk->text ) {
2561+ ts = ts->next ;
2562+ return dep.value ;
2563+ }
2564+ }
25302565 }
25312566
25322567 ts = ts->next ;
0 commit comments