root-project / root

The official repository for ROOT: analyzing, storing and visualizing big data, scientifically
https://root.cern
Other
2.67k stars 1.27k forks source link

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

Open bendavid opened 1 year ago

bendavid commented 1 year ago

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
hahnjo commented 10 months ago

Still same issue after the upgrade to LLVM 16. As this involves TClingCallFunc, I'm adding Vassil here

bendavid commented 2 weeks ago

Just confirming this is still a problem in current nightlies.