Adding a new compiler intrinsic

Hi all,

(Not yet a list member, please CC me in all replies)

I’m new to clang and am interested in adding a new compiler intrinsic to simplify my work with variadic template parameter packs in C++. The first half of this message explains the intrinsic I’m hoping to add, and the second half is a plea for code pointers I could use as a starting point.

The motivation/description of the intrinsic can be illustrated by the following C++17 code snippet:

template <typename T>
int hash(T const &t);
/* ^^^ to be overloaded for all relevant types */

template <template <typename...> class Tuple, typename... T>
int hash(Tuple<T...> const &t)
{
using std::get; // ADL
return ... ^ hash(get<**__indexof(T)**>(t));
}

The new intrinsic, __indexof(T) would only be valid inside an expression that unpacks a parameter pack T. For each unpacked expression that is produced, it would evaluate to a constexpr size_t between 0 and sizeof…(T) giving the ordinal position of that expression within the pack. Without such a functionality, you end up writing a lot more (and a lot uglier) code to achieve the same result when dealing with tuples.

I’m floating this idea at the ISO std-proposals forum as a potential addition for C++17—it’s a great complement to fold expressions—but I suspect it would get a lot more traction if I could show a working implementation. Plus, then I could use it for my own work in the meantime.

Any pointers folks might have to parts of the code base I should be studying as a starting point would be greatly appreciated. Currently I’m digesting two things:

  • Everything to do with the C++11 sizeof… operator. Hopefully this will identify the bits of parsing and semantic analysis that will need attention.
  • The changeset that introduced C++17 fold expressions. Hopefully this will highlight locations that expand expressions containing parameter packs.

So far, it looks like the best approach will be to parse __indexof(T) into a new IndexOfPackExpr object, and at an appropriate moment later on—after the pack size is known but before expansion begins—to replace that Expr with a non-type template pack <size_t …Indexes>, whose entries start at 0 and end just before sizeof…(T). That way, when expansion starts the expression will contain two peer parameter packs of the same size and the existing machinery will dutifully expand both in lockstep.

Does that sound like a reasonable approach?

Thanks,
Ryan Johnson