@@ -576,6 +576,9 @@ class PROTOBUF_EXPORT TcParser final {
576576 static const char * FastMlS1 (PROTOBUF_TC_PARAM_DECL);
577577 static const char * FastMlS2 (PROTOBUF_TC_PARAM_DECL);
578578
579+ // NOTE: Do not dedup RefAt by having one call the other with a const_cast. It
580+ // causes ICEs of gcc 7.5.
581+ // https://github.com/protocolbuffers/protobuf/issues/13715
579582 template <typename T>
580583 static inline T& RefAt (void * x, size_t offset) {
581584 T* target = reinterpret_cast <T*>(static_cast <char *>(x) + offset);
@@ -595,7 +598,20 @@ class PROTOBUF_EXPORT TcParser final {
595598
596599 template <typename T>
597600 static inline const T& RefAt (const void * x, size_t offset) {
598- return RefAt<T>(const_cast <void *>(x), offset);
601+ const T* target =
602+ reinterpret_cast <const T*>(static_cast <const char *>(x) + offset);
603+ #if !defined(NDEBUG) && !(defined(_MSC_VER) && defined(_M_IX86))
604+ // Check the alignment in debug mode, except in 32-bit msvc because it does
605+ // not respect the alignment as expressed by `alignof(T)`
606+ if (PROTOBUF_PREDICT_FALSE (
607+ reinterpret_cast <uintptr_t >(target) % alignof (T) != 0 )) {
608+ AlignFail (std::integral_constant<size_t , alignof (T)>(),
609+ reinterpret_cast <uintptr_t >(target));
610+ // Explicit abort to let compilers know this code-path does not return
611+ abort ();
612+ }
613+ #endif
614+ return *target;
599615 }
600616
601617 template <typename T>
0 commit comments