Semantic checks and template instantiations

Hello cfe-dev.

I am trying to perform additional checks on the alignment of C++ variables (outputting diagnostic messages if the checks trigger), and the place where it feels more natural to do so is in Sema::ActOnVariableDeclarator. There is already a check for under-alignment there (a call to Sema::CheckAlignasUnderalignment) so I thought I was on the right track.
However I am finding that my checks don’t trigger when the variable being declared/defined is a template instantiation.

Suppose for the sake of example that I wanted to add a check that warns if the alignment exceeds a certain number of CharUnits, say 32. If I put the check in ActOnVariableDeclarator right after the under-alignment check, it does catch this case:

struct attribute(( aligned(64) )) my_aligned { int x; }
// …
my_aligned my_variable; // Diagnostic here

However it does not catch this case:

template class attribute(( aligned(64) )) my_aligned_template {
int x;
void foo (T param) { /* some code */ }
}
// …
my_aligned_template my_variable; // No diagnostic here, but the IR has the right alignment (64)

I am using ASTContext::getDeclAlign to get the alignment of the variable in the declaration, as the documentation says that it returns a conservative alignment for the variable, and it’s actually the same function used at CodeGen time to determine the alignment.
However I seem to understand that at that point (when ActOnVariableDeclarator runs) the template instantiation hasn’t been processed yet and therefore the type of the variable is still a dependent type (despite the fact that the layout of my_aligned_template does not in fact depend on T, but I accept that in the general case it can do). This means that the alignment is unknown at that stage and I can’t really check it.
In fact, I have noticed that Sema::CheckAlignasUnderalignment (which is my reference for implementing the checks) also skips dependent and incomplete types.

Of course when ASTContext::getDeclAlign is used later on in CodeGen everything is known about variables and their types, so I could move my checks there, but it would feel wrong to do the checks while IR is being generated, I think Sema should be the right place to perform semantic checks.

Can anyone point me in the right direction? Is there a more sensible place than ActOnVariableDeclarator where I can put my additional alignment checks?

Thanks,
Dario Domizioli
SN Systems - Sony Computer Entertainment Group

Hello again, cfe-dev.

I’m back from holidays and I’m looking at this again.
I’m also having trouble performing the checks at CodeGen time since there are many places where variables are emitted; but still it feels wrong to perform checks during CodeGen.

Any ideas where it would be best to perform alignment checks?

Thanks,
Dario Domizioli
SN Systems - Sony Computer Entertainment Group

We perform similar alignment checks in ‘Sema::AddAlignedAttr’ like ensuring that the number is a power-of-two and less than 8192.
If I understand you correctly, you would want to add your checks there.

Thanks for the suggestion, David.

It’s a step in the right direction, but it still doesn’t quite work for me. The checks in Sema::AddAlignedAttr are performed when the alignment attribute is applied to a declaration, but not when a declared variable is implicitly aligned because it has an aligned type. My goal is to detect aligned variables.
For instance, consider the following code:

struct A { int x; };
struct attribute(( aligned (64) )) B { int y; };
template struct attribute(( aligned (64) )) C { int z; void foo (T t) {} };
A a;
A al_a attribute(( aligned (64) ));
B b;
C c;

If the checks are performed in Sema::AddAlignedAttr, they will flag the definition of “struct B” and the template “struct C”, plus the explicitly aligned variable “al_a”, but they will not flag the definition of either variable “b” or “c”.
So it’s performing the check for templates too, which is great, but only when the type is defined, not when a variable is defined.

For the check I actually want to perform, things are even more complex as I need to flag “over-aligned” variables only in some cases (I need to check some other properties of the variable). In my use case having an “over-aligned” type is allowed provided that no “problematic” variables are defined using it.
So I need the check to be performed on the variable, not on the attribute (which is why I was doing the check in Sema::ActOnVariableDeclarator).

Cheers,

Dario Domizioli
SN Systems - Sony Computer Entertainment Group