This is an archive of the discontinued LLVM Phabricator instance.

[clang] Allow gnu::aligned attribute to work with templated type alias declarations
Needs ReviewPublic

Authored by leonardchan on Feb 7 2023, 4:00 PM.

Details

Summary

Prior to this, the following would fail:

template <typename T>
using NaturallyAligned [[gnu::aligned(sizeof(T))]] = T;

struct S { char x[2]; };
using AlignedS = NaturallyAligned<S>;
static_assert(alignof(AlignedS) == 2);  // alignof(AlignedS) == 1

This is because clang ignores attributes on type aliases when evaluating type info and instead resolves to alignment of the replacement type T.

This patch attempts to check if the associated type declaration is an alias that contains an attribute and return whatever the value is indicated by the alignment expression.

Diff Detail

Event Timeline

leonardchan created this revision.Feb 7 2023, 4:00 PM
Herald added a project: Restricted Project. · View Herald TranscriptFeb 7 2023, 4:00 PM
leonardchan requested review of this revision.Feb 7 2023, 4:00 PM
rsmith added inline comments.Feb 13 2023, 3:06 PM
clang/lib/AST/ASTContext.cpp
2154

I don't think this approach is going to work out well. There are many cases this gets wrong, fixing them would require reinventing template substitution here, and generally we shouldn't be doing this substitution as part of alignment computation at all -- we should have TreeTransform produce the right alignment value during template instantiation and just pull it back out of the Type here. We can't really use the same approach as we do for TypedefDecls, though, because we don't instantiate a TypeAliasDecl for each use of a TypeAliasTemplateDecl, so there's nowhere to hang an instantiated attribute. But the handling for TypedefTypes is also fairly painful, so I think we should be considering an approach that makes both of them more elegant. Here's what I suggest:

  • We add a new sugar-only Type subclass that represents an alignment attribute. Maybe we can model this as an AttributedType for the AlignedAttr, or maybe we create a new kind of type node.
  • We translate AlignedAttrs on typedef and type alias declarations into this new kind of Type wrapping the declared type.
  • We make getTypeInfoImpl special-case that type sugar node instead of special-casing TypedefType sugar.
  • We make sure that TreeTransform properly instantiates the new node, in particular performing substitution within the argument.
2577–2583

Looking for a SubstTemplateTypeParm will mean that you don't handle cases like:

template<int N> using AlignedChar [[gnu::aligned(N)]] = char;

Instead, it would be better to add the special treatment to TemplateSpecializationTypes for which isTypeAlias is true... but see my other comment.

Adding Erich as attributes code owner.

clang/lib/AST/ASTContext.cpp
2154

I think this approach makes sense to me, but it's worth noting: the alignment attributes (vendor specific or standard) are declaration attributes and not type attributes. I think this is a design mistake; alignment is a fundamental property of a type (see http://eel.is/c++draft/basic.align#1), so I'm in favor of modeling this as a type attribute, but the standard alignas attribute does not have type semantics: http://eel.is/c++draft/dcl.align#1. Should we approach the standards committees about this or are we not concerned about alignas behavior?

(If we expect alignas to be a declaration attribute and [[gnu::aligned]] to be a type attribute, another question is whether we should split them in Attr.td.)

erichkeane added inline comments.Feb 14 2023, 7:17 AM
clang/lib/AST/ASTContext.cpp
2154

IMO, the idea of doing this via this visitor is incorrect, we should just make sure the instantiated decl of the type alias to get the attribute, we do similar things for function decls.