diff --git a/.travis.yml b/.travis.yml index 2bc5872d..060a16aa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,18 +4,11 @@ language: cpp -sudo: false - -python: "2.7" - -os: - - linux - - osx - branches: only: - master - develop + - /feature\/.*/ env: matrix: @@ -27,6 +20,20 @@ matrix: - env: BOGUS_JOB=true include: + - os: linux + env: TEST_CMAKE=true # variables unused - just for identification in travis ci gui + script: + - mkdir __build__ && cd __build__ + - cmake .. -DBOOST_ENABLE_CMAKE=ON -DBOOST_INCLUDE_LIBRARIES=regex -DBOOST_REGEX_INCLUDE_EXAMPLES=ON + - cmake --build . + + - os: linux + env: TEST_CMAKE=true BUILD_SHARED_LIBS=On # variables unused - just for identification in travis ci gui + script: + - mkdir __build__ && cd __build__ + - cmake .. -DBUILD_SHARED_LIBS=ON -DBOOST_ENABLE_CMAKE=ON -DBOOST_INCLUDE_LIBRARIES=regex -DBOOST_REGEX_INCLUDE_EXAMPLES=ON + - cmake --build . + - os: linux env: TOOLSET=gcc COMPILER=g++ CXXSTD=03 @@ -241,60 +248,27 @@ matrix: - os: osx env: TOOLSET=clang COMPILER=clang++ CXXSTD=11 osx_image: xcode6.4 + # On this image, git doesn't support --jobs 3 + install: + - BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true + - cd .. + - git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + - cd boost-root + - git submodule update --init tools/boostdep + - cp -r $TRAVIS_BUILD_DIR/* libs/regex + - python tools/boostdep/depinst/depinst.py -I example regex + - ./bootstrap.sh + - ./b2 headers + install: + - BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true - cd .. - - git clone -b $TRAVIS_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root + - git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root - cd boost-root - - git submodule update --init tools/build - - git submodule update --init tools/boost_install - - git submodule update --init libs/headers - - git submodule update --init libs/config - - git submodule update --init libs/core - - git submodule update --init libs/container_hash - - git submodule update --init libs/detail - - git submodule update --init libs/smart_ptr - - git submodule update --init libs/predef - - git submodule update --init libs/assert - - git submodule update --init libs/throw_exception - - git submodule update --init libs/mpl - - git submodule update --init libs/type_traits - - git submodule update --init libs/static_assert - - git submodule update --init libs/integer - - git submodule update --init libs/preprocessor - - git submodule update --init libs/functional - - git submodule update --init libs/program_options - - git submodule update --init libs/chrono - - git submodule update --init libs/system - - git submodule update --init libs/thread - - git submodule update --init libs/winapi - - git submodule update --init libs/move - - git submodule update --init libs/date_time - - git submodule update --init libs/ratio - - git submodule update --init libs/iterator - - git submodule update --init libs/range - - git submodule update --init libs/any - - git submodule update --init libs/concept_check - - git submodule update --init libs/array - - git submodule update --init libs/timer - - git submodule update --init libs/bind - - git submodule update --init libs/utility - - git submodule update --init libs/io - - git submodule update --init libs/intrusive - - git submodule update --init libs/container - - git submodule update --init libs/tuple - - git submodule update --init libs/exception - - git submodule update --init libs/function - - git submodule update --init libs/type_index - - git submodule update --init libs/lexical_cast - - git submodule update --init libs/numeric - - git submodule update --init libs/math - - git submodule update --init libs/tokenizer - - git submodule update --init libs/optional - - git submodule update --init libs/atomic - - git submodule update --init libs/rational - - git submodule update --init libs/algorithm + - git submodule update --init tools/boostdep - cp -r $TRAVIS_BUILD_DIR/* libs/regex + - python tools/boostdep/depinst/depinst.py -I example -g "--jobs 3" regex - ./bootstrap.sh - ./b2 headers diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..a61ba77c --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,103 @@ +# Copyright 2018-2019 Mike Dev +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt +# +# NOTE: CMake support for Boost.Regex is currently experimental at best +# and the interface is likely to change in the future + + +##### How-To: +# +# If you have a cmake project that wants to use and compile +# boost_regex, as part of a single build system run, do the following: +# 1) clone the boost project and all its sub-projects: +# +# git clone --branch develop --depth 1 --recursive --shallow-submodules https://github.com/boostorg/boost.git boost-root +# +# 2) add to your cmake script: +# +# add_subdirectory( []) +# target_link_libraries( PUBLIC Boost::regex) +# +# 3) run your cmake build as usual +# +# ## Explanation: +# +# Currently this file does not work standalone. It is expected to be +# invoked from a parent script via add_subdirectory. That parent script +# is responsible for providing targets for direct and indirect dependencies, +# such as Boost::assert, Boost::concept_check, e.g. by also adding those +# libraries via add_submodule (order doesn't matter). +# The parent script can be your own cmake script, but it is easier to just +# use add the CMakeLists in the root of the boost super project, which +# will in turn add all boost libraries usable with the add_subdirectory +# Workflow. +# +# Note: You don't need to actually clone all boost libraries. E.g. look +# into the travis ci file to see on which libraries boost_regex actually +# depends or use boostdep https://github.com/boostorg/boostdep + + +##### Current Limitations: +# +# - Doesn't compile or run tests +# + +cmake_minimum_required( VERSION 3.5...3.16 ) +project( boost_regex VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX ) + +option( BOOST_REGEX_INCLUDE_EXAMPLES "Also build (some) boost regex examples" OFF ) +option( BOOST_REGEX_USE_ICU "Enable ICU support in boost regex" OFF ) + +file( GLOB BOOST_REGEX_SRC ./src/*.cpp ) + +add_library( boost_regex ${BOOST_REGEX_SRC} ) +add_library( Boost::regex ALIAS boost_regex ) + +target_include_directories( boost_regex PUBLIC include ) + +target_compile_definitions( boost_regex + PUBLIC + # No need for autolink + BOOST_REGEX_NO_LIB + $<$,SHARED_LIBRARY>:BOOST_REGEX_DYN_LINK=1> + $<$,STATIC_LIBRARY>:BOOST_REGEX_STATIC_LINK=1> +) + +# Specify dependencies (including header-only libraries) +target_link_libraries( boost_regex + PUBLIC + Boost::assert + Boost::concept_check + Boost::config + Boost::container_hash + Boost::core + Boost::integer + Boost::iterator + Boost::mpl + Boost::predef + Boost::smart_ptr + Boost::static_assert + Boost::throw_exception + Boost::type_traits +) + +if( BOOST_REGEX_USE_ICU ) + # ICU Targets could be provided by parent project, + # if not, look for them ourselves + if( NOT TARGET ICU::dt ) + # components need to be listed explicitly + find_package( ICU COMPONENTS dt in uc REQUIRED ) + endif() + + target_link_libraries( boost_regex + PRIVATE + ICU::dt ICU::in ICU::uc + ) + target_compile_definitions( boost_regex PRIVATE BOOST_HAS_ICU=1 ) +endif() + +if( BOOST_REGEX_INCLUDE_EXAMPLES ) + add_subdirectory( example/snippets ) +endif() + diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index f5415728..e4de0afd 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -116,7 +116,7 @@ if ! $(disable-icu) } -unit-test has_icu : has_icu_test.cpp : $(ICU_OPTS) ; +exe has_icu : has_icu_test.cpp : $(ICU_OPTS) ; explicit has_icu ; alias icu_options : : : : [ check-target-builds has_icu : $(ICU_OPTS) : ] ; diff --git a/doc/history.qbk b/doc/history.qbk index 026f5a30..be64bb13 100644 --- a/doc/history.qbk +++ b/doc/history.qbk @@ -8,12 +8,11 @@ [section:history History] -New issues should be submitted at [@http://svn.boost.org svn.boost.org] - don't forget to include your -email address in the ticket! +New issues should be submitted at [@https://github.com/boostorg/regex/issues https://github.com/boostorg/regex/issues] -Currently open issues can be viewed [@https://svn.boost.org/trac/boost/query?status=assigned&status=new&status=reopened&component=regex&order=priority&col=id&col=summary&col=status&col=type&col=milestone&col=component here]. +Currently open issues can be viewed [@https://github.com/boostorg/regex/issues?q=is%3Aopen+is%3Aissue here]. -All issues including closed ones can be viewed [@https://svn.boost.org/trac/boost/query?status=assigned&status=closed&status=new&status=reopened&component=regex&order=priority&col=id&col=summary&col=status&col=type&col=milestone&col=component here]. +All issues including closed ones can be viewed [@https://github.com/boostorg/regex/issues?q=is%3Aissue+is%3Aclosed here]. [h4 Boost.Regex-5.1.4 (Boost-172.0)] diff --git a/example/snippets/CMakeLists.txt b/example/snippets/CMakeLists.txt new file mode 100644 index 00000000..f672785b --- /dev/null +++ b/example/snippets/CMakeLists.txt @@ -0,0 +1,30 @@ +# Copyright 2019 Mike Dev +# Distributed under the Boost Software License, Version 1.0. +# See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt +# +# NOTE: CMake support for Boost.Regex is currently experimental at best +# and we are currently only building a few examples + +set(examples + partial_regex_grep + partial_regex_iterate + partial_regex_match + regex_grep_example_1 + regex_grep_example_2 + regex_grep_example_3 + regex_grep_example_4 + regex_iterator_example + regex_match_example + regex_merge_example + regex_replace_example + regex_search_example + regex_split_example_1 + regex_split_example_2 + regex_token_iterator_eg_1 + regex_token_iterator_eg_2 +) + +foreach( example IN LISTS examples ) + add_executable( boost_regex_ex_${example} ${example}.cpp ) + target_link_libraries( boost_regex_ex_${example} Boost::regex ) +endforeach() diff --git a/include/boost/regex/pattern_except.hpp b/include/boost/regex/pattern_except.hpp index 004b67f3..7ca409d8 100644 --- a/include/boost/regex/pattern_except.hpp +++ b/include/boost/regex/pattern_except.hpp @@ -43,13 +43,16 @@ namespace boost{ #ifdef BOOST_MSVC #pragma warning(push) #pragma warning(disable : 4275) +#if BOOST_MSVC >= 1800 +#pragma warning(disable : 26812) +#endif #endif class BOOST_REGEX_DECL regex_error : public std::runtime_error { public: explicit regex_error(const std::string& s, regex_constants::error_type err = regex_constants::error_unknown, std::ptrdiff_t pos = 0); explicit regex_error(regex_constants::error_type err); - ~regex_error() throw(); + ~regex_error() BOOST_NOEXCEPT_OR_NOTHROW; regex_constants::error_type code()const { return m_error_code; } std::ptrdiff_t position()const diff --git a/include/boost/regex/pending/object_cache.hpp b/include/boost/regex/pending/object_cache.hpp index c47862f0..ea51ba3a 100644 --- a/include/boost/regex/pending/object_cache.hpp +++ b/include/boost/regex/pending/object_cache.hpp @@ -57,6 +57,10 @@ private: friend struct data; }; +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable: 4702) +#endif template boost::shared_ptr object_cache::get(const Key& k, size_type l_max_cache_size) { @@ -80,6 +84,9 @@ boost::shared_ptr object_cache::get(const Key& k, siz return do_get(k, l_max_cache_size); #endif } +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif template boost::shared_ptr object_cache::do_get(const Key& k, size_type l_max_cache_size) diff --git a/include/boost/regex/v4/basic_regex.hpp b/include/boost/regex/v4/basic_regex.hpp index b3bb1fe0..c56dd8ef 100644 --- a/include/boost/regex/v4/basic_regex.hpp +++ b/include/boost/regex/v4/basic_regex.hpp @@ -70,13 +70,14 @@ void bubble_down_one(I first, I last) } } +static const int hash_value_mask = 1 << (std::numeric_limits::digits - 1); + template inline int hash_value_from_capture_name(Iterator i, Iterator j) { std::size_t r = boost::hash_range(i, j); - r %= ((std::numeric_limits::max)() - 10001); - r += 10000; - return static_cast(r); + r %= ((std::numeric_limits::max)()); + return static_cast(r) | hash_value_mask; } class named_subexpressions @@ -170,9 +171,19 @@ struct regex_data : public named_subexpressions regex_data(const ::boost::shared_ptr< ::boost::regex_traits_wrapper >& t) - : m_ptraits(t), m_expression(0), m_expression_len(0), m_disable_match_any(false) {} + : m_ptraits(t), m_flags(0), m_status(0), m_expression(0), m_expression_len(0), + m_mark_count(0), m_first_state(0), m_restart_type(0), +#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) && !(defined(BOOST_MSVC) && (BOOST_MSVC < 1900)) + m_startmap{ 0 }, +#endif + m_can_be_null(0), m_word_mask(0), m_has_recursions(false), m_disable_match_any(false) {} regex_data() - : m_ptraits(new ::boost::regex_traits_wrapper()), m_expression(0), m_expression_len(0), m_disable_match_any(false) {} + : m_ptraits(new ::boost::regex_traits_wrapper()), m_flags(0), m_status(0), m_expression(0), m_expression_len(0), + m_mark_count(0), m_first_state(0), m_restart_type(0), +#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) && !(defined(BOOST_MSVC) && (BOOST_MSVC < 1900)) + m_startmap{ 0 }, +#endif + m_can_be_null(0), m_word_mask(0), m_has_recursions(false), m_disable_match_any(false) {} ::boost::shared_ptr< ::boost::regex_traits_wrapper diff --git a/include/boost/regex/v4/basic_regex_creator.hpp b/include/boost/regex/v4/basic_regex_creator.hpp index 7c006527..f4b1660a 100644 --- a/include/boost/regex/v4/basic_regex_creator.hpp +++ b/include/boost/regex/v4/basic_regex_creator.hpp @@ -20,6 +20,8 @@ #ifndef BOOST_REGEX_V4_BASIC_REGEX_CREATOR_HPP #define BOOST_REGEX_V4_BASIC_REGEX_CREATOR_HPP +#include + #ifdef BOOST_MSVC #pragma warning(push) #pragma warning(disable: 4103) @@ -239,7 +241,7 @@ protected: bool m_icase; // true for case insensitive matches unsigned m_repeater_id; // the state_id of the next repeater bool m_has_backrefs; // true if there are actually any backrefs - unsigned m_backrefs; // bitmask of permitted backrefs + indexed_bit_flag m_backrefs; // bitmask of permitted backrefs boost::uintmax_t m_bad_repeats; // bitmask of repeats we can't deduce a startmap for; bool m_has_recursions; // set when we have recursive expresisons to fixup std::vector m_recursion_checks; // notes which recursions we've followed while analysing this expression @@ -267,7 +269,8 @@ private: template basic_regex_creator::basic_regex_creator(regex_data* data) - : m_pdata(data), m_traits(*(data->m_ptraits)), m_last_state(0), m_repeater_id(0), m_has_backrefs(false), m_backrefs(0), m_has_recursions(false) + : m_pdata(data), m_traits(*(data->m_ptraits)), m_last_state(0), m_icase(false), m_repeater_id(0), + m_has_backrefs(false), m_bad_repeats(0), m_has_recursions(false), m_word_mask(0), m_mask_space(0), m_lower_mask(0), m_upper_mask(0), m_alpha_mask(0) { m_pdata->m_data.clear(); m_pdata->m_status = ::boost::regex_constants::error_ok; @@ -591,7 +594,7 @@ re_syntax_base* basic_regex_creator::append_set( return 0; } // everything in range matches: - std::memset(result->_map + static_cast(c1), true, 1 + static_cast(c2) - static_cast(c1)); + std::memset(result->_map + static_cast(c1), true, static_cast(1u) + static_cast(static_cast(c2) - static_cast(c1))); } } // @@ -763,7 +766,7 @@ void basic_regex_creator::fixup_recursions(re_syntax_base* state) if(idx < 0) { idx = -idx-1; - if(idx >= 10000) + if(idx >= hash_value_mask) { idx = m_pdata->get_id(idx); if(idx <= 0) @@ -795,7 +798,7 @@ void basic_regex_creator::fixup_recursions(re_syntax_base* state) bool ok = false; re_syntax_base* p = base; std::ptrdiff_t idx = static_cast(state)->alt.i; - if(idx > 10000) + if(idx >= hash_value_mask) { // // There may be more than one capture group with this hash, just do what Perl @@ -1067,9 +1070,21 @@ int basic_regex_creator::calculate_backstep(re_syntax_base* state return -1; } +struct recursion_saver +{ + std::vector saved_state; + std::vector* state; + recursion_saver(std::vector* p) : saved_state(*p), state(p) {} + ~recursion_saver() + { + state->swap(saved_state); + } +}; + template void basic_regex_creator::create_startmap(re_syntax_base* state, unsigned char* l_map, unsigned int* pnull, unsigned char mask) { + recursion_saver saved_recursions(&m_recursion_checks); int not_last_jump = 1; re_syntax_base* recursion_start = 0; int recursion_sub = 0; @@ -1512,6 +1527,10 @@ void basic_regex_creator::probe_leading_repeat(re_syntax_base* st state = state->next.p; continue; } +#ifdef BOOST_MSVC +# pragma warning(push) +#pragma warning(disable:6011) +#endif if((static_cast(state)->index == -1) || (static_cast(state)->index == -2)) { @@ -1519,6 +1538,9 @@ void basic_regex_creator::probe_leading_repeat(re_syntax_base* st state = static_cast(state->next.p)->alt.p->next.p; continue; } +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif if(static_cast(state)->index == -3) { // Have to skip the leading jump state: diff --git a/include/boost/regex/v4/basic_regex_parser.hpp b/include/boost/regex/v4/basic_regex_parser.hpp index 6c7065f0..8bdb079f 100644 --- a/include/boost/regex/v4/basic_regex_parser.hpp +++ b/include/boost/regex/v4/basic_regex_parser.hpp @@ -22,6 +22,9 @@ #ifdef BOOST_MSVC #pragma warning(push) #pragma warning(disable: 4103) +#if BOOST_MSVC >= 1800 +#pragma warning(disable: 26812) +#endif #endif #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -124,7 +127,8 @@ private: template basic_regex_parser::basic_regex_parser(regex_data* data) - : basic_regex_creator(data), m_mark_count(0), m_mark_reset(-1), m_max_mark(0), m_paren_start(0), m_alt_insert_point(0), m_has_case_change(false), m_recursion_count(0) + : basic_regex_creator(data), m_parser_proc(), m_base(0), m_end(0), m_position(0), + m_mark_count(0), m_mark_reset(-1), m_max_mark(0), m_paren_start(0), m_alt_insert_point(0), m_has_case_change(false), m_recursion_count(0) { } @@ -193,7 +197,7 @@ void basic_regex_parser::parse(const charT* p1, const charT* p2, if(this->m_pdata->m_status) return; // fill in our sub-expression count: - this->m_pdata->m_mark_count = 1 + m_mark_count; + this->m_pdata->m_mark_count = 1u + (std::size_t)m_mark_count; this->finalize(p1, p2); } @@ -321,6 +325,12 @@ bool basic_regex_parser::parse_basic() return true; } +#ifdef BOOST_MSVC +# pragma warning(push) +#if BOOST_MSVC >= 1800 +#pragma warning(disable:26812) +#endif +#endif template bool basic_regex_parser::parse_extended() { @@ -409,6 +419,9 @@ bool basic_regex_parser::parse_extended() return result; } #ifdef BOOST_MSVC +# pragma warning(pop) +#endif +#ifdef BOOST_MSVC #pragma warning(pop) #endif @@ -545,8 +558,8 @@ bool basic_regex_parser::parse_open_paren() // // allow backrefs to this mark: // - if((markid > 0) && (markid < sizeof(unsigned) * CHAR_BIT)) - this->m_backrefs |= 1u << (markid - 1); + if(markid > 0) + this->m_backrefs.set(markid); return true; } @@ -859,7 +872,7 @@ escape_type_class_jump: { bool have_brace = false; bool negative = false; - static const char* incomplete_message = "Incomplete \\g escape found."; + static const char incomplete_message[] = "Incomplete \\g escape found."; if(++m_position == m_end) { fail(regex_constants::error_escape, m_position - m_base, incomplete_message); @@ -911,8 +924,8 @@ escape_type_class_jump: pc = m_position; } if(negative) - i = 1 + m_mark_count - i; - if(((i > 0) && (i < std::numeric_limits::digits) && (i - 1 < static_cast(sizeof(unsigned) * CHAR_BIT)) && (this->m_backrefs & (1u << (i-1)))) || ((i > 10000) && (this->m_pdata->get_id(i) > 0) && (this->m_pdata->get_id(i)-1 < static_cast(sizeof(unsigned) * CHAR_BIT)) && (this->m_backrefs & (1u << (this->m_pdata->get_id(i)-1))))) + i = 1 + (static_cast(m_mark_count) - i); + if(((i < hash_value_mask) && (i > 0) && (this->m_backrefs.test(i))) || ((i >= hash_value_mask) && (this->m_pdata->get_id(i) > 0) && (this->m_backrefs.test(this->m_pdata->get_id(i))))) { m_position = pc; re_brace* pb = static_cast(this->append_state(syntax_element_backref, sizeof(re_brace))); @@ -1133,7 +1146,7 @@ bool basic_regex_parser::parse_repeat(std::size_t low, std::size_ template bool basic_regex_parser::parse_repeat_range(bool isbasic) { - static const char* incomplete_message = "Missing } in quantified repetition."; + static const char incomplete_message[] = "Missing } in quantified repetition."; // // parse a repeat-range: // @@ -1339,7 +1352,7 @@ bool basic_regex_parser::parse_alt() template bool basic_regex_parser::parse_set() { - static const char* incomplete_message = "Character set declaration starting with [ terminated prematurely - either no ] was found or the set had no content."; + static const char incomplete_message[] = "Character set declaration starting with [ terminated prematurely - either no ] was found or the set had no content."; ++m_position; if(m_position == m_end) { @@ -1431,7 +1444,7 @@ bool basic_regex_parser::parse_set() template bool basic_regex_parser::parse_inner_set(basic_char_set& char_set) { - static const char* incomplete_message = "Character class declaration starting with [ terminated prematurely - either no ] was found or the set had no content."; + static const char incomplete_message[] = "Character class declaration starting with [ terminated prematurely - either no ] was found or the set had no content."; // // we have either a character class [:name:] // a collating element [.name.] @@ -1944,7 +1957,7 @@ bool basic_regex_parser::parse_backref() charT c = unescape_character(); this->append_literal(c); } - else if((i > 0) && (this->m_backrefs & (1u << (i-1)))) + else if((i > 0) && (this->m_backrefs.test(i))) { m_position = pc; re_brace* pb = static_cast(this->append_state(syntax_element_backref, sizeof(re_brace))); @@ -2132,7 +2145,7 @@ insert_recursion: // Oops not a relative recursion at all, but a (?-imsx) group: goto option_group_jump; } - v = m_mark_count + 1 - v; + v = static_cast(m_mark_count) + 1 - v; if(v <= 0) { // Rewind to start of (? sequence: @@ -2710,7 +2723,7 @@ option_group_jump: { #ifndef BOOST_NO_STD_DISTANCE if(this->flags() & regbase::save_subexpression_location) - this->m_pdata->m_subs.at(markid - 1).second = std::distance(m_base, m_position) - 1; + this->m_pdata->m_subs.at((std::size_t)markid - 1).second = std::distance(m_base, m_position) - 1; #else if(this->flags() & regbase::save_subexpression_location) this->m_pdata->m_subs.at(markid - 1).second = (m_position - m_base) - 1; @@ -2718,8 +2731,7 @@ option_group_jump: // // allow backrefs to this mark: // - if(markid < (int)(sizeof(unsigned) * CHAR_BIT)) - this->m_backrefs |= 1u << (markid - 1); + this->m_backrefs.set(markid); } return true; } @@ -2747,6 +2759,12 @@ bool basic_regex_parser::match_verb(const char* verb) return true; } +#ifdef BOOST_MSVC +# pragma warning(push) +#if BOOST_MSVC >= 1800 +#pragma warning(disable:26812) +#endif +#endif template bool basic_regex_parser::parse_perl_verb() { @@ -2915,6 +2933,9 @@ bool basic_regex_parser::parse_perl_verb() fail(regex_constants::error_perl_extension, m_position - m_base); return false; } +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif template bool basic_regex_parser::add_emacs_code(bool negate) diff --git a/include/boost/regex/v4/cpp_regex_traits.hpp b/include/boost/regex/v4/cpp_regex_traits.hpp index b7b32d8a..847f2ed7 100644 --- a/include/boost/regex/v4/cpp_regex_traits.hpp +++ b/include/boost/regex/v4/cpp_regex_traits.hpp @@ -174,7 +174,7 @@ template struct cpp_regex_traits_base { cpp_regex_traits_base(const std::locale& l) - { imbue(l); } + { (void)imbue(l); } std::locale imbue(const std::locale& l); std::locale m_locale; diff --git a/include/boost/regex/v4/indexed_bit_flag.hpp b/include/boost/regex/v4/indexed_bit_flag.hpp new file mode 100644 index 00000000..c9d32c59 --- /dev/null +++ b/include/boost/regex/v4/indexed_bit_flag.hpp @@ -0,0 +1,54 @@ +/* + * + * Copyright (c) 2020 + * John Maddock + * + * Use, modification and distribution are subject to 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) + * + */ + + /* + * LOCATION: see http://www.boost.org for most recent version. + * FILE basic_regex_parser.cpp + * VERSION see + * DESCRIPTION: Declares template class basic_regex_parser. + */ + +#include +#include + +#ifndef BOOST_REGEX_V4_INDEXED_BIT_FLAG_HPP +#define BOOST_REGEX_V4_INDEXED_BIT_FLAG_HPP + +namespace boost{ +namespace BOOST_REGEX_DETAIL_NS{ + +class indexed_bit_flag +{ + boost::uint64_t low_mask; + std::set mask_set; +public: + indexed_bit_flag() : low_mask(0) {} + void set(std::size_t i) + { + if (i < std::numeric_limits::digits - 1) + low_mask |= static_cast(1u) << i; + else + mask_set.insert(i); + } + bool test(std::size_t i) + { + if (i < std::numeric_limits::digits - 1) + return low_mask & static_cast(1u) << i ? true : false; + else + return mask_set.find(i) != mask_set.end(); + } +}; + +} // namespace BOOST_REGEX_DETAIL_NS +} // namespace boost + + +#endif diff --git a/include/boost/regex/v4/match_flags.hpp b/include/boost/regex/v4/match_flags.hpp index aa8fd532..1999ecf0 100644 --- a/include/boost/regex/v4/match_flags.hpp +++ b/include/boost/regex/v4/match_flags.hpp @@ -28,6 +28,13 @@ namespace boost{ namespace regex_constants{ #endif +#ifdef BOOST_MSVC +#pragma warning(push) +#if BOOST_MSVC >= 1800 +#pragma warning(disable : 26812) +#endif +#endif + typedef enum _match_flags { match_default = 0, @@ -143,6 +150,11 @@ using regex_constants::format_no_copy; using regex_constants::format_first_only; /*using regex_constants::format_is_if;*/ +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + + } /* namespace boost */ #endif /* __cplusplus */ #endif /* include guard */ diff --git a/include/boost/regex/v4/match_results.hpp b/include/boost/regex/v4/match_results.hpp index d88a7b16..7e509801 100644 --- a/include/boost/regex/v4/match_results.hpp +++ b/include/boost/regex/v4/match_results.hpp @@ -95,7 +95,7 @@ public: // See https://svn.boost.org/trac/boost/ticket/3632. // match_results(const match_results& m) - : m_subs(m.m_subs), m_named_subs(m.m_named_subs), m_last_closed_paren(m.m_last_closed_paren), m_is_singular(m.m_is_singular) + : m_subs(m.m_subs), m_base(), m_null(), m_named_subs(m.m_named_subs), m_last_closed_paren(m.m_last_closed_paren), m_is_singular(m.m_is_singular) { if(!m_is_singular) { diff --git a/include/boost/regex/v4/perl_matcher.hpp b/include/boost/regex/v4/perl_matcher.hpp index 663e6188..05886b08 100644 --- a/include/boost/regex/v4/perl_matcher.hpp +++ b/include/boost/regex/v4/perl_matcher.hpp @@ -27,6 +27,13 @@ #ifdef BOOST_MSVC # pragma warning(push) +#pragma warning(disable : 4251) +#if BOOST_MSVC < 1700 +# pragma warning(disable : 4231) +#endif +# if BOOST_MSVC < 1600 +# pragma warning(disable : 4660) +# endif #if BOOST_MSVC < 1910 #pragma warning(disable:4800) #endif @@ -341,6 +348,12 @@ enum saved_state_type saved_state_count = 14 }; +#ifdef BOOST_MSVC +# pragma warning(push) +#if BOOST_MSVC >= 1800 +#pragma warning(disable:26495) +#endif +#endif template struct recursion_info { @@ -352,16 +365,8 @@ struct recursion_info repeater_count* repeater_stack; iterator location_of_start; }; - #ifdef BOOST_MSVC -#pragma warning(push) -#pragma warning(disable : 4251) -#if BOOST_MSVC < 1700 -# pragma warning(disable : 4231) -#endif -# if BOOST_MSVC < 1600 -# pragma warning(disable : 4660) -# endif +# pragma warning(pop) #endif template @@ -578,6 +583,12 @@ private: unsigned m_recursions; #endif +#ifdef BOOST_MSVC +# pragma warning(push) +#if BOOST_MSVC >= 1800 +#pragma warning(disable:26495) +#endif +#endif // these operations aren't allowed, so are declared private, // bodies are provided to keep explicit-instantiation requests happy: perl_matcher& operator=(const perl_matcher&) @@ -586,14 +597,17 @@ private: } perl_matcher(const perl_matcher& that) : m_result(that.m_result), re(that.re), traits_inst(that.traits_inst), rep_obj(0) {} +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif }; -#ifdef BOOST_MSVC -#pragma warning(pop) -#endif - } // namespace BOOST_REGEX_DETAIL_NS +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif + #ifdef BOOST_MSVC #pragma warning(push) #pragma warning(disable: 4103) @@ -607,10 +621,6 @@ private: } // namespace boost -#ifdef BOOST_MSVC -# pragma warning(pop) -#endif - // // include the implementation of perl_matcher: // diff --git a/include/boost/regex/v4/perl_matcher_common.hpp b/include/boost/regex/v4/perl_matcher_common.hpp index 3c654e58..7d6ff488 100644 --- a/include/boost/regex/v4/perl_matcher_common.hpp +++ b/include/boost/regex/v4/perl_matcher_common.hpp @@ -23,6 +23,9 @@ #ifdef BOOST_MSVC #pragma warning(push) #pragma warning(disable: 4103) +#if BOOST_MSVC >= 1800 +#pragma warning(disable: 26812) +#endif #endif #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -44,7 +47,11 @@ namespace boost{ namespace BOOST_REGEX_DETAIL_NS{ -template +#ifdef BOOST_MSVC +# pragma warning(push) +#pragma warning(disable:26812) +#endif + template void perl_matcher::construct_init(const basic_regex& e, match_flag_type f) { typedef typename regex_iterator_traits::iterator_category category; @@ -94,6 +101,9 @@ void perl_matcher::construct_init(const basic_r if(e.get_data().m_disable_match_any) m_match_flags &= regex_constants::match_not_any; } +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif template void perl_matcher::estimate_max_state_count(std::random_access_iterator_tag*) @@ -609,7 +619,7 @@ bool perl_matcher::match_backref() // or PCRE. // int index = static_cast(pstate)->index; - if(index >= 10000) + if(index >= hash_value_mask) { named_subexpressions::range_type r = re.get_data().equal_range(index); BOOST_ASSERT(r.first != r.second); @@ -758,7 +768,7 @@ inline bool perl_matcher::match_assert_backref( { // Have we matched subexpression "index"? // Check if index is a hash value: - if(index >= 10000) + if(index >= hash_value_mask) { named_subexpressions::range_type r = re.get_data().equal_range(index); while(r.first != r.second) @@ -782,7 +792,7 @@ inline bool perl_matcher::match_assert_backref( // Have we recursed into subexpression "index"? // If index == 0 then check for any recursion at all, otherwise for recursion to -index-1. int idx = -(index+1); - if(idx >= 10000) + if(idx >= hash_value_mask) { named_subexpressions::range_type r = re.get_data().equal_range(idx); int stack_index = recursion_stack.empty() ? -1 : recursion_stack.back().idx; diff --git a/include/boost/regex/v4/regex_format.hpp b/include/boost/regex/v4/regex_format.hpp index b65ffcc9..33c4a5cb 100644 --- a/include/boost/regex/v4/regex_format.hpp +++ b/include/boost/regex/v4/regex_format.hpp @@ -90,6 +90,10 @@ struct trivial_format_traits } }; +#ifdef BOOST_MSVC +# pragma warning(push) +#pragma warning(disable:26812) +#endif template class basic_regex_formatter { @@ -203,6 +207,9 @@ private: basic_regex_formatter(const basic_regex_formatter&); basic_regex_formatter& operator=(const basic_regex_formatter&); }; +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif template OutputIterator basic_regex_formatter::format(ForwardIter p1, ForwardIter p2, match_flag_type f) diff --git a/include/boost/regex/v4/regex_iterator.hpp b/include/boost/regex/v4/regex_iterator.hpp index 380a9a71..bbdeed58 100644 --- a/include/boost/regex/v4/regex_iterator.hpp +++ b/include/boost/regex/v4/regex_iterator.hpp @@ -50,6 +50,8 @@ class regex_iterator_implementation public: regex_iterator_implementation(const regex_type* p, BidirectionalIterator last, match_flag_type f) : base(), end(last), re(*p), flags(f){} + regex_iterator_implementation(const regex_iterator_implementation& other) + :what(other.what), base(other.base), end(other.end), re(other.re), flags(other.flags){} bool init(BidirectionalIterator first) { base = first; diff --git a/include/boost/regex/v4/regex_token_iterator.hpp b/include/boost/regex/v4/regex_token_iterator.hpp index fde51d74..ee8a0120 100644 --- a/include/boost/regex/v4/regex_token_iterator.hpp +++ b/include/boost/regex/v4/regex_token_iterator.hpp @@ -67,16 +67,16 @@ class regex_token_iterator_implementation public: regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, int sub, match_flag_type f) - : end(last), re(*p), flags(f){ subs.push_back(sub); } + : end(last), re(*p), flags(f), N(0){ subs.push_back(sub); } regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, const std::vector& v, match_flag_type f) - : end(last), re(*p), flags(f), subs(v){} + : end(last), re(*p), flags(f), N(0), subs(v){} #if !BOOST_WORKAROUND(__HP_aCC, < 60700) #if (BOOST_WORKAROUND(__BORLANDC__, >= 0x560) && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570)))\ || BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) \ || BOOST_WORKAROUND(__HP_aCC, < 60700) template regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, const T& submatches, match_flag_type f) - : end(last), re(*p), flags(f) + : end(last), re(*p), flags(f), N(0) { // assert that T really is an array: BOOST_STATIC_ASSERT(::boost::is_array::value); @@ -89,7 +89,7 @@ public: #else template regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, const int (&submatches)[CN], match_flag_type f) - : end(last), re(*p), flags(f) + : end(last), re(*p), flags(f), N(0) { for(std::size_t i = 0; i < CN; ++i) { diff --git a/include/boost/regex/v4/regex_traits_defaults.hpp b/include/boost/regex/v4/regex_traits_defaults.hpp index e58d6bae..d08047d9 100644 --- a/include/boost/regex/v4/regex_traits_defaults.hpp +++ b/include/boost/regex/v4/regex_traits_defaults.hpp @@ -141,7 +141,7 @@ inline bool is_separator(char c) BOOST_REGEX_DECL std::string BOOST_REGEX_CALL lookup_default_collate_name(const std::string& name); // -// get the state_id of a character clasification, the individual +// get the state_id of a character classification, the individual // traits classes then transform that state_id into a bitmask: // template @@ -208,8 +208,8 @@ int get_default_class_id(const charT* p1, const charT* p2) {data+63, data+67,}, // word {data+67, data+73,}, // xdigit }; - static const character_pointer_range* ranges_begin = ranges; - static const character_pointer_range* ranges_end = ranges + (sizeof(ranges)/sizeof(ranges[0])); + const character_pointer_range* ranges_begin = ranges; + const character_pointer_range* ranges_end = ranges + (sizeof(ranges)/sizeof(ranges[0])); character_pointer_range t = { p1, p2, }; const character_pointer_range* p = std::lower_bound(ranges_begin, ranges_end, t); diff --git a/include/boost/regex/v4/w32_regex_traits.hpp b/include/boost/regex/v4/w32_regex_traits.hpp index 378ee856..f869e58a 100644 --- a/include/boost/regex/v4/w32_regex_traits.hpp +++ b/include/boost/regex/v4/w32_regex_traits.hpp @@ -546,7 +546,7 @@ typename w32_regex_traits_implementation::char_class_type if(pos != m_custom_class_names.end()) return pos->second; } - std::size_t state_id = 1 + BOOST_REGEX_DETAIL_NS::get_default_class_id(p1, p2); + std::size_t state_id = 1u + (std::size_t)BOOST_REGEX_DETAIL_NS::get_default_class_id(p1, p2); if(state_id < sizeof(masks) / sizeof(masks[0])) return masks[state_id]; return masks[0]; diff --git a/src/c_regex_traits.cpp b/src/c_regex_traits.cpp index a0b52ee4..09300666 100644 --- a/src/c_regex_traits.cpp +++ b/src/c_regex_traits.cpp @@ -157,7 +157,7 @@ c_regex_traits::char_class_type BOOST_REGEX_CALL c_regex_traits::loo s[i] = static_cast((std::tolower)(static_cast(s[i]))); idx = ::boost::BOOST_REGEX_DETAIL_NS::get_default_class_id(&*s.begin(), &*s.begin() + s.size()); } - BOOST_ASSERT(std::size_t(idx+1) < sizeof(masks) / sizeof(masks[0])); + BOOST_ASSERT(std::size_t(idx) + 1u < sizeof(masks) / sizeof(masks[0])); return masks[idx+1]; } diff --git a/src/cregex.cpp b/src/cregex.cpp index a1ae3b08..ece28204 100644 --- a/src/cregex.cpp +++ b/src/cregex.cpp @@ -70,6 +70,10 @@ inline std::string to_string(const char* i, const char* j) } namespace BOOST_REGEX_DETAIL_NS{ +#ifdef BOOST_MSVC +# pragma warning(push) +#pragma warning(disable:26812) +#endif class RegExData { public: @@ -103,6 +107,9 @@ public: #endif strings(), positions() {} }; +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif void RegExData::update() { diff --git a/src/fileiter.cpp b/src/fileiter.cpp index c80459b8..a7a759a6 100644 --- a/src/fileiter.cpp +++ b/src/fileiter.cpp @@ -112,16 +112,21 @@ void mapfile::open(const char* file) std::runtime_error err("Unable to create file mapping."); boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err); } - _first = static_cast(MapViewOfFile(hmap, FILE_MAP_READ, 0, 0, 0)); - if(_first == 0) + else { - CloseHandle(hmap); - CloseHandle(hfile); - hmap = 0; - hfile = 0; - std::runtime_error err("Unable to create file mapping."); + _first = static_cast(MapViewOfFile(hmap, FILE_MAP_READ, 0, 0, 0)); + if (_first == 0) + { + CloseHandle(hmap); + CloseHandle(hfile); + hmap = 0; + hfile = 0; + std::runtime_error err("Unable to create file mapping."); + boost::BOOST_REGEX_DETAIL_NS::raise_runtime_error(err); + } + else + _last = _first + GetFileSize(hfile, 0); } - _last = _first + GetFileSize(hfile, 0); } else { diff --git a/src/icu.cpp b/src/icu.cpp index 5f249e2d..cb11f323 100644 --- a/src/icu.cpp +++ b/src/icu.cpp @@ -354,8 +354,8 @@ icu_regex_traits::char_class_type icu_regex_traits::lookup_icu_mask(const ::UCha }; - static const BOOST_REGEX_DETAIL_NS::character_pointer_range< ::UChar32>* ranges_begin = range_data; - static const BOOST_REGEX_DETAIL_NS::character_pointer_range< ::UChar32>* ranges_end = range_data + (sizeof(range_data)/sizeof(range_data[0])); + const BOOST_REGEX_DETAIL_NS::character_pointer_range< ::UChar32>* ranges_begin = range_data; + const BOOST_REGEX_DETAIL_NS::character_pointer_range< ::UChar32>* ranges_end = range_data + (sizeof(range_data)/sizeof(range_data[0])); BOOST_REGEX_DETAIL_NS::character_pointer_range< ::UChar32> t = { p1, p2, }; const BOOST_REGEX_DETAIL_NS::character_pointer_range< ::UChar32>* p = std::lower_bound(ranges_begin, ranges_end, t); diff --git a/src/posix_api.cpp b/src/posix_api.cpp index 1531d948..47133fa0 100644 --- a/src/posix_api.cpp +++ b/src/posix_api.cpp @@ -66,6 +66,10 @@ const char* names[] = { typedef boost::basic_regex > c_regex_type; +#ifdef BOOST_MSVC +# pragma warning(push) +#pragma warning(disable:26812) +#endif BOOST_REGEX_DECL int BOOST_REGEX_CCALL regcompA(regex_tA* expression, const char* ptr, int f) { #ifndef BOOST_NO_EXCEPTIONS @@ -140,6 +144,9 @@ BOOST_REGEX_DECL int BOOST_REGEX_CCALL regcompA(regex_tA* expression, const char return result; } +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorA(int code, const regex_tA* e, char* buf, regsize_t buf_size) { diff --git a/src/regex.cpp b/src/regex.cpp index 5a8bbdc0..ee0204cc 100644 --- a/src/regex.cpp +++ b/src/regex.cpp @@ -72,7 +72,7 @@ regex_error::regex_error(regex_constants::error_type err) { } -regex_error::~regex_error() throw() +regex_error::~regex_error() BOOST_NOEXCEPT_OR_NOTHROW { } diff --git a/src/regex_traits_defaults.cpp b/src/regex_traits_defaults.cpp index 0b66c68d..5ac46d2d 100644 --- a/src/regex_traits_defaults.cpp +++ b/src/regex_traits_defaults.cpp @@ -193,7 +193,7 @@ BOOST_REGEX_DECL bool BOOST_REGEX_CALL is_combining_implementation(boost::uint_l // // these are the POSIX collating names: // -BOOST_REGEX_DECL const char* def_coll_names[] = { +static const char* def_coll_names[] = { "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "alert", "backspace", "tab", "newline", "vertical-tab", "form-feed", "carriage-return", "SO", "SI", "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB", "CAN", "EM", "SUB", "ESC", "IS4", "IS3", "IS2", "IS1", "space", "exclamation-mark", @@ -214,7 +214,7 @@ BOOST_REGEX_DECL const char* def_coll_names[] = { // little more - but this will have to do for // now: -BOOST_REGEX_DECL const char* def_multi_coll[] = { +static const char* def_multi_coll[] = { "ae", "Ae", "AE", diff --git a/src/wide_posix_api.cpp b/src/wide_posix_api.cpp index bc1c0af2..c675104b 100644 --- a/src/wide_posix_api.cpp +++ b/src/wide_posix_api.cpp @@ -76,6 +76,10 @@ const wchar_t* wnames[] = { typedef boost::basic_regex > wc_regex_type; +#ifdef BOOST_MSVC +# pragma warning(push) +#pragma warning(disable:26812) +#endif BOOST_REGEX_DECL int BOOST_REGEX_CCALL regcompW(regex_tW* expression, const wchar_t* ptr, int f) { #ifndef BOOST_NO_EXCEPTIONS @@ -150,6 +154,9 @@ BOOST_REGEX_DECL int BOOST_REGEX_CCALL regcompW(regex_tW* expression, const wcha return result; } +#ifdef BOOST_MSVC +# pragma warning(pop) +#endif BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorW(int code, const regex_tW* e, wchar_t* buf, regsize_t buf_size) { diff --git a/test/regress/info.hpp b/test/regress/info.hpp index 5c08961e..beca8e5d 100644 --- a/test/regress/info.hpp +++ b/test/regress/info.hpp @@ -112,7 +112,7 @@ private: boost::call_once(f,&init_data); return do_get_data(); #else - static data_type d; + static data_type d = {}; return d; #endif } diff --git a/test/regress/main.cpp b/test/regress/main.cpp index e3e3dd7f..87ad9ff4 100644 --- a/test/regress/main.cpp +++ b/test/regress/main.cpp @@ -139,10 +139,10 @@ int cpp_main(int /*argc*/, char * /*argv*/[]) int* get_array_data() { - static boost::thread_specific_ptr > tp; + static boost::thread_specific_ptr > tp; if(tp.get() == 0) - tp.reset(new boost::array); + tp.reset(new boost::array); return tp.get()->data(); } @@ -160,9 +160,9 @@ const int* make_array(int first, ...) #ifdef TEST_THREADS int* data = get_array_data(); #else - static int data[200]; + static int data[800]; #endif - std::fill_n(data, 200, -2); + std::fill_n(data, 800, -2); va_list ap; va_start(ap, first); // diff --git a/test/regress/test.hpp b/test/regress/test.hpp index d9224e8e..e350990b 100644 --- a/test/regress/test.hpp +++ b/test/regress/test.hpp @@ -99,7 +99,7 @@ void do_test(const charT& c, const tagT& tag) boost::call_once(f, proc); #endif if(test_locale::cpp_locale_state() == test_locale::test_with_locale) - e1.imbue(test_locale::cpp_locale()); + (void)e1.imbue(test_locale::cpp_locale()); if(test_locale::cpp_locale_state() != test_locale::no_test) test(e1, tag); #endif diff --git a/test/regress/test_backrefs.cpp b/test/regress/test_backrefs.cpp index 58f4dedb..be9f54ca 100644 --- a/test/regress/test_backrefs.cpp +++ b/test/regress/test_backrefs.cpp @@ -103,5 +103,10 @@ void test_backrefs() TEST_REGEX_SEARCH("a(?'foo'(?'bar'(?'bb'(?'aa'b*))))c\\g{foo}d", perl, "abbcbbbd", match_default, make_array(-2, -2)); TEST_REGEX_SEARCH("^(?'foo'.)\\g{foo}", perl, "abc", match_default, make_array(-2, -2)); TEST_REGEX_SEARCH("a(?'foo'[bc])\\g{foo}d", perl, "abcdabbd", match_default, make_array(4, 8, 5, 6, -2, -2)); + + // Bug cases from https://github.com/boostorg/regex/issues/75 + TEST_REGEX_SEARCH("(?:(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)\\g{-1}|WORKING)", perl, "WORKING", match_default, make_array(0, 7, -2, -2)); + TEST_REGEX_SEARCH("(?:(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)(z)\\g{-1}|WORKING)", perl, "WORKING", match_default, make_array(0, 7, -2, -2)); + } diff --git a/test/regress/test_perl_ex.cpp b/test/regress/test_perl_ex.cpp index 6a53256d..2a7310cd 100644 --- a/test/regress/test_perl_ex.cpp +++ b/test/regress/test_perl_ex.cpp @@ -935,6 +935,7 @@ void test_recursion() TEST_REGEX_SEARCH("namespace\\s+(\\w+)\\s+(\\{(?:[^{}]*(?:(?2)[^{}]*)*)?\\})", perl, "namespace one { namespace two { int foo(){} } { {{{ } } } } {}}", match_default, make_array(0, 64, 10, 13, 14, 64, -2, -2)); TEST_INVALID_REGEX("((?1)|a)", perl); TEST_REGEX_SEARCH("a(?0)?", perl, "aaaaa", match_default, make_array(0, 5, -2, -2)); + TEST_REGEX_SEARCH("((?(DEFINE)(?'a'A)(?'b'(?&a)?(?&a)))(?&b)?)", perl, "AA", match_default, make_array(0, 2, 0, 2, -1, -1, -2, 2, 2, 2, 2, -1, -1, -2, -2)); // Recursion to a named sub with a name that is used multiple times: TEST_REGEX_SEARCH("(?:(?a+)|(?b+))\\.(?&A)", perl, "aaaa.aa", match_default, make_array(0, 7, 0, 4, -1, -1, -2, -2));