[PATCH] support ptrdiff_t if it has the same storage size as int, but does not alias it

"'Robin Haberkorn' via scintilla-interest" <[email protected]> Tue, 26 Aug 2025 18:40:53 +0300 (MSK)
Newsgroups gmane.comp.lib.scintilla.devel
Message-ID <[email protected]>
Hello everybody!

As promised, this patch fixes NetBSD 10 builds on ARMv6.
But it's not NetBSD-specific.

Scintilla assumed that ptrdiff_t and int alias (are the same time) if 
their storage size is equal. With this patch we no longer make such 
assumptions which should improve code portability.

It also removes a hack for 32-bit Haiku which was apparently
causing the same issues [1] I was experiencing and would probably
be broken by now due to the same ptrdiff_t-assumptions in CellBuffer.cxx.

See the patch header for more details.

Due to my CI systems I can say that this at least does not break Linux 
x86_64 GCC and Clang, i586 GCC and MinGW MSVCRT (Win64) GCC builds.

Best regards,
Robin

PS: Scintilla v5.5.7 is still building on NetBSD 10 ARMv6 with the default 
GCC. It's a GCC v10.5.0 and not a GCC v7 as I was erronously writing 
earlier.

PPS: Musing about C++'s std::is_same<X,Y> construct, I realized that we 
can do the same in C11 now as well - at least with some ubiquitous GCC 
extensions:

#define TYPE_EQUALS(X, Y) ({ \
 	X __dummy; \
 	_Generic(__dummy, Y : true, default : false); \
})

With some minor modifications, you could use it for static assertions as 
well. That's actually an useful application of _Generic() for once...

[1] https://groups.google.com/g/scintilla-interest/c/xPXquJUIXo8/m/BLXBpTTgBwAJ

-- 
You received this message because you are subscribed to the Google Groups "scintilla-interest" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To view this discussion visit https://groups.google.com/d/msgid/scintilla-interest/c87bfb51-8367-afb6-461b-bc570a3865a5%40googlemail.com.
0001-support-ptrdiff_t-if-it-has-the-same-storage-size-as.patch (text/plain, 3.2 KB)
From 0953ffeee80abdd8e79ddacc7066eb02c78968e7 Mon Sep 17 00:00:00 2001
From: Robin Haberkorn <[email protected]>
Date: Thu, 21 Aug 2025 23:04:57 +0000
Subject: [PATCH] support ptrdiff_t if it has the same storage size as int, but
 does *not* alias it

* This is the case e.g. on NetBSD 10 for ARMv6 where Sci::Position == ptrdiff_t == long int,
  but obviously for other platforms as well, where it causes "invalid conversion"
  and "undefined symbol" errors.
  Scintilla was testing for aliasability by comparing the storage size with sizeof()
  or PTRDIFF_MAX == INT_MAX at the preprocessor level.
  This was fundamentally flawed.
* In LineVector<T>::InsertLines() we are now using the C++17 construct
  std::is_convertible_v<From*,To*> instead.
* We need RunStyles<ptrdiff_t> as well on the affected platforms.
  AFAIK this is impossible to test for in a constant expression that can be used
  with the preprocessor.
  A workaround has been added previously for Haiku:
  https://groups.google.com/g/scintilla-interest/c/xPXquJUIXo8/m/BLXBpTTgBwAJ
  The workaround is not very robust, as probably nobody guarantees that ptrdiff_t
  never aliases on Haiku. If it does, you will suddenly get errors about duplicate
  template instantiations.
  Instead we now instantiate RunStyles for all scalar types that could possibly be behind ptrdiff_t.
  This will always be more than what is required on any particular platform,
  but the linker should eliminate unused symbols.
---
 src/CellBuffer.cxx | 3 ++-
 src/RunStyles.cxx  | 9 +++++----
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/src/CellBuffer.cxx b/src/CellBuffer.cxx
index 04486d4c6..3e9deb934 100644
--- a/src/CellBuffer.cxx
+++ b/src/CellBuffer.cxx
@@ -21,6 +21,7 @@
 #include <optional>
 #include <algorithm>
 #include <memory>
+#include <type_traits>
 
 #include "ScintillaTypes.h"
 
@@ -215,7 +216,7 @@ public:
 	}
 	void InsertLines(Sci::Line line, const Sci::Position *positions, size_t lines, bool lineStart) override {
 		const POS lineAsPos = pos_cast(line);
-		if constexpr (sizeof(Sci::Position) == sizeof(POS)) {
+		if constexpr (std::is_convertible_v<Sci::Position *, POS *>) {
 			starts.InsertPartitions(lineAsPos, positions, lines);
 		} else {
 			starts.InsertPartitionsWithCast(lineAsPos, positions, lines);
diff --git a/src/RunStyles.cxx b/src/RunStyles.cxx
index 848670ba9..4fac2c2b3 100644
--- a/src/RunStyles.cxx
+++ b/src/RunStyles.cxx
@@ -319,9 +319,10 @@ void RunStyles<DISTANCE, STYLE>::Check() const {
 	}
 }
 
+// should also cover all possible types underlying ptrdiff_t (Sci::Position)
 template class Scintilla::Internal::RunStyles<int, int>;
 template class Scintilla::Internal::RunStyles<int, char>;
-#if (PTRDIFF_MAX != INT_MAX) || defined(__HAIKU__)
-template class Scintilla::Internal::RunStyles<ptrdiff_t, int>;
-template class Scintilla::Internal::RunStyles<ptrdiff_t, char>;
-#endif
+template class Scintilla::Internal::RunStyles<long, int>;
+template class Scintilla::Internal::RunStyles<long, char>;
+template class Scintilla::Internal::RunStyles<long long, int>;
+template class Scintilla::Internal::RunStyles<long long, char>;
-- 
2.50.1