This is an archive of the discontinued LLVM Phabricator instance.

Add an optional string argument to DeprecatedAttr for Fix-It.
ClosedPublic

Authored by manmanren on Mar 3 2016, 12:34 PM.

Details

Summary

This can be used to display Fix-Its.
We only add this to GNU attributes. Since it now has two optional arguments, and the common parsing does not handle "replacement = ", we use custom parsing for DeprecatedAttr.

Diff Detail

Repository
rL LLVM

Event Timeline

manmanren updated this revision to Diff 49768.Mar 3 2016, 12:34 PM
manmanren retitled this revision from to Add replacement = "xxx" to DeprecatedAttr..
manmanren updated this object.
manmanren added reviewers: dexonsmith, rjmccall.
manmanren added a subscriber: cfe-commits.
aaron.ballman added a subscriber: aaron.ballman.

I like the idea of a potential fixit being provided by the attribute, but I do not agree with the way the feature is surfaced in this patch.

For the GNU-style attribute, the named argument functionality is sufficiently novel syntax that I would strongly like to avoid it, especially since attribute((deprecated)) is supported by multiple compilers.

We should not be adding this functionality to the C++-style attribute in the gnu namespace; that's not our vendor namespace to modify. I wouldn't be opposed to adding a clang namespace where we support this feature, however.

We definitely need to make sure we are not modifying the functionality for the C++ standards-based attribute, or the __declspec based attribute (for pretty printing, as well as parsing, etc).

So this change is missing a lot of tests to make sure we do not support this feature in places where it doesn't belong.

