From 31e8a0bad8daf07b5f06dc1dad8ed4d8b640b267 Mon Sep 17 00:00:00 2001 From: Jeff Trull Date: Fri, 24 Jun 2022 14:55:35 -0700 Subject: [PATCH 1/2] Fix line directives after endif when else clause is present The initial part of a conditional block (the if/ifdef/ifndef) takes the "slow" path through the code in cpp_iterator.hpp using the C++ expression grammar, while else and endif directives take the "fast" path. The slow path sets must_emit_line_directive, and it will be cleared after either else or endif is processed. Unfortunately when an else precedes the endif, must_emit_line_directive is cleared and is never set, as only the slow path sets it. The result is proper line directives are issued for the else clause, but not for the subsequent endif. This changes adds setting of must_emit_line_directive in the "fast" path for endif so line directives are considered after an intervening else. --- include/boost/wave/util/cpp_iterator.hpp | 4 + test/testwave/testfiles/t_5_039.cpp | 205 +++++++++++++++++++++++ test/testwave/testfiles/test.cfg | 1 + 3 files changed, 210 insertions(+) create mode 100644 test/testwave/testfiles/t_5_039.cpp diff --git a/include/boost/wave/util/cpp_iterator.hpp b/include/boost/wave/util/cpp_iterator.hpp index 22c68570e..550e26157 100644 --- a/include/boost/wave/util/cpp_iterator.hpp +++ b/include/boost/wave/util/cpp_iterator.hpp @@ -1157,6 +1157,8 @@ pp_iterator_functor::handle_pp_directive(IteratorT &it) seen_newline = true; iter_ctx->first = it; } + if (T_PP_ENDIF == id) + must_emit_line_directive = true; return true; default: // #something else @@ -1233,6 +1235,8 @@ pp_iterator_functor::handle_pp_directive(IteratorT &it) // we skipped to the end of this line already seen_newline = true; iter_ctx->first = it; + if (T_PP_ENDIF == id) + must_emit_line_directive = true; return true; } break; diff --git a/test/testwave/testfiles/t_5_039.cpp b/test/testwave/testfiles/t_5_039.cpp new file mode 100644 index 000000000..7c9518b61 --- /dev/null +++ b/test/testwave/testfiles/t_5_039.cpp @@ -0,0 +1,205 @@ +/*============================================================================= + Boost.Wave: A Standard compliant C++ preprocessor library + http://www.boost.org/ + + Copyright (c) 2022 Jeff Trull. 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) + +=============================================================================*/ + +// Check generated line directives +// This test covers issue #24 + +// define one macro +#define FOO + +// try a variation matrix: +// 1. initial #if true vs. false +// 2. with/without else clause +// 3. additional text immediately after #endif vs. one line later + +#ifdef FOO +struct Bar {}; +#endif +struct Quux {}; + +// initial #if false + +#ifndef FOO +struct Bar {}; +#endif +struct Quux {}; + +// adding else clause + +#ifdef FOO +struct Bar {}; +#else +struct Baz {}; +#endif +struct Quux {}; + +#ifndef FOO +struct Bar {}; +#else +struct Baz {}; +#endif +struct Quux {}; + +// intermediate space before next line + +#ifdef FOO +struct Bar {}; +#endif + +struct Quux {}; + +#ifndef FOO +struct Bar {}; +#endif + +struct Quux {}; + +#ifdef FOO +struct Bar {}; +#else +struct Baz {}; +#endif + +struct Quux {}; + +#ifndef FOO +struct Bar {}; +#else +struct Baz {}; +#endif + +struct Quux {}; + +// varying the location of the "true" conditional block among 3 + +#ifdef FOO +// first block is present +struct Bar {}; +#elif defined(BAR) +struct Baz {}; +#else +struct Boozle {}; +#endif + +struct Quux {}; + +#ifndef FOO +struct Bar {}; +#elif !defined(BAR) +// second block is present +struct Baz {}; +#else +struct Boozle {}; +#endif + +struct Quux {}; + +#ifndef FOO +struct Bar {}; +#elif defined(BAR) +struct Baz {}; +#else +// third block is present +struct Boozle {}; +#endif + +struct Quux {}; + +// test two-part conditionals that have an elif instead of an else +#ifdef FOO +// first part true +struct Bar {}; +#elif defined(BAR) +struct Baz {}; +#endif +struct Quux {}; + +#ifndef FOO +struct Bar {}; +#elif !defined(BAR) +// second part true +struct Baz {}; +#endif + +struct Quux {}; + +// neither part true +#ifndef FOO +struct Bar {}; +#elif defined(BAR) +struct Baz {}; +#endif +struct Quux {}; + +// one more test: extra empty line before else clause +#ifndef FOO +struct Bar {}; +#else + +struct Baz {}; +#endif +struct Quux {}; + + + +//R #line 23 "t_5_039.cpp" +//R struct Bar {}; +//R +//R struct Quux {}; +//R #line 32 "t_5_039.cpp" +//R struct Quux {}; +//R #line 37 "t_5_039.cpp" +//R struct Bar {}; +//R #line 41 "t_5_039.cpp" +//R struct Quux {}; +//R #line 46 "t_5_039.cpp" +//R struct Baz {}; +//R +//R struct Quux {}; +//R #line 53 "t_5_039.cpp" +//R struct Bar {}; +//R #line 56 "t_5_039.cpp" +//R struct Quux {}; +//R #line 62 "t_5_039.cpp" +//R struct Quux {}; +//R #line 65 "t_5_039.cpp" +//R struct Bar {}; +//R #line 70 "t_5_039.cpp" +//R struct Quux {}; +//R #line 75 "t_5_039.cpp" +//R struct Baz {}; +//R #line 78 "t_5_039.cpp" +//R struct Quux {}; +//R #line 84 "t_5_039.cpp" +//R struct Bar {}; +//R #line 91 "t_5_039.cpp" +//R struct Quux {}; +//R #line 97 "t_5_039.cpp" +//R struct Baz {}; +//R #line 102 "t_5_039.cpp" +//R struct Quux {}; +//R #line 110 "t_5_039.cpp" +//R struct Boozle {}; +//R #line 113 "t_5_039.cpp" +//R struct Quux {}; +//R #line 118 "t_5_039.cpp" +//R struct Bar {}; +//R #line 122 "t_5_039.cpp" +//R struct Quux {}; +//R #line 128 "t_5_039.cpp" +//R struct Baz {}; +//R #line 131 "t_5_039.cpp" +//R struct Quux {}; +//R #line 139 "t_5_039.cpp" +//R struct Quux {}; +//R #line 146 "t_5_039.cpp" +//R struct Baz {}; +//R +//R struct Quux {}; diff --git a/test/testwave/testfiles/test.cfg b/test/testwave/testfiles/test.cfg index 9102783fa..6b41964e8 100644 --- a/test/testwave/testfiles/test.cfg +++ b/test/testwave/testfiles/test.cfg @@ -145,6 +145,7 @@ t_5_035.cpp t_5_036.cpp t_5_037.cpp t_5_038.cpp +t_5_039.cpp # # unit tests from the mcpp preprocessor validation suite From 79fae476787fdfa89a1f65f1d530d7a2560aa77b Mon Sep 17 00:00:00 2001 From: Jeff Trull Date: Fri, 24 Jun 2022 15:40:19 -0700 Subject: [PATCH 2/2] Also include new fix in ChangeLog --- ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog b/ChangeLog index 4c9ae36c4..7f2398829 100644 --- a/ChangeLog +++ b/ChangeLog @@ -19,6 +19,7 @@ TODO (known issues): CHANGELOG Boost V1.80: + - Fixed #24: Line numbers wrong after conditional section - Fixed #160: one test fails with error C2660 and error C2440 under msvc /permissive- mode - Fixed #161: BOOST_WAVE_THROW_NAME_CTX does not result in a context callback and always throws - Fixed #162: When Boost headers are included in the preprocessed translation unit, Wave fails in boost/integer.hpp(99)