From 9486efc0220302fb63e7aba9df943531eaa4dac6 Mon Sep 17 00:00:00 2001 From: Martin Medler <36563496+martis42@users.noreply.github.com> Date: Sun, 20 Sep 2026 18:21:40 +0200 Subject: [PATCH] Fix aliasing _has_include with a custom macro Fixes https://github.com/boostorg/wave/issues/260 --- include/boost/wave/util/cpp_macromap.hpp | 8 +++--- test/testwave/testfiles/t_2_033.cpp | 32 ++++++++++++++++++++++++ test/testwave/testfiles/test.cfg | 1 + 3 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 test/testwave/testfiles/t_2_033.cpp diff --git a/include/boost/wave/util/cpp_macromap.hpp b/include/boost/wave/util/cpp_macromap.hpp index fad958a3..c7b93bc4 100644 --- a/include/boost/wave/util/cpp_macromap.hpp +++ b/include/boost/wave/util/cpp_macromap.hpp @@ -224,7 +224,6 @@ class macromap { void rescan_replacement_list(token_type const &curr_token, macro_definition_type ¯odef, ContainerT &replacement_list, ContainerT &expanded, bool expand_operator_defined, - bool expand_operator_has_include, IteratorT &nfirst, IteratorT const &nlast); // Resolves the operator defined() and replaces the token with "0" or "1" @@ -1363,7 +1362,6 @@ macromap::rescan_replacement_list(token_type const &curr_token, macro_definition_type ¯o_def, ContainerT &replacement_list, ContainerT &expanded, bool expand_operator_defined, - bool expand_operator_has_include, IteratorT &nfirst, IteratorT const &nlast) { if (!replacement_list.empty()) { @@ -1394,9 +1392,11 @@ macromap::rescan_replacement_list(token_type const &curr_token, typename ContainerT::iterator begin_it = replacement_list.begin(); typename ContainerT::iterator end_it = replacement_list.end(); + // The replacement list does not contain tokens following the macro invocation. + // Defer __has_include resolution until the expanded tokens are rescanned with those tokens available. expand_whole_tokensequence( expanded, begin_it, end_it, - expand_operator_defined, expand_operator_has_include); + expand_operator_defined, false); // trim replacement list, leave placeholder tokens untouched impl::trim_replacement_list(expanded); @@ -1643,7 +1643,7 @@ macromap::expand_macro(ContainerT &expanded, rescan_replacement_list( curr_token, macro_def, replacement_list, expanded_list, expand_operator_defined, - expand_operator_has_include, first, last); + first, last); ctx.get_hooks().rescanned_macro(ctx.derived(), expanded_list); diff --git a/test/testwave/testfiles/t_2_033.cpp b/test/testwave/testfiles/t_2_033.cpp new file mode 100644 index 00000000..9bab81eb --- /dev/null +++ b/test/testwave/testfiles/t_2_033.cpp @@ -0,0 +1,32 @@ +/*============================================================================= + Boost.Wave: A Standard compliant C++ preprocessor library + http://www.boost.org/ + + Copyright (c) 2026 Martin Medler. Distributed under the Boost + Software License, Version 1.0. (See accompanying file + LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +=============================================================================*/ + +//O --c++17 +//O -Werror +//O -S. + +// An object-like macro alias for __has_include must be expanded once before +// resolving the operator. +#define HAS_INCLUDE __has_include +#if HAS_INCLUDE() +#define FOUND_SELF_VIA_ALIAS +#else +#warning has_include could not find this file through an alias +#endif + +//H 10: t_2_033.cpp(16): #define +//H 08: t_2_033.cpp(16): HAS_INCLUDE=__has_include +//H 10: t_2_033.cpp(17): #if +//H 01: t_2_033.cpp(16): HAS_INCLUDE +//H 02: __has_include +//H 03: __has_include +//H 11: t_2_033.cpp(17): #if HAS_INCLUDE(): 1 +//H 10: t_2_033.cpp(18): #define +//H 08: t_2_033.cpp(18): FOUND_SELF_VIA_ALIAS= +//H 10: t_2_033.cpp(19): #else diff --git a/test/testwave/testfiles/test.cfg b/test/testwave/testfiles/test.cfg index 10d51b91..872f04a5 100644 --- a/test/testwave/testfiles/test.cfg +++ b/test/testwave/testfiles/test.cfg @@ -85,6 +85,7 @@ t_2_029.cpp t_2_030.cpp t_2_031.cpp t_2_032.cpp +t_2_033.cpp # # t_3: Predefined macros