include/clang/Basic/Attr.td
716 ↗(On Diff #49768)

Would you mind adding some documentation to the attribute since we're changing it?

lib/Parse/ParseDecl.cpp
1048 ↗(On Diff #49768)

This also gets called for attributes parsed in the gnu:: namespace, which means that you are modifying the behavior of gnu::deprecated(), which we should not do unless GCC also supports this feature.

1068 ↗(On Diff #49768)

I assume this was meant to do something useful?

1070 ↗(On Diff #49768)

This now makes the attribute behave differently than __attribute__((deprecated)) because you can have this odd named-argument behavior. I would strongly prefer this be an actual optional parameter instead of using this approach. e.g., __attribute__((deprecated("", "fixit"))).

lib/Sema/SemaDeclAttr.cpp
5074 ↗(On Diff #49768)

This check should be moved above the extension warning above -- we only want to diagnose the extension if the attribute is actually applied.

test/SemaCXX/cxx11-attr-print.cpp
16 ↗(On Diff #49768)

This is a bug; we should not be hijacking the gnu attribute space.

18 ↗(On Diff #49768)

I would like a test that verifies we don't print an empty fixit literal when using the C++14 [[deprecated]] attribute. Same for __declspec(deprecated).

Hi Aaron,

Thanks for the review!

I like the idea of a potential fixit being provided by the attribute, but I do not agree with the way the feature is surfaced in this patch.

For the GNU-style attribute, the named argument functionality is sufficiently novel syntax that I would strongly like to avoid it, especially since attribute((deprecated)) is supported by multiple compilers.

I suggested replacement = "" mostly for its explicitness, especially when we already have an optional message argument "".
If a user only want to specify replacement without a message, we can say deprecated(replacement = "xxx")
With 'replacement =`, the user will need to specify an empty message.
But your concern makes sense too. We can support the following:
deprecated("xxx") --> a message
deprecated("xxx, "fixit") --> a message and a fixit

We should not be adding this functionality to the C++-style attribute in the gnu namespace; that's not our vendor namespace to modify.

I believe the patch currently does not change the C++-style attribute. Of course, I should add testing cases to verify.

I wouldn't be opposed to adding a clang namespace where we support this feature, however.

We definitely need to make sure we are not modifying the functionality for the C++ standards-based attribute

Is this ("the C++ standards-based attribute") the same as "the C++-style attribute" you mentioned above?

, or the declspec based attribute (for pretty printing, as well as parsing, etc).
Yes, I should add testing cases to make sure
declspec is not changed at all with this patch.

So this change is missing a lot of tests to make sure we do not support this feature in places where it doesn't belong.

include/clang/Basic/Attr.td
716 ↗(On Diff #49768)

Yes, I should.

lib/Parse/ParseDecl.cpp
1048 ↗(On Diff #49768)

Yes, I will fix this.

1068 ↗(On Diff #49768)

Yes, I should emit a diagnostic.

lib/Sema/SemaDeclAttr.cpp
5074 ↗(On Diff #49768)

Agree.

test/SemaCXX/cxx11-attr-print.cpp
16 ↗(On Diff #49768)

Yes, I will fix this.

18 ↗(On Diff #49768)

Will do.

aaron.ballman edited edge metadata.Mar 9 2016, 11:45 AM

Hi Aaron,

Thanks for the review!

I like the idea of a potential fixit being provided by the attribute, but I do not agree with the way the feature is surfaced in this patch.

For the GNU-style attribute, the named argument functionality is sufficiently novel syntax that I would strongly like to avoid it, especially since attribute((deprecated)) is supported by multiple compilers.

I suggested replacement = "" mostly for its explicitness, especially when we already have an optional message argument "".
If a user only want to specify replacement without a message, we can say deprecated(replacement = "xxx")
With 'replacement =`, the user will need to specify an empty message.

I do like the explicit nature of this approach, but I'm worried about it being too novel. For instance, would this compel GCC to implement a similar parsing feature since they also support the deprecated attribute, that sort of thing. Also, it feels like a bit of an odd design in C and C++ since nothing else in the language supports argument passing by name like that (and I would really hate to see us use = blah only to find out that C++ someday standardizes on something different).

But your concern makes sense too. We can support the following:
deprecated("xxx") --> a message
deprecated("xxx, "fixit") --> a message and a fixit

I think this is the correct approach, even with multiple optional arguments.

We should not be adding this functionality to the C++-style attribute in the gnu namespace; that's not our vendor namespace to modify.

I believe the patch currently does not change the C++-style attribute. Of course, I should add testing cases to verify.

I believe the patch does change the C++-style attribute in the gnu namespace, as best I can tell. e.g., it would now allow: `[[gnu::deprecated("something", "a fixit")]]`. We need to be careful not to allow this unless GCC allows the same syntax, otherwise we are hijacking their vendor attribute namespace with something incompatible.

I wouldn't be opposed to adding a clang namespace where we support this feature, however.

We definitely need to make sure we are not modifying the functionality for the C++ standards-based attribute

Is this ("the C++ standards-based attribute") the same as "the C++-style attribute" you mentioned above?

This is talking about the C++14 [[deprecated]] attribute. We want to make sure we don't allow [[deprecated("foo", "fixit")]], which I don't think your patch does (but we should have tests ensuring it).

, or the declspec based attribute (for pretty printing, as well as parsing, etc).
Yes, I should add testing cases to make sure
declspec is not changed at all with this patch.

So this change is missing a lot of tests to make sure we do not support this feature in places where it doesn't belong.

I do like the explicit nature of this approach, but I'm worried about it being too novel. For instance, would this compel GCC to implement a similar parsing feature since they also support the deprecated attribute, that sort of thing. Also, it feels like a bit of an odd design in C and C++ since nothing else in the language supports argument passing by name like that (and I would really hate to see us use = blah only to find out that C++ someday standardizes on something different).

This makes sense to me. We also want to add this to the "availability" attribute, and since that already uses named arguments, I think we should use the "replacement=" syntax there.

Uploading a new patch addressing Aaron's comments:
1> Add an optional string argument for fix-it, instead of the original proposal of named argument Replacement = "xxx"
This actually simplifies the patch a lot
2> Add testing cases to make sure we don't accept a fix-it argument for declspec, c++11 attribute, gnu namespace attribute
3> Change AST printing to make sure we only dump the fix-it argument for gnu style attribute

Cheers,
Manman

manmanren updated this revision to Diff 50374.Mar 10 2016, 4:11 PM
manmanren retitled this revision from Add replacement = "xxx" to DeprecatedAttr. to Add an optional string argument to DeprecatedAttr for Fix-It..
manmanren edited edge metadata.
manmanren added inline comments.
utils/TableGen/ClangAttrEmitter.cpp
1234 ↗(On Diff #50374)

This does not look pretty. Maybe we can implement a function writeDeprecatedValue that can skip the second argument if it is empty?

aaron.ballman added inline comments.Mar 11 2016, 2:43 PM
include/clang/Basic/Attr.td
726 ↗(On Diff #50374)

The formatting here is a bit strange.

lib/Sema/SemaDeclAttr.cpp
5143 ↗(On Diff #50374)

This should move back down below the extension warning (the effect is the same, but logically we want to warn before attaching).

utils/TableGen/ClangAttrEmitter.cpp
1234 ↗(On Diff #50374)

I wouldn't be opposed to that approach; we already do it for writeAvailabilityValue(), so another one for deprecated wouldn't be that horrible.

manmanren updated this revision to Diff 50502.Mar 11 2016, 5:15 PM
manmanren marked 3 inline comments as done.

Upload patch to address review comments.

Thanks,
Manman

Aside from the missing attribute documentation, looks good to me.

Aside from the missing attribute documentation, looks good to me.

Hi Aaron,

Which document are you referring to? "include/clang/Basic/AttrDocs.td"?
We don't have a section for DeprecatedAttr, should I start one?

Cheers,
Manman

Aside from the missing attribute documentation, looks good to me.

Hi Aaron,

Which document are you referring to? "include/clang/Basic/AttrDocs.td"?

Yes, AttrDocs.td that you then reference in to Attr.td.

We don't have a section for DeprecatedAttr, should I start one?

Yes, please! We used to get away with relying on GCC to document the attribute, so now that we're adding Clang-specific behavior, we should bite the bullet and document the attribute properly. :-)

Thanks!

manmanren updated this revision to Diff 50682.Mar 14 2016, 5:24 PM
aaron.ballman accepted this revision.Mar 16 2016, 7:05 AM
aaron.ballman edited edge metadata.

One small documentation nit, but I'm fine with you fixing it then committing (no need for another round of review). Thanks!

include/clang/Basic/AttrDocs.td
2189 ↗(On Diff #50682)

"When spelled as `__attribute__((deprecated))`, the deprecated attribute can..."

"Otherwise, when spelled as `[[gnu::deprecated]] or [[deprecated]]`, the attribute can have one optional string argument which is the message to display when emitting the warning."

This revision is now accepted and ready to land.Mar 16 2016, 7:05 AM
This revision was automatically updated to reflect the committed changes.