Issue with uninstantiated RunStyles templates on 32-bit

52 views
Skip to first unread message

Kacper Kasper

unread,
Jul 21, 2018, 11:11:00 AM7/21/18
to scintilla-interest
Hi,

I have recently changed Haiku port to create Shared Object along with static library. Unfortunately that has uncovered an issue in 32-bit build.

In RunStyles.cxx there are two instatiations of RunStyles - for int and for ptrdiff_t. The second one is guarded with #if PTRDIFF_MAX != INT_MAX.
This is problematic because on 32-bit Haiku PTRDIFF_MAX is equal to INT_MAX, but ptrdiff_t is long int. Despite the same size it's a different type and shared object ends up with undefined symbols.

We have a fix in our ports tree [1], but I think this check is broken and should be removed.

Thanks,
Kacper

Neil Hodgson

unread,
Jul 21, 2018, 6:44:44 PM7/21/18
to Scintilla mailing list
Kacper Kasper:

> In RunStyles.cxx there are two instatiations of RunStyles - for int and for ptrdiff_t. The second one is guarded with #if PTRDIFF_MAX != INT_MAX.
> This is problematic because on 32-bit Haiku PTRDIFF_MAX is equal to INT_MAX, but ptrdiff_t is long int. Despite the same size it's a different type and shared object ends up with undefined symbols.
>
> We have a fix in our ports tree [1], but I think this check is broken and should be removed.

The check is required to build with g++ on 32-bit Linux. Here is the error when it is removed:

g++ -I/usr/include/gtk-3.0 -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/libdrm -I/usr/include/harfbuzz -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/gio-unix-2.0/ -I/usr/include/atk-1.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include -pthread --std=gnu++17 -DNDEBUG -Os -Wall -pedantic -fPIC -DGTK -DSCI_LEXER -I ./../include -I ./../src -I ./../lexlib -c ./../src/RunStyles.cxx
./../src/RunStyles.cxx:313:27: error: duplicate explicit instantiation of ‘class Scintilla::RunStyles<int, int>’ [-fpermissive]
template class Scintilla::RunStyles<ptrdiff_t, int>;
^~~~~~~~~~~~~~~~~~~~~~~~~
./../src/RunStyles.cxx:314:27: error: duplicate explicit instantiation of ‘class Scintilla::RunStyles<int, char>’ [-fpermissive]
template class Scintilla::RunStyles<ptrdiff_t, char>;
^~~~~~~~~~~~~~~~~~~~~~~~~~
make: *** [makefile:96: RunStyles.o] Error 1

A better fix would be to detect if ptrdiff_t and int are different types but I can’t see how to do that with the preprocessor or with templates.

Neil

Neil Hodgson

unread,
Jul 28, 2018, 5:28:29 AM7/28/18
to Scintilla mailing list
While I hate platform #ifs greatly, this is a case in which they may be required. So something like:

#if (PTRDIFF_MAX != INT_MAX) || defined(PLAT_HAIKU)
template class Scintilla::RunStyles<ptrdiff_t, int>;
template class Scintilla::RunStyles<ptrdiff_t, char>;
#endif

A good way to detect Haiku would have to be found. Its possible that the choice of long int for ptrdiff_t is from the compiler or runtime library, not the operating system.

Neil

Kacper Kasper

unread,
Jul 30, 2018, 11:47:20 AM7/30/18
to scintilla-interest

   A good way to detect Haiku would have to be found. Its possible that the choice of long int for ptrdiff_t is from the compiler or runtime library, not the operating system.
 
Yes, this typedef is in GCC headers. I don't know why there is a difference between Linux and Haiku there.

There is no PLAT_HAIKU in Platform.h yet. It can be detected using #if defined(__HAIKU__).

I was thinking about using std::conditional, but there is no good way to use it in this case. #if would have to stay anyway.

Kacper

Neil Hodgson

unread,
Jul 30, 2018, 7:41:34 PM7/30/18
to scintilla...@googlegroups.com
Kacper Kasper:

> There is no PLAT_HAIKU in Platform.h yet. It can be detected using #if defined(__HAIKU__).

OK, added PLAT_HAIKU and then used it in RunStyles.cxx.
https://sourceforge.net/p/scintilla/code/ci/406da729a8b35503e50046407b39c0f88aea0436/

> I was thinking about using std::conditional, but there is no good way to use it in this case. #if would have to stay anyway.

I can’t see any simple way to make this work. All the RunStyles.cxx code could be moved up as inline methods in RunStyles.h but that produces a much fatter header than I like.

Neil

Reply all
Reply to author
Forward
0 new messages