-
Notifications
You must be signed in to change notification settings - Fork 103
Description
I think we need mangling for all the 22 different kinds of reflection constants (and for some kinds different ways how to mangle different types of the reflections of the same kind, see later.
https://eel.is/c++draft/basic.fundamental#17 lists the 22 kinds (0th is the null reflection). std::meta::info values which are template parameter equivalent need to mangle the same, those which are not need to mangle differently.
#include <meta>
template <auto A>
void foo () {}
int arr[] = {1, 2, 3};
auto [a1, a2, a3] = arr;
[[=1]] void fn(int n);
enum Enum { A };
using Alias = int;
struct B {};
struct S : B {
int mem;
int : 0;
};
template<auto> struct TCls {};
template<auto> void TFn();
template<auto> int TVar;
template<auto N> using TAlias = TCls<N>;
template<auto> concept Concept = requires { true; };
namespace NS {};
namespace NSAlias = NS;
constexpr auto ctx = std::meta::access_context::current();
void bar () {
foo <std::meta::info {}> (); // null reflection
foo <std::meta::reflect_constant(42)> (); // value
foo <std::meta::reflect_object(arr[1])> (); // object
foo <^^arr> (); // variable
foo <^^a3> (); // structured binding
foo <^^fn> (); // function
foo <std::meta::parameters_of(^^fn)[0]> (); // function parameter
foo <^^Enum::A> (); // enumerator
foo <std::meta::annotations_of(^^fn)[0]> (); // annotation
foo <^^Alias> (); // type alias; could be either also specialization of template alias
foo <^^S> (); // type
foo <^^S::mem> (); // class member
foo <std::meta::members_of(^^S, ctx)[1]> (); // unnamed bit-field
foo <^^TCls> (); // class template
foo <^^TFn> (); // function template
foo <^^TVar> (); // variable template
foo <^^TAlias> (); // alias template
foo <^^Concept> (); // concept
foo <^^NSAlias> (); // namespace alias
foo <^^NS> (); // namespace
foo <^^::> (); // global namespace (special case of namespace that might need to be mangled differently
foo <std::meta::bases_of(^^S, ctx)[0]> (); // direct base class relationship
foo <std::meta::data_member_spec(^^int, {.name="member"})> (); // data member description
}Guess we need some 2 letter prefix for mangling all std::meta::info objects and then one (or two letters?) for each of the 22 kinds and then depending on the kind some way how to mangle what exactly it reflects, ideally using some existing non-terminals in the mangling grammar to mangle existing concepts like namespaces (except :: is special), types, variables, enumerators, ...
For value it can be a scalar constant (so 42, 1.0f, or even a std::meta::info constant recursively) or a structured type constant, those can be mangled guess like the non-type template arguments, types like template arguments. For annotations, I think best is to mangle it as Nth
annotation of something (function, namespace, variable, etc.). Direct base class relationship could be mangled as Nth direct base of a particular derived type. Data member description needs to be mangled as quintuple of type, optional identifier, optional integer constant (alignment), optional integer constant (bit_width) and integer constant (false/true). For parameters again Nth parameter of some function.
For class members or unnamed bit-fields or variables it might be interesting, some class members can be easy if they have a unique name, mangle the corresponding class name and the name in it. Except that there can be unnamed class members (e.g. anonymous unions, or the unnamed bitfields). For class members those could be still in theory mangled as Nth non-static data member or Nth unnamed bit-field.
What to do for anonymous unions at class scope? Pedantically
static union {};is invalid but some compiler accept that (though e.g. in GCC it is not reachable through members_of right now because we though we don't have to bother with something hard which is not pedantically valid).