Pseudo-functions taking types as arguments - keywords?

Hi,

I just implemented the POD property of C++ classes, but to test it, I also need a way to determine if a class is a POD. Since the rules in the C++ standard only specify runtime behaviour of PODs, I can't use those. I'm therefore looking to type traits, which expose this information.

To implement TR1 type traits, the compiler must provide some sort of help. In GCC, this help takes the form of about 15 type-traits extension built-ins, like __is_pod, __is_abstract, __has_trivial_constructor, etc. These built-ins take the form of unary and binary functions that take types as arguments and return a bool constant expression. So my goal is to implement the __is_pod, and the only sane way to do this is to provide the infrastructure for all these type traits.

The question is, how do I implement the names of these functions? If they are normal identifiers, their arguments will be mis-parsed, unless I introduce a lot of special cases in the parser. However, it's a lot of keywords to add. Thus, I'm wondering if Clang has some pre-established way of handling such things.

Sebastian

I just implemented the POD property of C++ classes,

Great!

but to test it, I
also need a way to determine if a class is a POD. Since the rules in the
C++ standard only specify runtime behaviour of PODs, I can't use those.
I'm therefore looking to type traits, which expose this information.

The only detectable compile-time behavior I can think of for POD types is [dcl.init]p9, which says that for a const uninitialized variable of

  const X x;

X either needs to be a POD or needs to have a user-declared default constructor. We don't check that condition at the moment, since we don't have a way to check for POD types, although there's an #if 0'd spot for it in Sema::ActOnUninitializedDecl. Unfortunately, we haven't fixed the linkage-specification issues yet that caused that code to be #if'd out.

To implement TR1 type traits, the compiler must provide some sort of
help. In GCC, this help takes the form of about 15 type-traits extension
built-ins, like __is_pod, __is_abstract, __has_trivial_constructor, etc.
These built-ins take the form of unary and binary functions that take
types as arguments and return a bool constant expression. So my goal is
to implement the __is_pod, and the only sane way to do this is to
provide the infrastructure for all these type traits.

This is a great idea.

The question is, how do I implement the names of these functions? If
they are normal identifiers, their arguments will be mis-parsed, unless
I introduce a lot of special cases in the parser. However, it's a lot of
keywords to add. Thus, I'm wondering if Clang has some pre-established
way of handling such things.

Clang's IdentifierInfo structure has a field that's set to a non-zero "builtin ID" for builtin function names (such as "__builtin_constant_p"); see IdentifierInfo::getBuiltinID/setBuiltinID. The target-independent builtins themselves are declared in include/clang/AST/Builtins.def and there are various target-dependent builtins as well (e.g., X86Builtins.def).

Now, all of these builtins are functions that operate on values, not on types, so the mechanism would probably need to be extended a bit for the type-trait functions (say, by specifying the type of the function as "T"). The parser will need to be able to distinguish between builtins that operate on values vs. builtins those that operate on types, but I think such a change won't be terribly complex.

  - Doug

In the past, we've just used keywords; as far as I recall, the only
cases we've had to deal with so far are sizeof, alignof, and typeof.
You're pretty much forced to use keywords, actually, because you'll
need a special action to pass the type names to Sema. If you want to
avoid adding 15 Actions, you can probably make a single ActOnTypeTrait
which takes an enum.

-Eli

Yep, we already have several other builtins that take types (e.g. __builtin_types_compatible_p, etc). These are all handled in the parser as language keywords, because they have ad-hoc and weird different parsing rules.

Since these are C++ specific builtins, would it make sense to have "builtin templates" that handle these? That way these could just be implicitly declared templates and take their arguments as type parameters?

-Chris

GCC has function-like builtins for the type traits, which are documented here:

  Type Traits (Using the GNU Compiler Collection (GCC))

I think it's best to implement these for querying the properties of types, rather than invent some new kind of builtin template. If sufficiently motivated, one could also implement Microsoft's type trait functions (which, IIRC, the GCC builtins were modeled after):

  Compiler Support for Type Traits (C++/CLI and C++/CX) | Microsoft Docs

  - Doug

Yep, we already have several other builtins that take types (e.g.
__builtin_types_compatible_p, etc). These are all handled in the
parser as language keywords, because they have ad-hoc and weird
different parsing rules.

Well, these traits don't have weird or ad-hoc rules, really. But I get the
drift. I'll do them as keywords.

Since these are C++ specific builtins, would it make sense to have
"builtin templates" that handle these? That way these could just be
implicitly declared templates and take their arguments as type
parameters?

While the notion of compiler-supplied templates is highly attractive in
general, it doesn't allow compatibility on this low level with GCC.
Nevertheless, CSTs could be used for highly interesting purposes at a later
time, e.g. an experimental implementation of compile-time reflection for
C++ types.

GCC has function-like builtins for the type traits, which are
documented here:

  Type Traits (Using the GNU Compiler Collection (GCC))

I think it's best to implement these for querying the properties of
types, rather than invent some new kind of builtin template.

That's what I'm doing. This also has the advantage of GCC compatibility in
libraries that have their own traits implementations (like Boost).

If
sufficiently motivated, one could also implement Microsoft's type
trait functions (which, IIRC, the GCC builtins were modeled after):

  Compiler Support for Type Traits (C++/CLI and C++/CX) | Microsoft Docs

Should be doable. There are only 5 or so that aren't C++/CLI-specific.

Sebastian