<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/92586>92586</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
bits/unicode.h from GCC 14.1.1 stdlibc++ errors
</td>
</tr>
<tr>
<th>Labels</th>
<td>
libc++
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
KyunLFA
</td>
</tr>
</table>
<pre>
Something has regressed from the day before yesterday to today as of 621d0f3e86ecc46c2df302041777e42dfc10171e which I compiled from git and passed all Clang and LLD tests which I run every time.
I compiled Mesa successfully. However, the PCSX2 emulator no longer compiles, not crashing the compiler but instead producing a compilation error, not inside PCSX2, but in GCC's stdlib++'s unicode.h, located on Arch Linux bases on /usr/include/c++/14.1.1/bits/unicode.h.
The error reads:
```
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.1.1/../../../../include/c++/14.1.1/bits/unicode.h:807:4: error: expression is not assignable
807 | ++this;
```
Version 18.1.5 of LLVM Clang (latest stable I have on CachyOS Linux) does not suffer from this error. Reverting to that version no longer produces the error. Going back to LLVM Clang git 621d0f3 introduces the error again.
Here's the offending excerpt from unicode.h:
```
inline namespace __v15_1_0
{
#define _GLIBCXX_GET_UNICODE_DATA 150100
#include "unicode-data.h"
#ifdef _GLIBCXX_GET_UNICODE_DATA
# error "Invalid unicode data"
#endif
// The field width of a code point.
constexpr int
__field_width(char32_t __c) noexcept
{
if (__c < __width_edges[0]) [[likely]]
return 1;
auto* __p = std::upper_bound(__width_edges, std::end(__width_edges), __c);
return (__p - __width_edges) % 2 + 1;
}
// @pre c <= 0x10FFFF
constexpr _Gcb_property
__grapheme_cluster_break_property(char32_t __c) noexcept
{
constexpr uint32_t __mask = (1 << __gcb_shift_bits) - 1;
auto* __end = std::end(__gcb_edges);
auto* __p = std::lower_bound(__gcb_edges, __end,
(__c << __gcb_shift_bits) | __mask);
return _Gcb_property(__p[-1] & __mask);
}
constexpr bool
__is_incb_linker(char32_t __c) noexcept
{
const auto __end = std::end(__incb_linkers);
// Array is small enough that linear search is faster than binary search.
return std::find(__incb_linkers, __end, __c) != __end;
}
// @pre c <= 0x10FFFF
constexpr _InCB
__incb_property(char32_t __c) noexcept
{
if ((__c << 2) < __incb_edges[0]) [[likely]]
return _InCB(0);
constexpr uint32_t __mask = 0x3;
auto* __end = std::end(__incb_edges);
auto* __p = std::lower_bound(__incb_edges, __end, (__c << 2) | __mask);
return _InCB(__p[-1] & __mask);
}
constexpr bool
__is_extended_pictographic(char32_t __c)
{
if (__c < __xpicto_edges[0]) [[likely]]
return 0;
auto* __p = std::upper_bound(__xpicto_edges, std::end(__xpicto_edges), __c);
return (__p - __xpicto_edges) % 2;
}
struct _Grapheme_cluster_iterator_base
{
char32_t _M_c; // First code point in the cluster.
_Gcb_property _M_prop; // GCB property of _M_c.
enum class _XPicto : unsigned char { _Init, _Zwj, _Matched, _Failed };
_XPicto _M_xpicto_seq_state = _XPicto::_Init;
unsigned char _M_RI_count = 0;
bool _M_incb_linker_seen = false;
constexpr void
_M_reset(char32_t __c, _Gcb_property __p)
{
_M_c = __c;
_M_prop = __p;
_M_xpicto_seq_state = _XPicto::_Init;
_M_RI_count = 0;
_M_incb_linker_seen = false;
}
constexpr void
_M_update_xpicto_seq_state(char32_t __c, _Gcb_property __p)
{
if (_M_xpicto_seq_state == _XPicto::_Failed)
return;
auto __next_state = _XPicto::_Failed;
if (_M_xpicto_seq_state != _XPicto::_Zwj) // i.e. Init or Matched
{
if (__p == _Gcb_property::_Gcb_ZWJ)
{
if (_M_xpicto_seq_state == _XPicto::_Matched)
__next_state = _XPicto::_Zwj;
// We check _M_c here so that we do the lookup at most once,
// and only for clusters containing at least one ZWJ.
else if (__is_extended_pictographic(_M_c))
__next_state = _XPicto::_Zwj;
}
else if (__p == _Gcb_property::_Gcb_Extend)
__next_state = _M_xpicto_seq_state; // no change
}
else // Zwj
{
// This assumes that all \p{Extended_Pictographic} emoji have
// Grapheme_Cluster_Break=Other.
if (__p == _Gcb_property::_Gcb_Other
&& __is_extended_pictographic(__c))
__next_state = _XPicto::_Matched;
}
_M_xpicto_seq_state = __next_state;
}
constexpr void
_M_update_ri_count(_Gcb_property __p)
{
if (__p == _Gcb_property::_Gcb_Regional_Indicator)
++_M_RI_count;
else
_M_RI_count = 0;
}
constexpr void
_M_update_incb_state(char32_t __c, _Gcb_property)
{
if (__is_incb_linker(__c))
_M_incb_linker_seen = true;
}
};
// Split a range into extended grapheme clusters.
template<ranges::forward_range _View> requires ranges::view<_View>
class _Grapheme_cluster_view
: public ranges::view_interface<_Grapheme_cluster_view<_View>>
{
public:
constexpr
_Grapheme_cluster_view(_View __v)
: _M_begin(_Utf32_view<_View>(std::move(__v)).begin())
{ }
constexpr auto begin() const { return _M_begin; }
constexpr auto end() const { return _M_begin.end(); }
private:
struct _Iterator : private _Grapheme_cluster_iterator_base
{
private:
// Iterator over the underlying code points.
using _U32_iterator = ranges::iterator_t<_Utf32_view<_View>>;
public:
// TODO: Change value_type to be subrange<_U32_iterator> instead?
// Alternatively, value_type could be _Utf32_view<iterator_t<_View>>.
// That would be the whole cluster, not just the first code point.
// Would need to store two iterators and find end of current cluster
// on increment, so operator* returns value_type(_M_base, _M_next).
using value_type = char32_t;
using iterator_concept = forward_iterator_tag;
using difference_type = ptrdiff_t;
constexpr
_Iterator(_U32_iterator __i)
: _M_base(__i)
{
if (__i != __i.end())
{
_M_c = *__i;
_M_prop = __grapheme_cluster_break_property(_M_c);
}
}
// The first code point of the current extended grapheme cluster.
constexpr value_type
operator*() const
{ return _M_c; }
constexpr auto
operator->() const
{ return &_M_c; }
// Move to the next extended grapheme cluster.
constexpr _Iterator&
operator++()
{
const auto __end = _M_base.end();
if (_M_base != __end)
{
auto __p_prev = _M_prop;
auto __it = _M_base;
while (++__it != __end)
{
char32_t __c = *__it;
auto __p = __grapheme_cluster_break_property(*__it);
_M_update_xpicto_seq_state(__c, __p);
_M_update_ri_count(__p);
_M_update_incb_state(__c, __p);
if (_M_is_break(__p_prev, __p, __it))
{
// Found a grapheme cluster break
_M_reset(__c, __p);
break;
}
__p_prev = __p;
}
_M_base = __it;
}
return *this;
}
constexpr _Iterator
operator++(int)
{
auto __tmp = *this;
++this; \\ crashes here **(annotated here for the sake of the issue)**
return __tmp;
}
constexpr bool
operator==(const _Iterator& __i) const
{ return _M_base == __i._M_base; }
// This supports iter != iter.end()
constexpr bool
operator==(const ranges::sentinel_t<_View>& __i) const
{ return _M_base == __i; }
// Iterator to the start of the current cluster.
constexpr auto base() const { return _M_base.base(); }
// The end of the underlying view (not the end of the current cluster!)
constexpr auto end() const { return _M_base.end(); }
// Field width of the first code point in the cluster.
constexpr int
width() const noexcept
{ return __field_width(_M_c); }
private:
_U32_iterator _M_base;
// Implement the Grapheme Cluster Boundary Rules from Unicode Annex #29
// http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundary_Rules
// This implements the rules from TR29 revision 43 in Unicode 15.1.0.
// Return true if there is a break between code point with property p1
// and code point with property p2.
constexpr bool
_M_is_break(_Gcb_property __p1, _Gcb_property __p2,
_U32_iterator __curr) const
{
using enum _Gcb_property;
if (__p1 == _Gcb_Control || __p1 == _Gcb_LF)
return true; // Break after Control or LF.
if (__p1 == _Gcb_CR)
return __p2 != _Gcb_LF; // Do not break between a CR and LF.
// Rule GB5
if (__p2 == _Gcb_Control || __p2 == _Gcb_CR || __p2 == _Gcb_LF)
return true; // Break before Control, CR or LF.
// Rule GB6
if (__p1 == _Gcb_L)
switch (__p2)
{
case _Gcb_L:
case _Gcb_V:
case _Gcb_LV:
case _Gcb_LVT:
return false; // Do not break Hangul syllable sequences.
default:
return true;
}
// Rule GB7
if (__p1 == _Gcb_LV || __p1 == _Gcb_V)
switch (__p2)
{
case _Gcb_V:
case _Gcb_T:
return false; // Do not break Hangul syllable sequences.
default:
return true;
}
// Rule GB8
if (__p1 == _Gcb_LVT || __p1 == _Gcb_T)
return __p2 != _Gcb_T; // Do not break Hangul syllable sequences.
// Rule GB9
if (__p2 == _Gcb_Extend || __p2 == _Gcb_ZWJ)
return false; // Do not break before extending characters or ZWJ.
// The following GB9x rules only apply to extended grapheme clusters,
// which is what the C++ standard uses (not legacy grapheme clusters).
// Rule GB9a
if (__p2 == _Gcb_SpacingMark)
return false; // Do not break before SpacingMarks,
// Rule GB9b
if (__p1 == _Gcb_Prepend)
return false; // or after Prepend characters.
// Rule GB9c (Unicode 15.1.0)
// Do not break within certain combinations with
// Indic_Conjunct_Break (InCB)=Linker.
if (_M_incb_linker_seen
&& __incb_property(_M_c) == _InCB::_Consonant
&& __incb_property(*__curr) == _InCB::_Consonant)
{
// Match [_M_base, __curr] against regular expression
// Consonant ([Extend Linker]* Linker [Extend Linker]* Consonant)+
bool __have_linker = false;
auto __it = _M_base;
while (++__it != __curr)
{
if (__is_incb_linker(*__it))
__have_linker = true;
else
{
auto __incb = __incb_property(*__it);
if (__incb == _InCB::_Consonant)
__have_linker = false;
else if (__incb != _InCB::_Extend)
break;
}
}
if (__it == __curr && __have_linker)
return false;
}
// Rule GB11
// Do not break within emoji modifier sequences
// or emoji zwj sequences.
if (__p1 == _Gcb_ZWJ && _M_xpicto_seq_state == _XPicto::_Matched)
return false;
// Rules GB12 and GB13
// Do not break within emoji flag sequences. That is, do not break
// between regional indicator (RI) symbols if there is an odd number
// of RI characters before the break point.
if (__p1 == _Gcb_property::_Gcb_Regional_Indicator && __p1 == __p2)
return (_M_RI_count & 1) == 0;
// Rule GB999
return true; // Otherwise, break everywhere.
}
};
_Iterator _M_begin;
};
} // namespace __v15_1_0
```
My flags:
CFLAGS: "-flto=full -march=znver4 -O3 -pipe -fno-plt -fexceptions -Wp,-D_FORTIFY_SOURCE=3 -Wformat -Werror=format-security -fstack-protector-all --param=ssp-buffer-size=4 -fcf-protection -fno-semantic-interposition -Wno-unused-command-line-argument -fplugin=/usr/lib/LLVMPolly.so -mllvm -polly -fwhole-program-vtables -pthread -fopenmp -mllvm -polly-parallel -mllvm -polly-omp-backend=LLVM -mllvm -polly-num-threads=24 -mllvm -polly-vectorizer=stripmine -mllvm -polly-position=before-vectorizer -fopenmp-extensions -foffload-lto=full -funified-lto -foptimize-sibling-calls -funroll-loops -fstrict-aliasing -fstrict-aliasing -fstrict-vtable-pointers -fslp-vectorize -fvectorize -mllvm -polly-reschedule -mllvm -polly-tc-opt -mllvm -polly-tiling -mllvm -polly-2nd-level-tiling -mllvm -polly-matmul-opt -mllvm -polly-optimized-scops -mllvm -polly-pattern-matching-based-opts -mllvm -polly-postopts -mllvm -polly-register-tiling -fPIE -fPIC"
CXXFLAGS: "$CFLAGS -Wp,-D_GLIBCXX_ASSERTIONS"
LDFLAGS: "-v -fuse-ld=lld -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now,--threads=24,--lto-O3,--lto-CGO3,-lpthread,-lgomp,-z,pack-relative-relocs"
(PCSX2 and most programs I compile do compile and work correctly with these flags)
Can anyone confirm at the least that PCSX2 doesn't compile for you as well on git HEAD of LLVM? Thanks.
My system info:
Kernel: 6.9.0-GIT (patched)
Distro: CachyOS
AMD Ryzen 9 7900X
2x48GB 6800MT/s DDR5
LLVM 621d0f3e86ecc46c2df302041777e42dfc10171e
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy0PFtT4zjWv8b9csqpxCZAHvoBkg7DLmxP0Ux3f_PiUuzjRIMieSQ5If3rv5Lki-w4ge7ZraIgsaWjc79JgihF1xzxYzC9DaaLD6TUGyE__vtQ8oflzYeVyA4fv4gt6g3la9gQBRLXEpXCDHIptqA3CBk5wApzIREOqDRK80AL0MJ8IApEDpfRJBvnMV5fYppeXKZRlsfjaHwxubq6wosoy9PJeHI1QdhvaLqBe0jFtqCsXmZNNRCeQUHs0oQxmDPC1_bhw8MCNCqtmsmy5IA7lAfQdIujYLwIxjfutwf5ERUBVaYpKpWXjB1G8JvYm3lBNLeU_T7_8j0C3JaMaCGBC2CCr1HWMJQZyIWGVBJlWWRmVS8lrEoNlCuNJINCiqxMzRBSDSCaCg4opZA1GMoVzaplzTMHAO7m8yC6UqB0xugqiG7tz5WCktNUZDjamMFMpERjBoLDjUw38EB5-QorolCZZ0G0LJUMoiXlKSszDKJlWoNaTi5Gk9EkiJYrqpUZWQPu8O55gw5fkEgyFcTV8-ByXP24r_VKK8qDaDkaBdGS0dXlRRAt12kaRMvX68vk8iIs0pAZJMM1L30k7Izer5_COohvrsdXQXxzEcQ3FYvNh9fC6K5hO1WW4U7_yYqhQx3genwFwdUc3CJ6Q1UQ3w6TaX9_RWkBTq5Hk9HUqPrDw9fHSjuD6JoRo5qgtFkE7mFDdmjEMSfp5vD5i5NSEM0gE-hwUmWeo6zNiyqH_wiejGZqq2QC9IZo2FVrt3rptAyV1cNq3p0wc1YkfTETPeyMUVV2CZTro6lA1oTyjgb8hhKt5plBIs-RZwY4vqYoC-1w9qXgz-2xj3JGOQInW1QFSRGSZDeZJpOkZu9VzfYozjA3Y5O7h_vb-ffvyd2n5-SP_9zPPy8-JYub5xuYTMeTcaN-caUsEERRhU2YEU2MnUTtoDzD_DTMZlzFjCCK7vmOMJrVFIKB6UM03Mh9ksFYXRAtwVhOTpFlsKeZ3hg1MW4gQygE5XpUD0-FcRevhTQCqR8miZ2a2KlBdJ1uiIyjREOSpEZzuDD8L5rxDecAAGhutDBJUgjiOSQOSILZGlUwvR0H04UBYd3_LaMvyA7m0XTRQgCQqEvJYdJaQvOSlFoE0Q0kSQFBvDAuyog9vimLAmWyEiXP7Pr-utG8HYdD72dmiKOuWdNDxE4oIIT-NAiiKUTGdj1kDUMWg1IJLsaFRLCsMciPXyfj5XK5rIa1wkju0lVSSFGg1IdWLGtJig1uMUlZaeJespJIXtqBPymqdr2Scl1N2xL1YjkbRNcTh6hhzTpdJWpDc5043zeDsEOyLxnkWVc2Nc8NkIbjw3N7UmVi35GqB2HuVgqiec3rWfPjqeAp9I3PddSeEHpXBlYDgultOAmmhjeXg5P7gm85vBKCtYKkKqE8XSWM8hcT_X9CbhakZdg5TnvQj5hdKeONlORg4pLamvQGuSjXG-fnjaMkEhQSE9epgpwYdTMvOawoJ_JQvRwdsa1BJaeDuLRiq2kNoomhwT3-x0bkW9E9n996TOddgb7B8wGv1tWqyCJv1cuC_iUf53CMrse-lN5rouPX-GdN0MP0V23QB-FJc4g5b9pYRf07bOtIHc7YFr5q5BlmSUFTLazXpOmxxE8Lug1frxbEr8l23Bfou4NXZ9Wh6NUd8P7w1Zvn4tc5o1NalqmG5K4feqhGaYqUxCT8w-Gl4fZjkgbxbW3ASyqV9pIRU3HYMsZB9lxKxwUbMOazB-lufgvNa5HbhbzpyMstpIwoBcn33w3hYLLyktsaNLMIGpSNGlJtefjn_i_795HodIPOSy2Jrd4Ma3zm1iCTx5qrCv9OlCYarXCr905uboVmeheF5DF5uk9SUXLtzLqzjtFuM8Rzo4lC5HZoTpjCs35jJ2jmIf2YSFSoj4xh3md2UrQWAj3JWjipo9KKtvfKQKneFu3bX2FUDfEUf97HF0fA4l1MSh6TssiIxiNk_wHPKq8yzIBjHjiNa2AF45mz5AFBQ50KcHzVJ5laAeyy9QxSVUTuwLCmMatNj45wBEZWICTU1tLkYU0pNZ61LrVoiO1kVg66efTnt3_5NHdYWH0_i_UQKxtDnvlZ4hvsMqTG_YUrwr8hpBtMX5wJbFAiqKo83iNkwroyJsRLWQDRsBVKg-Ap-nlqByDhGQjODpALWftAZXRTE8pt_0YDQ2LBIPz57V-jHhxkChsmn4l-1g2bWPFPWOGZ0ay39Jvy_WQR64v4GIFj2Xo-nwvjNPkaPW3rBF-LUzXYYD-olE2ZTBUQpcqt7UMQbTt9wXReBFe3n2o-_u7z8WoBuBV_UdtY8QipQ1IdJ-dVnLw1JVoQLz7rTRPbfs4s7MxOjRNduiTpnLCPZP2Wj6gtxZN2j7MnHbgH-B_6XEmdnzcU_Ew8ejczn3BNBScsuecZTU0C07EH24Tz4k1LjlGrZtz5iP3zZNsY9q4g8x4mHFWXx8pwKm5qWZ4QYSf_6ZVkXwpGNRCQxi6Bci2g1kuoexaNa6sTNI3bglmNmdt5qiobhdwTmSUOVvKV4j6IP4HEv0sqUYE_dmdfzutBdYXsMr6jjNWObgmLb6AoV4ymRyATyjXKnKQGtxNwvFWbhTsScbB7LUknp0YZOsY1vE50bdeBJNl5FUtslWeFa8rNiD90HkdHeEXXTdmwFTu0erBzejCqp_pqUUWlq9shBfZV2GYcHoSqJ2Fm1nVdjVzsAetDcLXM2fmjZkwHUotWIenO6lD9rK5X7qvyxMnZjXpnFdOzqv4S1k1YtW_WEDvbHEEoeYaSHUzUbusb1Xr9UplXyR9x1Kxszc7XwAYlbYQ5LFrzM5AKHulcjenz58Vnw4i5jZywI6zERB8KBCtJUOXKomBX9JAzlldtKAXxsg_1hmmUnGi6M1VwNPfhpqJkmQHdpaBLXEvO6Ahjm1DVQAxv9xvBGi9Sb2D9VSpt3-a9ovII4DcLiyNmhmalhUTQewE1RsomYjnlmVFMU02mpZTIdbNkD6DgQHkqcYvc1o5KgHHRLqTcVJqsPJ64FMwqmi0xbdQ0xthTD4-LRjfqcOAHZjewYWZqEszChaLaf7acJuvjqRnNc5TIU2-hQkvzuLNSNannsUwAqZXf-h9fn5OEdkJq5ass2df9l4OFAm1bgtTzAG-WBk1RGkQ3ZqGjFL5bmr7dTa8z5lMJcM8h-dp7rJFGpWybo1KrkxFydMx2X4vql56y-W7U563nTtMBB9pZwfam-rBDF0fOAg-iy9PwK348ih26XUQEo_U_R7yna5cD5LvN2evTejXYMq90shNhjnXRDeq2qN_Uw2qlIikk7urFqtbV8FCqfZyOh-03lKHrQNsE1U44gVOPfMcBL6X0LKTjU-zAGvV3m0gNqMs_W26ca6TUqa3L6k_O9MuBwaGncuiz8FvhUuUocvCtvJpptq-vjwvmvsz79fxSlDwDcqTZ4FY6mua15M5i7ab3SYGuQ7Is6WheUvTmdCv4CgOn5c7l6r7-dWc0Zn_TPaww5A6HbPikAVOuT9twpZh6W9T621-9e4LCFPHBdO4OyqByjRrrKo23JJwLbQ-v2Oe5cOmbIi9Yu2mqVIlW-nbOEf0Wl_dS3-5Q-ITbStUUfNY_-V6uCqJnPXotsjpQts7jtB-2_Q5VFoWQWtn8oXYj5rPnC3-NBD-NVcg15ci6md4vkXaWpCYJr8KL0kQexdozwcUVMy47OVmLmEDRjnmDxVgnkL2KwKTAxu-YvFV3R_VTzWgyLIT31E39oHYa1WX3gMhQGj28N9PBqTk4Eoxn9YmRFrnupmpP0r1zJm26NVyBDlRivdTzKH72dGVbMJuvW5rqYhCqVh3cGs9N5AGeSobKHS76ozp6c8M5vkIQxZ1ukYW60bowONlv-_1-VB9IEnIdREuJ1tqCaKll5ObEx13CaunELj1otrRG3h2Gki2Oz0_RDCTuqD2cdREbodV4T6ajyWh8VA09OQloWdr-rbZukCogLszACvUekfuasKd60-62FZM-SFM-nR4eDalOx6f0wnG_-zcZ3G-Jesc_oF-LGMsadDeeR3clkd0t7LUN-3rU9hknnUbjXHAtBYPgau72vHvvH5b9rFG2AvCa27ZZDCQ32ljDFBIelqM-IicxeTqxkmFWkzNWOLULL4Qtp7vCJzB_cgdeB9avFalkCHe30wEWRW-wqPf-6eSrHvfOsa46FlwtZlRm_nSKg10KLt8U8kOfs2pPdbqpqX27LkhNWKtAxTcnX3499_LhjbfPne5PvXHY7IcOyvs3wtclA3VgzB4aVfh3iTxF1d9pyjAnJdPDS3Rax21SfBR8-oy_elupH76etKyv_z2hnOXs_4qv_xOWXr-ty1-fT7L0-b0e5PnXCT-B-GxIF7rOwO3KnfQVA3vI7xFV5TdcW8K2bzdEktRuxQrZ2XXto257PYIxsTfz7m5nr1Vstpu6pCiYvZxwekOkuzNcQXU3C6iC_Ya4dGXu6huT4JpUIYNSoarzSYZrkh6GYM_e5Dl503d_KUhK-fqRyJd_wFwPyjDNNUKrtz3C7xKLfi_mBCpCVgG1muOJ9k3WpGbxbirVZcAQuSbzoRxSlJqYv2K7otxevlD23fF0uxdpIuRfJU-12zI2K7vTcbMgXjzYfbqB7ePjfbxOrd_sFPfOPlapdsNTu5LbJZ0LrgQnXlZ_DpDt_9RJ1llob3riuldIrP-e3vrNcrfEdOGuCJhSE9clI9K7YjEMrVnfds-m1aY-OH7aw3w31Rc48bZDQdRH2p3OSjZkh5UQBs9l_RfbfRWzz_b7Tu4Ee-26467WMRn9AGQGdjbCz_XDamJ5uqpbS0PKM9g8bAioJr9LreoDLW8Koyajt0zFYW-Z4xMr7mewF9drxB332ZrVdNvcMNKExro8zHuL9pzbqf7cCUc2mbzPZ7mTLVuR0ZyibOP28Wwhq8E_9n8NJ4wnPPef3_7V0PsPDnENxJ5zPFCGCZEtZu5uJ_HPcCNnZO1R6HYmqT2Wm3mTjkHWZZSsjpwArY-cGMY83RuPqQ7blWCqW4NzEFkGvNyuvF3HlvM5PN37-UkVXk2O4NDvbYCeFMW7jse0yunNHsisvbPG_uGY6BImXmjoH4keCrozH_BwsWePRO2pCw6OaHv9cm946DU7zh5esS7v3u8dVUcW2gHH04KrRXMS7eRNsqF7e48Hq0ntJcb58uHm7ksQ30AQRWHOjLYv8pIxCLdEppsgXvzgO5QXEH6OISxogRDmXIQF0xDmrq1mk4rwWxFE83CRLD8_Pd8v_y_58vmPp_mnIF7EEH7LhdwSDeG36lriwj0IFaalpPoAYa40SV_CQgqNqRYyJAaJsCCSbIN4oVQRruwdwVDRHxjEiwsI8zSvJ1DBHWIKt4Rrmob2_EwhFHXvvnERlrxUmIWp2G4Jz0JGOYZErkvbjQvzgpWW94vmLqe9eLp8ePj6-Ltg7DBSAsItY7sthIV5AGFuTwQYLNaSbMOdvfGoICz0RiLJIMxFgXxbdOdZshhD1nsstkW4IumLvYSysLcWuwN4uQ0dZBXEi-ii93pnWUd_oGGx0pIWW8qxv3bFkyBeOKv1pjX4hrZUUE60uchzJkgW-vqRl9w4aPvQTtN0S39gqOiKUb4OU8KYssOkYCxkQhTKilnSVIeEUWI7XmeeOGaG1pMYHxPmihUtshDm3ucOiRKV8dXGlrsvdBqKQvcfUmbX7TyMjILgDtnw6y3R25INAKv5kIUqtRT35K41Sm6mpxvDJZN7ZWbS0Uih9MBj48dNUdVglf9-_8n-njeXMuffv_tmHUQXzsxbG62vf958-fLp6fn-83--NJMfFh2XsDMSVBgyo5CMZRB-YwbG54n5HSohtbUnwe13okKOmNlLC-GPIJpLZFLUX7jY21G-BtsHTIvwc9x8nN-5L6yyIvt5LbZFDagwrkIis8d-zAeRKu9O6rW7wm4CrT36XFmnam_Ym6hZfzTD9kK-QCqkxFSzg-sb6w0qrPxlG2csgwkHwg-CI6SC51RuoaqP3Rlpe4jX4ZAJVDyIrnSzXC4kHEQJRMEeGQPB7Z3k3z7dLOqL1EFszx7xl25x-HgAdVAat0B5Lhof_m-UHJkR2OVoNhqHd_fPJgIWvXxlQZWWwh7Acrew3eObxwU8HX4ghxlczcbj7-5x9HpxfXcLl9fj8eNzEC0VLBZPVYPV-qX3_m-DD9nHOJvFM_IBP06uJtPZ1XgSTz9sPl7OSHSVT_PLMZleYHZJLjMkF2k2mcZxdjm7_EA_RuPoYjydXE2uo2gyHeWr2QWJJ4REq_j6cpUFF2PcEspGxkBGQq4_2P3Sj7Noen35gZEVMmX_x0MUMbpqbtBHwXTxQX40k8JVuVbBxZhRpVULRlPN8GP_fr3b57ibz8Fdwa_-M0EF112YVh9KyT5utC5UsxuzpnpTrkap2JqIwnb1HxM0_sJUB9HS4m0Ws6j_fwAAAP__l429eA">