This is an archive of the discontinued LLVM Phabricator instance.

Allow all supportable attributes to be used with #pragma clang attribute.
ClosedPublic

Authored by rsmith on Aug 30 2018, 2:18 PM.

Details

Summary

We previously disallowed use of undocumented attributes with #pragma clang
attribute, but the justification for doing so was weak and it prevented many
reasonable use cases.

Diff Detail

Repository
rL LLVM

Event Timeline

rsmith created this revision.Aug 30 2018, 2:18 PM
rsmith added a reviewer: tra.Aug 30 2018, 2:25 PM

+@tra for CUDA attributes

test/Misc/pragma-attribute-supported-attributes-list.test
1 ↗(On Diff #163407)

It's probably easiest to review the list of newly-supported attributes here. Some of these look tenuous, some of them look like obvious wins; I think we should go through the list and see if any seem like they should not be supported by the pragma.

50 ↗(On Diff #163407)

I think __attribute__((ext_vector_type)) is a good candidate to *not* have #pragma clang attribute support. A type modifier like this really should only be declared as part of declaring the type. Opinions?

dexonsmith added inline comments.Aug 30 2018, 2:49 PM
test/Misc/pragma-attribute-supported-attributes-list.test
50 ↗(On Diff #163407)

The same argument might hold for most type attributes. I have trouble imagining someone using this, but it's also hard to see how supporting it would lead to bugs in user code. It seems a bit simpler to support everything.

I don't have a strong opinion though.

tra added inline comments.Aug 30 2018, 3:05 PM
test/Misc/pragma-attribute-supported-attributes-list.test
27–32 ↗(On Diff #163407)

I don't see much practical use of this pragma for CUDA, but I also don't have any specific objections.
LGTM.

Theoretically we could use it to apply __host__ __device__ attribute to some portable headers-only library so we could use it on device side. In practice, though, there usually will be few things that would have to remain host-only (anything involving file-io, for example) and we would need to be more selective in applying the attributes or have a way to remove them from a subset of objects later on.

rsmith marked an inline comment as done.Aug 30 2018, 5:33 PM
rsmith added inline comments.
test/Misc/pragma-attribute-supported-attributes-list.test
27–32 ↗(On Diff #163407)

The pragma is already flexible enough to allow selectively applying attributes to a subset of the declarations in its scope:

https://clang.llvm.org/docs/LanguageExtensions.html#subject-match-rules

kristina added a subscriber: kristina.EditedAug 30 2018, 5:50 PM

LGTM.

Would allow for less repetition, ie. always_inline is an excellent candidate for cases like small functions that act as wrappers around bits of context sensitive inline asm and are usually clustered together in a header, a lot of embedded use cases come to mind, same goes for alias. Considering that everyone may have their own niche use cases for attributes, I think that's a very convenient change.

I don't think init_priority makes a lot of sense however, would essentially do nothing if I recall the semantics right since it would just cause a clash.

Also added a remark about objc_root_class making no sense. Independent classes that do not derive from the root class are perfectly fine but more than one root class violates the principle that as a general rule, in ObjC, all objects have a common ancestor that implements the basic NSObject protocol. Having two root classes would cause a diagnostic, or possibly trip an assert in pragma form.

kristina added inline comments.Aug 30 2018, 6:04 PM
test/Misc/pragma-attribute-supported-attributes-list.test
58 ↗(On Diff #163407)

Adding remark about init_priority as an inline comment. Wouldn't make sense semantically as it defeats the point of explicitly specifying static init order and cause a clash instead and causes ordering to become undefined again (as well as issuing a diagnostic I think).

kristina added inline comments.Aug 30 2018, 6:19 PM
test/Misc/pragma-attribute-supported-attributes-list.test
100 ↗(On Diff #163407)

There is only one root class in a given runtime (ie. NSObject for objc4, or Object for older Apple runtimes, ObjFW also has a different root class). Having more than one makes no sense especially in the same lexical context as there are no use cases I can think of where you would have more than one active ObjC runtime within a process.

rsmith marked an inline comment as done.Aug 30 2018, 7:11 PM

Based on the comments so far, my inclination is to allow #pragma clang attribute on all these attributes, including the highlighted ones where it's hard to think of cases where it'd be useful. I think our policy should be that we only disable support for attributes where the pragma is actually meaningless (we couldn't figure out where to apply the attribute, for example), not merely ones where we cannot imagine a use. Please comment if you disagree, of course! :)

test/Misc/pragma-attribute-supported-attributes-list.test
58 ↗(On Diff #163407)

As far as I can tell, it's valid to have multiple globals with the same init_priority, and they are initialized in the order in which they are declared within a source file. This also seems useful when combined with the pragma (as a way of moving the initialization of a group of globals earlier / later, without affecting their relative order).

100 ↗(On Diff #163407)

Thanks. Yes, this attribute probably doesn't make very much sense to use in conjunction with the pragma.

So, do we explicitly disallow it, or do we allow it with the expectation that it's likely that no-one will ever want to use it? (That is, do we want to disallow cases that are not useful, or merely cases that are not meaningful?) I don't have a strong opinion here, but I'm mildly inclined towards allowing the pragma on any attribute where it's meaningful, as there may be useful uses that we just didn't think of, and it costs nothing to permit.

kristina added inline comments.Aug 30 2018, 7:29 PM
test/Misc/pragma-attribute-supported-attributes-list.test
100 ↗(On Diff #163407)

Yes in theory it could only be used on a single interface in which case it would be perfectly valid. Otherwise when used incorrectly it would issue a diagnostic. As per your inclination of allowing it for all attributes I would say leave it allowed, as it can be used in a correct way. Diagnostics are sufficient enough to point out when it happens to apply the attribute to more than one interface.

So given your comment, I would say leave it as allowed.

kristina added a comment.EditedAug 31 2018, 3:46 AM

Giving it a second glance, just as an idea, maybe it's better to leave ObjC pragmas out for now, for another more narrower-scope revision/review specific to ObjC(/Swift)? Since they could cause incorrect code generation if combined in odd ways (as well as making no sense) especially with Automatic Reference Counting. For example a function annotated as returning a retained object while at the same time returning with release, and also a bridge annotation, may just miss the sema check and fail at runtime instead, which could be fairly erratic as it may vary depending on the autoreleasepool state as well as the runtime being used and could turn into a difficult bug to debug if it ever happened in the wild. I think semantic checker should catch the non-ObjC cases but only some ObjC cases. Another concern is Swift with Apple runtime and ObjC <=> Swift bridged objects (when Swift classes inherit ObjC classes or even interact with them) may introduce even more complications, and Swift patches and integration doesn't happen as part of mainline LLVM development, which complicates code review. Rest of it looks good however, not sure what you want to to do with the ObjC pragmas, they could be left in and re-reviewed later since that would mean they would end up in Swift development integration tree too, or left out and reviewed in a separate revision, since rest of this looks good?

I'm not really sure which is better, so I don't really want to suggest one or the other, just bringing it up as an option.

aaron.ballman added inline comments.Aug 31 2018, 5:22 AM
test/Misc/pragma-attribute-supported-attributes-list.test
50 ↗(On Diff #163407)

I don't think #pragma clang attribute should apply to types -- types show up in far too many places and attributes on types changes the fundamental meaning of types a bit too much for my tastes. I'd prefer users annotate the type directly.

dexonsmith added inline comments.Aug 31 2018, 6:22 AM
test/Misc/pragma-attribute-supported-attributes-list.test
50 ↗(On Diff #163407)

types show up in far too many places and attributes on types changes the fundamental meaning of types a bit too much for my tastes

I don't see how region-based attributes on type aliases is really any different from region-based annotations on variables.

Moreover, I'm strongly against disallowing use of this pragma on type aliases in general: as a vendor, we've already shipped that support for a number of attributes. Most critically, ExternalSourceSymbol applies to type aliases, and handling ExternalSourceSymbol was our primary motivation for adding this feature (the alternative was to add yet-another-attribute-specific-#pragma).

100 ↗(On Diff #163407)

So, do we explicitly disallow it, or do we allow it with the expectation that it's likely that no-one will ever want to use it? (That is, do we want to disallow cases that are not useful, or merely cases that are not meaningful?)

I'd prefer to only disallow cases that are not meaningful.

rsmith updated this revision to Diff 163584.Aug 31 2018, 1:38 PM

Don't add #pragma clang attribute support for 'mode' and 'ext_vector_type'.

aaron.ballman accepted this revision.Sep 4 2018, 1:33 PM

Thank you for pointing out that the new form of type attributes aren't automatically opted in from this change. With that (and the two problematic attributes opted out), this LGTM.

This revision is now accepted and ready to land.Sep 4 2018, 1:33 PM
arphaman accepted this revision.Sep 4 2018, 1:47 PM

LGTM, Thank you!

This revision was automatically updated to reflect the committed changes.