[PATCH] recog: Use parameter packs for operator()

Richard Sandiford richard.sandiford@arm.com
Thu Jun 18 07:55:25 GMT 2020


Sebastian Huber <sebastian.huber@embedded-brains.de> writes:
> On 18/06/2020 09:09, Richard Sandiford wrote:
>
>> Sebastian Huber <sebastian.huber@embedded-brains.de> writes:
>>> On 16/06/2020 12:42, Richard Sandiford wrote:
>>>
>>>> [...]
>>>> 2020-06-16  Richard Sandiford  <richard.sandiford@arm.com>
>>>>
>>>> gcc/
>>>> 	* coretypes.h (first_type): New alias template.
>>>> 	* recog.h (insn_gen_fn::operator()): Use it instead of a decltype.
>>>> 	Remove spurious “...” and split the function type out into a typedef.
>>>> ---
>>>>    gcc/coretypes.h | 4 ++++
>>>>    gcc/recog.h     | 5 +++--
>>>>    2 files changed, 7 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/gcc/coretypes.h b/gcc/coretypes.h
>>>> index cda22697cc3..01ec2e23ce2 100644
>>>> --- a/gcc/coretypes.h
>>>> +++ b/gcc/coretypes.h
>>>> @@ -359,6 +359,10 @@ struct kv_pair
>>>>      const ValueType value;	/* the value of the name */
>>>>    };
>>>>    
>>>> +/* Alias of the first type, ignoring the second.  */
>>>> +template<typename T1, typename T2>
>>>> +using first_type = T1;
>>>> +
>>>>    #else
>>>>    
>>>>    struct _dont_use_rtx_here_;
>>>> diff --git a/gcc/recog.h b/gcc/recog.h
>>>> index 0a71a02c4a9..d674d384723 100644
>>>> --- a/gcc/recog.h
>>>> +++ b/gcc/recog.h
>>>> @@ -295,9 +295,10 @@ struct insn_gen_fn
>>>>      typedef void (*stored_funcptr) (void);
>>>>    
>>>>      template<typename ...Ts>
>>>> -  rtx_insn *operator() (Ts... args...) const
>>>> +  rtx_insn *operator() (Ts... args) const
>>>>      {
>>>> -    return ((rtx_insn *(*) (decltype(args, NULL_RTX)...)) func) (args...);
>>>> +    typedef rtx_insn *(*funcptr) (first_type<rtx, Ts>...);
>>>> +    return ((funcptr) func) (args...);
>>>>      }
>>>>    
>>>>      // This is for compatibility of code that invokes functions like
>>> I get this error on FreeBSD 12.1 with
>>>
>>> c++ --version
>>> FreeBSD clang version 8.0.1 (tags/RELEASE_801/final 366581) (based on
>>> LLVM 8.0.1)
>>> Target: x86_64-unknown-freebsd12.1
>>> Thread model: posix
>>> InstalledDir: /usr/bin
>>>
>>> In file included from ../../gnu-mirror-gcc-aff95ee/gcc/function.c:51:
>>> ../../gnu-mirror-gcc-aff95ee/gcc/recog.h:301:30: error: too many
>>> arguments to function call, expected 1, have 2
>>>       return ((funcptr) func) (args...);
>>>              ~~~~~~~~~~~~~~~~  ^~~~
>>> ../../gnu-mirror-gcc-aff95ee/gcc/function.c:3315:29: note: in
>>> instantiation of function template specialization
>>> 'insn_gen_fn::operator()<rtx_def *, rtx_def *>' requested here
>>>           emit_insn (GEN_FCN (icode) (parmreg, validated_mem));
>> Thanks for the report.  Was clang OK with the earlier version
>> (i.e. before 4e49b994de060d4a6c9318d0ed52ef038153426e)?
> Yes, the last version I built successfully was 
> b952c2cfcd74c284970e1b9bf1fca58f5f69ab23 on 10th of June. I build GCC 
> roughly once per week.

Hmm, yeah, can reproduce with a recentish build from clang master:

template<typename T> using int_t = int;
void (*f)();
template<typename ...Ts>
void g(Ts... args) {
#if A
  ((void (*)(int_t<Ts>...)) f)(args...);
#elif B
  typedef void (*funcptr)(decltype((void)args, 0)...);
  ((funcptr) f)(args...);
#else
  typedef void (*funcptr)(int_t<Ts>...);
  ((funcptr) f)(args...);
#endif
}
void h(int x, int y) { g(x, y); }

Works with -DA and -DB, but fails with the final version.

So it looks like the obvious choices are:

(1) Remove the typedef.
(2) Go back to using decltype.
(3) Revert the whole thing and go back to the overloads.

Not sure about (1), because it leads to awkward formatting, and would
need a comment to say “Don't use a typedef!”.  The above error shows
that we're probably close to the edge of what compilers will support
reliably.

(2) seems to work more reliably, and gives nicer error messages,
but was unpopular for being unidiomatic C++.

I guess at this point, (3) is the way to go.

Thanks,
Richard


More information about the Gcc-patches mailing list