root icon indicating copy to clipboard operation
root copied to clipboard

Cling doesn't play nice with template arguments after a parameter pack

Open bendavid opened this issue 1 year ago • 2 comments

Consider the following test case:

test.c

#include "TInterpreter.h"
#include "TClass.h"
#include "TMethod.h"
#include "TROOT.h"
#include <iostream>

struct Dummy {
  double x;
};

struct Dummy2{
};

template<typename... Args, typename Extra = Dummy2>
double sumT(Args... args) {
  return (args.x + ...);
}

int test() {
  auto meth_explicit = gROOT->GetGlobalFunctionWithPrototype("sumT", "Dummy, Dummy, Dummy");
  TMethodCall call_explicit(meth_explicit);

  double res;
  const Dummy arg{5.};
  const void *args[3] = {&arg, &arg, &arg};
  call_explicit.Execute(nullptr, args, 3,  &res);
  std::cout << "res = " << res << std::endl;

  return 0;
}

The attempted call fails, because the "extra" template argument is explicitly appended to the list of template arguments when the call wrapper is compiled. (This issue prevents templated functions with this feature being called from PyROOT)

In file included from input_line_8:1:
/home/b/bendavid/pyrootdebug7/test.c:16:16: error: no member named 'x' in 'Dummy2'
  return (args.x + ...);
          ~~~~ ^
input_line_10:8:17: note: in instantiation of function template specialization 'sumT<Dummy, Dummy, Dummy, Dummy2, Dummy2>' requested here
         Dummy))sumT<Dummy, Dummy, Dummy, Dummy2>)(*(Dummy*)args[0], *(Dummy*)args[1],
                ^
Error in <TClingCallFunc::make_wrapper>: Failed to compile
  ==== SOURCE BEGIN ====
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wformat-security"
__attribute__((used)) __attribute__((annotate("__cling__ptrcheck(off)")))
extern "C" void __cf_0(void* obj, int nargs, void** args, void* ret)
{
   if (ret) {
      new (ret) (double) (((double (&)(Dummy, Dummy,
         Dummy))sumT<Dummy, Dummy, Dummy, Dummy2>)(*(Dummy*)args[0], *(Dummy*)args[1],
         *(Dummy*)args[2]));
      return;
   }
   else {
      (void)(((double (&)(Dummy, Dummy,
         Dummy))sumT<Dummy, Dummy, Dummy, Dummy2>)(*(Dummy*)args[0], *(Dummy*)args[1],
         *(Dummy*)args[2]));
      return;
   }
}
#pragma clang diagnostic pop
  ==== SOURCE END ====
Error in <TClingCallFunc::ExecWithArgsAndReturn(address, args, ret)>: Called with no wrapper, not implemented!
res = 7.31217e-322
(int) 0

bendavid avatar Mar 27 '23 00:03 bendavid