On Wed, Sep 18, 2024 at 06:00:48PM +0200, Jakub Jelinek wrote: > Hi! > > The _cpp_trigraph_map initialization used to be done for C99+ using > designated initializers, but can't be done that way for C++ because > the designated initializer support in C++ as array designators are just > an extension there and don't allow skipping anything nor going backwards. > > But, we can get the same effect using C++14 constexpr constructor. > With the following patch we get rid of the runtime initialization > and the array can be in .rodata. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > > 2024-09-18 Jakub Jelinek <ja...@redhat.com> > > * internal.h (_cpp_trigraph_map_s): New type for C++14 or later. > (_cpp_trigraph_map_d): New variable for C++14 or later. > (_cpp_trigraph_map): Define to _cpp_trigraph_map_d.map for C++14 or > later. > * init.cc (init_trigraph_map): Define to nothing for C++14 or later. > (TRIGRAPH_MAP, END, s): Define differently for C++14 or later. > > --- libcpp/internal.h.jj 2024-09-12 18:16:49.993409101 +0200 > +++ libcpp/internal.h 2024-09-18 09:45:36.832570227 +0200 > @@ -666,6 +666,12 @@ struct cpp_embed_params > compiler that supports C99. */ > #if HAVE_DESIGNATED_INITIALIZERS > extern const unsigned char _cpp_trigraph_map[UCHAR_MAX + 1]; > +#elif __cpp_constexpr >= 201304L > +extern const struct _cpp_trigraph_map_s { > + unsigned char map[UCHAR_MAX + 1]; > + constexpr _cpp_trigraph_map_s (); > +} _cpp_trigraph_map_d; > +#define _cpp_trigraph_map _cpp_trigraph_map_d.map > #else > extern unsigned char _cpp_trigraph_map[UCHAR_MAX + 1]; > #endif > --- libcpp/init.cc.jj 2024-09-13 16:09:32.701455021 +0200 > +++ libcpp/init.cc 2024-09-18 09:49:43.671189585 +0200 > @@ -41,8 +41,8 @@ static void read_original_directory (cpp > static void post_options (cpp_reader *); > > /* If we have designated initializers (GCC >2.7) these tables can be > - initialized, constant data. Otherwise, they have to be filled in at > - runtime. */ > + initialized, constant data. Similarly for C++14 and later. > + Otherwise, they have to be filled in at runtime. */ > #if HAVE_DESIGNATED_INITIALIZERS > > #define init_trigraph_map() /* Nothing. */ > @@ -52,6 +52,15 @@ __extension__ const uchar _cpp_trigraph_ > #define END }; > #define s(p, v) [p] = v, > > +#elif __cpp_constexpr >= 201304L > + > +#define init_trigraph_map() /* Nothing. */ > +#define TRIGRAPH_MAP \ > +constexpr _cpp_trigraph_map_s::_cpp_trigraph_map_s () : map {} { > +#define END } \ > +constexpr _cpp_trigraph_map_s _cpp_trigraph_map_d; > +#define s(p, v) map[p] = v; > +
So with this we generate: constexpr _cpp_trigraph_map_s::_cpp_trigraph_map_s () : map {} { map['='] = '#'; map[')'] = ']'; map['!'] = '|'; map['('] = '['; map['\''] = '^'; map['>'] = '}'; map['/'] = '\\'; map['<'] = '{'; map['-'] = '~'; } constexpr _cpp_trigraph_map_s _cpp_trigraph_map_d; That makes sense to me. The patch is OK. Marek