This is an archive of the discontinued LLVM Phabricator instance.

parse: process GNU and standard attributes on top-level decls
ClosedPublic

Authored by compnerd on Nov 14 2022, 1:25 PM.

Details

Summary

We would previously reject valid input where GNU attributes preceded the
standard attributes on top-level declarations. A previous attribute
handling change had begun rejecting this whilst GCC does honour this
layout. In practice, this breaks use of extern "C" attributed
functions which use both standard and GNU attributes as experienced by
the Swift runtime.

Objective-C deserves an honourable mention for requiring some additional
special casing. Because attributes on declarations and definitions
differ in semantics, we need to replicate some of the logic for
detecting attributes to declarations to which they appertain cannot be
attributed. This should match the existing case for the application of
GNU attributes to interfaces, protocols, and implementations.

Take the opportunity to split out the tooling tests into two cases: ones
which process macros and ones which do not.

Special thanks to Aaron Ballman for the many hints and extensive rubber
ducking that was involved in identifying the various places where we
accidentally dropped attributes.

Fixes: #58229

Diff Detail

Event Timeline

compnerd created this revision.Nov 14 2022, 1:25 PM
Herald added a project: Restricted Project. · View Herald TranscriptNov 14 2022, 1:25 PM
Herald added a subscriber: jdoerfert. · View Herald Transcript
compnerd requested review of this revision.Nov 14 2022, 1:25 PM
Herald added a project: Restricted Project. · View Herald TranscriptNov 14 2022, 1:25 PM
compnerd edited the summary of this revision. (Show Details)Nov 14 2022, 1:29 PM
ymandel added inline comments.
clang/unittests/Tooling/SourceCodeTest.cpp
249–271

Thanks for trying to fix these! The changed test cases seem to be doing two things at once: macros and attributes, and I don't remember why. We should test the behavior separately. So, I think you're new test cases are good regardless. But, we still want the old tests to test the behavior for attributes that are hidden behind a macro, since this is used not infrequently in my exprience.

IIUC, the current code isn't properly handling attributes that appear inside macros, which is why this fix breaks the code. Specifically, it is not considering the case that the location in Attr->getLocation() is in a macro, while Range.getBegin() is in the original file, and hence the locations are not comparable. I'm surprised this ever worked, tbh.

My preference would be to update the code, if you know how, so that both the old and new tests pass. But, I realize this may be a lot to ask. So, at the least, please comment out, but keep, the old tests; or, copy the old tests to a new test and mark it disabled. Either way, prefix with a FIXME indicating the issue.

WDYT?

Adding some additional reviewers for more awareness.

compnerd added inline comments.Nov 15 2022, 9:59 AM
clang/unittests/Tooling/SourceCodeTest.cpp
249–271

Unfortunately, I couldn't figure out how to track through the expansion so I am going to take you up on the commented out case option.

compnerd updated this revision to Diff 475530.Nov 15 2022, 11:07 AM

Add unsupported test cases

compnerd marked an inline comment as done.Nov 15 2022, 11:13 AM
compnerd updated this revision to Diff 475570.Nov 15 2022, 2:02 PM
compnerd edited the summary of this revision. (Show Details)
compnerd edited the summary of this revision. (Show Details)
compnerd edited the summary of this revision. (Show Details)
aaron.ballman edited reviewers, added: eandrews; removed: elizabethandrews.Nov 16 2022, 6:34 AM

I added the wrong account for Elizabeth, so fixing that up.

ymandel added inline comments.Nov 16 2022, 9:00 AM
clang/unittests/Tooling/SourceCodeTest.cpp
259–268

Added tests, here and below, look good to me. Thanks!

arphaman added inline comments.Nov 16 2022, 6:00 PM
clang/lib/Parse/ParseObjc.cpp
70

I think it might be better to still report this error at the location of the @ token (Tok.getLocation()). This will let us report the error at the actual Objective-C keyword which the user should note should not be used with the attribute.

compnerd updated this revision to Diff 476163.Nov 17 2022, 9:33 AM
compnerd marked an inline comment as done.
arphaman accepted this revision.Nov 17 2022, 10:16 AM

Thanks, this LGTM. You might want to get another reviewers approval as well.

This revision is now accepted and ready to land.Nov 17 2022, 10:16 AM

Thank you for working on this, I know it was a slog! I think this is pretty close to ready, though you should definitely add a release note about the changes.

clang/include/clang/Parse/Parser.h
1605–1606

Should we rename Attrs to DeclaratorAttrs or something along those lines, so it's easier for someone to distinguish which attributes go where? (Same suggestion applies throughout the review.)

clang/lib/Parse/ParseObjc.cpp
68–70

llvm::for_each?

clang/lib/Parse/ParseOpenMP.cpp
1997

We can sink this down to the only place it's used in the function, right?

clang/lib/Parse/Parser.cpp
733–734

We probably could use some comments here explaining why we parse some into one container and others into another container.

1100–1101

How sure are you that this isn't overwriting existing range data that's potentially relevant? e.g., where declaration specifiers and attributes are mixed together such that the attribute range doesn't cover all of the declaration specifiers?

clang/test/Parser/attr-order.cpp
20

This makes me happy!!

compnerd marked 5 inline comments as done.Nov 21 2022, 10:41 AM
compnerd added inline comments.
clang/include/clang/Parse/Parser.h
1605–1606

Yes, DeclAttrs would be much nicer, but I wanted to get everything right before doing that and then forgot. Thanks for the reminder.

clang/lib/Parse/Parser.cpp
1100–1101

I don't believe it can - the range hasn't been setup yet when coming into this function, only the storage has been allocated. This is the first place where we are initializing the source range. If there are other unstated invariants, it would be nice to have some sort of assertion for them.

compnerd updated this revision to Diff 476949.Nov 21 2022, 10:42 AM
compnerd marked an inline comment as done.

Address review feedback

aaron.ballman added inline comments.Nov 21 2022, 10:42 AM
clang/lib/Parse/Parser.cpp
1100–1101

Ah, so we could perhaps assert that the range is invalid on entry and leave a comment explaining why we're asserting/what's going on?

aaron.ballman accepted this revision.Nov 21 2022, 10:46 AM

LGTM aside from the question about whether we want to add an assert or not (I don't insist on adding one) and adding a release note (which doesn't need further review unless you want it). Thank you for these changes!

This revision was landed with ongoing or failed builds.Nov 21 2022, 2:35 PM
This revision was automatically updated to reflect the committed changes.