From 1931c4306a38cb60ea6fbfefd238302909e57d42 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Thu, 28 Mar 2019 17:30:23 +0000 Subject: [PATCH] Fix PR#35967: ' syntax_option_type is not a proper bitmask' Sadly, this is an ABI break, so it's only available if you define either '_LIBCPP_ABI_VERSION > 2' or '_LIBCPP_ABI_UNSTABLE' or '_LIBCPP_ABI_REGEX_CONSTANTS_NONZERO' and rebuild your dylib. llvm-svn: 357190 --- libcxx/include/__config | 2 + libcxx/include/regex | 56 +++++++++++++++++----- .../re.const/re.synopt/syntax_option_type.pass.cpp | 4 ++ .../re.regex/re.regex.construct/default.pass.cpp | 2 +- 4 files changed, 51 insertions(+), 13 deletions(-) diff --git a/libcxx/include/__config b/libcxx/include/__config index b9423703..a7d0b14 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -100,6 +100,8 @@ # define _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION // Unstable attempt to provide a more optimized std::function # define _LIBCPP_ABI_OPTIMIZED_FUNCTION +// All the regex constants must be distinct and nonzero. +# define _LIBCPP_ABI_REGEX_CONSTANTS_NONZERO #elif _LIBCPP_ABI_VERSION == 1 # if !defined(_LIBCPP_OBJECT_FORMAT_COFF) // Enable compiling copies of now inline methods into the dylib to support diff --git a/libcxx/include/regex b/libcxx/include/regex index c381b51..b9aa9d6 100644 --- a/libcxx/include/regex +++ b/libcxx/include/regex @@ -793,7 +793,11 @@ enum syntax_option_type nosubs = 1 << 1, optimize = 1 << 2, collate = 1 << 3, +#ifdef _LIBCPP_ABI_REGEX_CONSTANTS_NONZERO + ECMAScript = 1 << 9, +#else ECMAScript = 0, +#endif basic = 1 << 4, extended = 1 << 5, awk = 1 << 6, @@ -801,6 +805,16 @@ enum syntax_option_type egrep = 1 << 8 }; +inline _LIBCPP_CONSTEXPR +syntax_option_type __get_grammar(syntax_option_type __g) +{ +#ifdef _LIBCPP_ABI_REGEX_CONSTANTS_NONZERO + return static_cast(__g & 0x3F0); +#else + return static_cast(__g & 0x1F0); +#endif +} + inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR syntax_option_type @@ -2526,19 +2540,27 @@ public: // construct/copy/destroy: _LIBCPP_INLINE_VISIBILITY basic_regex() - : __flags_(), __marked_count_(0), __loop_count_(0), __open_count_(0), + : __flags_(regex_constants::ECMAScript), __marked_count_(0), __loop_count_(0), __open_count_(0), __end_(0) {} _LIBCPP_INLINE_VISIBILITY explicit basic_regex(const value_type* __p, flag_type __f = regex_constants::ECMAScript) : __flags_(__f), __marked_count_(0), __loop_count_(0), __open_count_(0), __end_(0) - {__parse(__p, __p + __traits_.length(__p));} + { + if (__get_grammar(__flags_) == 0) __flags_ |= regex_constants::ECMAScript; + __parse(__p, __p + __traits_.length(__p)); + } + _LIBCPP_INLINE_VISIBILITY basic_regex(const value_type* __p, size_t __len, flag_type __f = regex_constants::ECMAScript) : __flags_(__f), __marked_count_(0), __loop_count_(0), __open_count_(0), __end_(0) - {__parse(__p, __p + __len);} + { + if (__get_grammar(__flags_) == 0) __flags_ |= regex_constants::ECMAScript; + __parse(__p, __p + __len); + } + // basic_regex(const basic_regex&) = default; // basic_regex(basic_regex&&) = default; template @@ -2547,21 +2569,31 @@ public: flag_type __f = regex_constants::ECMAScript) : __flags_(__f), __marked_count_(0), __loop_count_(0), __open_count_(0), __end_(0) - {__parse(__p.begin(), __p.end());} + { + if (__get_grammar(__flags_) == 0) __flags_ |= regex_constants::ECMAScript; + __parse(__p.begin(), __p.end()); + } + template _LIBCPP_INLINE_VISIBILITY basic_regex(_ForwardIterator __first, _ForwardIterator __last, flag_type __f = regex_constants::ECMAScript) : __flags_(__f), __marked_count_(0), __loop_count_(0), __open_count_(0), __end_(0) - {__parse(__first, __last);} + { + if (__get_grammar(__flags_) == 0) __flags_ |= regex_constants::ECMAScript; + __parse(__first, __last); + } #ifndef _LIBCPP_CXX03_LANG _LIBCPP_INLINE_VISIBILITY basic_regex(initializer_list __il, flag_type __f = regex_constants::ECMAScript) : __flags_(__f), __marked_count_(0), __loop_count_(0), __open_count_(0), __end_(0) - {__parse(__il.begin(), __il.end());} + { + if (__get_grammar(__flags_) == 0) __flags_ |= regex_constants::ECMAScript; + __parse(__il.begin(), __il.end()); + } #endif // _LIBCPP_CXX03_LANG // ~basic_regex() = default; @@ -3043,7 +3075,7 @@ basic_regex<_CharT, _Traits>::__parse(_ForwardIterator __first, __h.release(); __end_ = __start_.get(); } - switch (__flags_ & 0x1F0) + switch (__get_grammar(__flags_)) { case ECMAScript: __first = __parse_ecma_exp(__first, __last); @@ -3512,7 +3544,7 @@ basic_regex<_CharT, _Traits>::__parse_QUOTED_CHAR_ERE(_ForwardIterator __first, __first = ++__temp; break; default: - if ((__flags_ & 0x1F0) == awk) + if (__get_grammar(__flags_) == awk) __first = __parse_awk_escape(++__first, __last); break; } @@ -3596,7 +3628,7 @@ basic_regex<_CharT, _Traits>::__parse_ERE_dupl_symbol(_ForwardIterator __first, { if (__first != __last) { - unsigned __grammar = __flags_ & 0x1F0; + unsigned __grammar = __get_grammar(__flags_); switch (*__first) { case '*': @@ -3717,7 +3749,7 @@ basic_regex<_CharT, _Traits>::__parse_bracket_expression(_ForwardIterator __firs // __ml owned by *this if (__first == __last) __throw_regex_error(); - if ((__flags_ & 0x1F0) != ECMAScript && *__first == ']') + if (__get_grammar(__flags_) != ECMAScript && *__first == ']') { __ml->__add_char(']'); ++__first; @@ -3778,7 +3810,7 @@ basic_regex<_CharT, _Traits>::__parse_expression_term(_ForwardIterator __first, else if (*__temp == '.') __first = __parse_collating_symbol(++__temp, __last, __start_range); } - unsigned __grammar = __flags_ & 0x1F0; + unsigned __grammar = __get_grammar(__flags_); if (__start_range.empty()) { if ((__grammar == ECMAScript || __grammar == awk) && *__first == '\\') @@ -5848,7 +5880,7 @@ basic_regex<_CharT, _Traits>::__match_at_start( match_results& __m, regex_constants::match_flag_type __flags, bool __at_first) const { - if ((__flags_ & 0x1F0) == ECMAScript) + if (__get_grammar(__flags_) == ECMAScript) return __match_at_start_ecma(__first, __last, __m, __flags, __at_first); if (mark_count() == 0) return __match_at_start_posix_nosubs(__first, __last, __m, __flags, __at_first); diff --git a/libcxx/test/std/re/re.const/re.synopt/syntax_option_type.pass.cpp b/libcxx/test/std/re/re.const/re.synopt/syntax_option_type.pass.cpp index 49ce2b5..c34da53 100644 --- a/libcxx/test/std/re/re.const/re.synopt/syntax_option_type.pass.cpp +++ b/libcxx/test/std/re/re.const/re.synopt/syntax_option_type.pass.cpp @@ -38,7 +38,11 @@ int main(int, char**) assert(std::regex_constants::nosubs != 0); assert(std::regex_constants::optimize != 0); assert(std::regex_constants::collate != 0); +#ifdef _LIBCPP_ABI_REGEX_CONSTANTS_NONZERO // https://bugs.llvm.org/show_bug.cgi?id=35967 + assert(std::regex_constants::ECMAScript != 0); +#else assert(std::regex_constants::ECMAScript == 0); +#endif assert(std::regex_constants::basic != 0); assert(std::regex_constants::extended != 0); assert(std::regex_constants::awk != 0); diff --git a/libcxx/test/std/re/re.regex/re.regex.construct/default.pass.cpp b/libcxx/test/std/re/re.regex/re.regex.construct/default.pass.cpp index f706229..9705d70 100644 --- a/libcxx/test/std/re/re.regex/re.regex.construct/default.pass.cpp +++ b/libcxx/test/std/re/re.regex/re.regex.construct/default.pass.cpp @@ -21,7 +21,7 @@ void test() { std::basic_regex r; - assert(r.flags() == 0); + assert(r.flags() == std::regex_constants::ECMAScript); assert(r.mark_count() == 0); } -- 2.7.4