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

Reply via email to