Gnu::constructor doesn't handle dependent values

Consider this example:

void g();

template <int priority>
[[gnu::constructor(priority)]] auto f() -> void {

auto main() -> int {

This works on gcc, but fails to compile on clang:

<source>:4:3: error: 'constructor' attribute requires an integer constant
[[gnu::constructor(priority)]] auto f() -> void {
  ^                ~~~~~~~~

The error message here is a bit misleading since priority is an integer constant, just a value-dependent one. The issue is that the implementation for ConstructorAttr currently requires the value to be a non-dependent integer, simply doesn’t handle the value-dependent case, so it fails:

 def Constructor : InheritableAttr {
   let Spellings = [GCC<"constructor">];
   let Args = [DefaultIntArgument<"Priority", 65535>];
   let Subjects = SubjectList<[Function]>;
   let Documentation = [Undocumented];

Can gnu::constructor be extended to support value-dependent priorities?

it definitely could be, but dependent arguments on attributes are a bit of a pain, and we only h ave a few we’ve gone through and done. Part of the issue is the arguments end up having to be an Expr, and there is some special handling in a few places to make sure they are instantiated.

Based on the lack of documentation on that attribute, I’m guessing its old enough to have happened before we had the (still VERY limited) infra to do so that we do today.

Yup, it can be – we should change Clang’s attribute tablegen to better handle value dependent arguments more generally though, rather than play whack-a-mole with individual attributes.

1 Like

I guess more generally, gnu::constructor does pair nicely with gnu::init_priority and gnu::destructor, so at least those three should behave the same.

I have [approximately] no idea how the clang attribute gen stuff works, but I guess there’s something useful that’s missing in between something like IntArgument (must be int, must not be dependent) and ExprArgument (literally anything) - like a MaybeDependentIntArgument or something (this is why nobody asks me to name things).

1 Like

IMO, we should just change IntArgument to just work dependently always. It is probably a pretty sizable refactor to make this work, but thats the ‘sensible’ way to me.


Agreed, and we should support BoolArgument at the same time. The other arguments are a bit less clear whether we should try to automate support or not.

Also, agreed that this is likely a large refactoring to accomplish. But it then solves the problem for ~20 attributes instead of ~3 and sets the path for future arguments as well, which is nice.

1 Like