Where do attributes get merged?

I'm starting to look into Aaron Ballman's request to diagnose the cases
where the OptimizeNone attribute "wins" over things like MinSize. This
is leading me through a maze of twisty little passages all different.

One case that came up in my experiments is when you have (say) always_inline
on a function declaration, and optnone on the function's definition. The
existing detection logic seems to work only when the conflicting attributes
are on the same declaration. Seems like there would have to be some place
where attributes from the two declarations would be mashed together, but I'm
not finding it; could somebody please point me in the right direction?
Thanks,
--paulr

IIRC, attribute merging largely happens in mergeDeclAttribute: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?revision=222906&view=markup#l2124

Yes, you're looking for Sema::mergeDeclAttributes. You're also correct
that the current behavior only works when the attributes are on the
same declaration.

However, from memory, I don't think that situation of yours should
result in well-formed code. IIRC, the definition must not attempt to
declare new attributes (aside from some keyword-like ones) that do not
also appear on the declaration.

~Aaron

From: aaron.ballman@gmail.com [mailto:aaron.ballman@gmail.com] On Behalf
Of Aaron Ballman
Sent: Wednesday, December 10, 2014 5:50 AM
To: David Majnemer
Cc: Robinson, Paul; cfe-dev@cs.uiuc.edu Developers (cfe-dev@cs.uiuc.edu)
Subject: Re: [cfe-dev] Where do attributes get merged?

Yes, you're looking for Sema::mergeDeclAttributes. You're also correct
that the current behavior only works when the attributes are on the
same declaration.

Awesome, thanks guys. Exactly what I needed.

However, from memory, I don't think that situation of yours should
result in well-formed code. IIRC, the definition must not attempt to
declare new attributes (aside from some keyword-like ones) that do not
also appear on the declaration.

Hmm I poked around in online docs for both clang and gcc, I'm not finding
any statement like that. Looking at the code, the behavior seems to be:
- If we've already seen a definition, a new declaration can't add any
  attributes. Except for a couple of special cases.
- Otherwise, attributes that are on the old declaration, and are inheritable,
  are propagated to the new declaration (again with a few special cases).

The use case for __attribute__((optnone)) is such that having it on the
definition but not the declaration would be the normal case. I think it
would be reasonable to say that when optnone conflicts with something else,
the attribute on the definition wins.

How does that sound?
--paulr

From: aaron.ballman@gmail.com [mailto:aaron.ballman@gmail.com] On Behalf
Of Aaron Ballman
Sent: Wednesday, December 10, 2014 5:50 AM
To: David Majnemer
Cc: Robinson, Paul; cfe-dev@cs.uiuc.edu Developers (cfe-dev@cs.uiuc.edu)
Subject: Re: [cfe-dev] Where do attributes get merged?

Yes, you're looking for Sema::mergeDeclAttributes. You're also correct
that the current behavior only works when the attributes are on the
same declaration.

Awesome, thanks guys. Exactly what I needed.

However, from memory, I don't think that situation of yours should
result in well-formed code. IIRC, the definition must not attempt to
declare new attributes (aside from some keyword-like ones) that do not
also appear on the declaration.

Hmm I poked around in online docs for both clang and gcc, I'm not finding
any statement like that.

I may have been mis-remembering as well. :wink:

Looking at the code, the behavior seems to be:
- If we've already seen a definition, a new declaration can't add any
  attributes. Except for a couple of special cases.
- Otherwise, attributes that are on the old declaration, and are inheritable,
  are propagated to the new declaration (again with a few special cases).

The use case for __attribute__((optnone)) is such that having it on the
definition but not the declaration would be the normal case.

GNU-style attributes generally are not definition-only. In fact, I
believe we only allow that as an extension for attributes known to
GCC. Since optnone isn't a GCC attribute (at this time), it's not
technically an extension, but I suspect calling it the "normal case"
is a bit of a stretch.

I think it
would be reasonable to say that when optnone conflicts with something else,
the attribute on the definition wins.

How does that sound?

That may be feasible for optnone, but I'm not certain I like it in the
general sense. Attributes appearing on the definition but not the
declaration can change the behavior in a substantial way -- for
instance, a noreturn attribute. Also, this behavior will depend on the
spelling of the attribute given. A __declspec cannot be added to a
function definition if it is absent on a function declaration, but the
reverse isn't true.

~Aaron

From: aaron.ballman@gmail.com [mailto:aaron.ballman@gmail.com] On Behalf
Of Aaron Ballman
Sent: Wednesday, December 10, 2014 11:50 AM
To: Robinson, Paul
Cc: David Majnemer; cfe-dev@cs.uiuc.edu Developers (cfe-dev@cs.uiuc.edu)
Subject: Re: [cfe-dev] Where do attributes get merged?

>> From: aaron.ballman@gmail.com [mailto:aaron.ballman@gmail.com] On
Behalf
>> Of Aaron Ballman
>> Sent: Wednesday, December 10, 2014 5:50 AM
>> To: David Majnemer
>> Cc: Robinson, Paul; cfe-dev@cs.uiuc.edu Developers (cfe-
dev@cs.uiuc.edu)
>> Subject: Re: [cfe-dev] Where do attributes get merged?
>>
>> Yes, you're looking for Sema::mergeDeclAttributes. You're also correct
>> that the current behavior only works when the attributes are on the
>> same declaration.
>
> Awesome, thanks guys. Exactly what I needed.
>
>> However, from memory, I don't think that situation of yours should
>> result in well-formed code. IIRC, the definition must not attempt to
>> declare new attributes (aside from some keyword-like ones) that do not
>> also appear on the declaration.
>
> Hmm I poked around in online docs for both clang and gcc, I'm not
finding
> any statement like that.

I may have been mis-remembering as well. :wink:

> Looking at the code, the behavior seems to be:
> - If we've already seen a definition, a new declaration can't add any
> attributes. Except for a couple of special cases.
> - Otherwise, attributes that are on the old declaration, and are
inheritable,
> are propagated to the new declaration (again with a few special
cases).
>
> The use case for __attribute__((optnone)) is such that having it on the
> definition but not the declaration would be the normal case.

GNU-style attributes generally are not definition-only. In fact, I
believe we only allow that as an extension for attributes known to
GCC. Since optnone isn't a GCC attribute (at this time), it's not
technically an extension, but I suspect calling it the "normal case"
is a bit of a stretch.

Ah, by "normal case" I meant that the usual usage pattern for optnone would
be to attach it to the definition rather than the declaration. Not that
my proposed behavior for optnone was the "normal case" for attributes in
general.
--paulr