This is an archive of the discontinued LLVM Phabricator instance.

[Clang][Sema][AIX][PowerPC] Emit byval alignment warning only when struct is passed to a function
ClosedPublic

Authored by ZarkoCA on Jan 27 2022, 4:21 AM.

Details

Summary

Previous warning went on whenever a struct with a struct member with alignment => 16
was declared. This led to too many false positives and led to diagnostic lit failures
due to it being emitted too frequently. Only emit the warning when such a struct and
that struct contains a member that has an alignment of 16 bytes is passed to a caller
function since this is where the potential binary compatibility issue with XL 16.1.0
and older exists.

Diff Detail

Event Timeline

ZarkoCA created this revision.Jan 27 2022, 4:21 AM
ZarkoCA requested review of this revision.Jan 27 2022, 4:21 AM
ZarkoCA retitled this revision from [AIX][PowerPC] Emit byval alignment warning only when struct member is passed to a function to [Clang][Sema][AIX][PowerPC] Emit byval alignment warning only when struct member is passed to a function.Jan 27 2022, 4:22 AM
ZarkoCA updated this revision to Diff 403857.Jan 27 2022, 7:01 PM
ZarkoCA edited the summary of this revision. (Show Details)
  • Fixed formatting
  • Fixed test case
  • Check for when Arg is nullptr
daltenty added inline comments.
clang/lib/Sema/SemaChecking.cpp
5203–5204

This function definitely seems like the right place for this check. Maybe let's update the comment here to reflect we are checking more than the original alignment property this describes.

clang/test/Sema/aix-attr-align.c
4

Why remove all the -Wno-aix-compat flag cases?

ZarkoCA updated this revision to Diff 404090.Jan 28 2022, 10:33 AM

Addressing comments:

  • Change comment before checkArgAlignment()
  • Add missing RUN lines
aaron.ballman added inline comments.Jan 28 2022, 10:52 AM
clang/include/clang/Sema/Sema.h
12693–12696

I'm not keen on passing both Arg and ArgTy such that they can get out of sync. Do all of the places calling CheckArgAlignment() have access to the Expr so that we can require it be passed (and drop the ArgTy parameter)?

clang/lib/Sema/SemaChecking.cpp
5219

There's no case where IgnoreParens() will return null.

5221

Are there other things you want to ignore here (such as IgnoreParenNoopCasts())? (I don't have an opinion the current code is wrong, just checking if those sort of cases were considered or not.)

5222–5223

This achieves the same thing, but with less work.

5225–5226
5227–5229
5230–5231
5233–5234

Should we be using char bits rather than a hardcoded value?

ZarkoCA added inline comments.Jan 28 2022, 1:29 PM
clang/include/clang/Sema/Sema.h
12693–12696

Thanks, that is something I overlooked.

It seems like I can do this everywhere except the call from Sema::CheckConstructorCall. Trying to figure out whether it's something I'm missing.

ZarkoCA updated this revision to Diff 404190.Jan 28 2022, 4:08 PM

Addressed some of the comments:

  • Applied code cleanup per suggestions
  • Used CharUnits instead of hard coded values
ZarkoCA marked 8 inline comments as done.Jan 28 2022, 4:27 PM
ZarkoCA added inline comments.
clang/include/clang/Sema/Sema.h
12693–12696

Thanks for the through review, I think I addressed everything but this comment. I agree with your concern about having Arg and ArgTy getting out of sync. I need to spend more time on that particular call from Sema::CheckConstructorCall and see what can be done.

clang/lib/Sema/SemaChecking.cpp
5221

Yes, thanks. I do have suspicions that IgnoreParens() may be too broad but I am worried that we may miss cases to diagnose otherwise.

nemanjai added a comment.EditedJan 30 2022, 9:04 AM

Would it make sense (and would it be possible) to check the linkage of the callee? Presumably calling something like
static void localfunc(int *)
with an over-aligned member shouldn't be a problem.

ZarkoCA updated this revision to Diff 404600.Jan 31 2022, 10:24 AM
  • Warning shouldn't apply to functions that have internal linkage

Would it make sense (and would it be possible) to check the linkage of the callee? Presumably calling something like
static void localfunc(int *)
with an over-aligned member shouldn't be a problem.

That's a really good point. It wouldn't make sense for it to apply there, thanks!

ZarkoCA updated this revision to Diff 406086.Feb 4 2022, 12:58 PM
  • Moved AIX check to its own function to hopefully avoid Arg and ArgTy getting out of sync
  • Rebased and removed LIT test cases workaround
ZarkoCA added inline comments.Feb 4 2022, 1:02 PM
clang/include/clang/Sema/Sema.h
12693–12696

@aaron.ballman I moved the check to its own function and only pass Expr *Arg to it. I think this should avoid them getting out of sync.

aaron.ballman added inline comments.Feb 7 2022, 6:14 AM
clang/lib/Sema/SemaChecking.cpp
5212–5215

I don't see a need for AArg, so I'd sink it into the uses instead.

5220–5221

I think it'd probably be helpful to tell the user which alignment was calculated (it may not be obvious from the context because the alignment could be hidden behind a macro or something).

5348–5349
clang/test/Sema/aix-attr-align.c
34–35

This diagnostic is a bit odd to me. It says there's a request for alignment, but there's no such request on this line. So it's not clear how the user is supposed to react to the diagnostic. While the current code makes it somewhat obvious because there's only one field in the expression, imagine code like quux(s.a, s.b); where it's less clear as to which field causes the diagnostic from looking at the call site.

Personally, I found the old diagnostics to be more clear as to what the issue is. I think we should put the warning on the declaration involving the alignment request, and we should add a note to the call site where the diagnostic is generated from (or vice versa). WDYT?

ZarkoCA updated this revision to Diff 406620.Feb 7 2022, 2:44 PM
  • Add note for diagnostic pointing to declaration of the struct member
  • cleaned up use of unneeded variable
ZarkoCA marked 4 inline comments as done.Feb 7 2022, 2:55 PM
ZarkoCA added inline comments.
clang/lib/Sema/SemaChecking.cpp
5220–5221

I tried to address in slightly modifying the warning message to emit the offending alignment and also adding a note for the declaration as you suggested elsewhere.

clang/test/Sema/aix-attr-align.c
34–35

That's a good point actually, there's nothing on the line that would be obvious to a user.

I opted to warn at the use of struct member and to make a note where it was declared. This will hopefully help with determining which struct member is causing this warning instead of searching the code for its cause. I have a slight preference for doing it this way instead of the other way but can change it if preferred.

aaron.ballman added inline comments.Feb 8 2022, 4:52 AM
clang/test/Sema/aix-attr-align.c
34–35

I'd like to understand why you have a preference for this way around.

The use is the point in time at which we know there's a problem, so I definitely agree with waiting until the struct member is used to diagnose anything.

But, to my thinking, the use is not the cause of the issue; the declaration is what's problematic. With that perspective, it seems like we want the warning and the note the other way around: warn about the structure member declaration being the issue, and note where the use that triggered the complaint about the declaration. Then the warning diagnostic is associated most closely with the code that needs to be adjusted by the user in order to silence the warning. This also makes it easier for the user to silence the warning with pragmas (you can put the suppression mechanism in one place, at the declaration site, instead of sprinkling it all over at the use sites).

ZarkoCA updated this revision to Diff 406822.Feb 8 2022, 7:32 AM
  • Warn on declaration of struct member and add note for call
ZarkoCA added inline comments.Feb 8 2022, 7:39 AM
clang/test/Sema/aix-attr-align.c
34–35

Then the warning diagnostic is associated most closely with the code that needs to be adjusted by the user in order to silence the warning.

Thanks, that's a good point and your additional argument about silencing it with pragmas at a single place has convinced me to switch it up.

Thanks! I think we're pretty close, just some wording nits with the diagnostics.

clang/include/clang/Basic/DiagnosticSemaKinds.td
3299–3301 ↗(On Diff #406822)

How about this slight rewording from the old form? (Have to re-flow to 80 cols.)

I had previously suggested adding the requested alignment before but now that we're closely tying the diagnostic to the structure member, I think this form is okay (and it's shorter, which is what I was hoping to accomplish).

clang/lib/Sema/SemaChecking.cpp
5221

I don't think this note is the correct one to use (it looks weird in the test cases). I think you'll want to add a new note along the lines of:

def note_misaligned_member_used_here : Note<
  "%0 used with potentially incompatible alignment here">;

And you should pass in FD rather than FD->getDeclName() (the diagnostics engine knows how to print the names of NamedDecl subclasses and has special logic for that.

ZarkoCA updated this revision to Diff 406843.Feb 8 2022, 8:26 AM
  • Shorten warning message
  • Add new note
ZarkoCA added inline comments.Feb 8 2022, 8:31 AM
clang/include/clang/Basic/DiagnosticSemaKinds.td
3299–3301 ↗(On Diff #406822)

Yes, I cringed a bit seeing it at 3 lines. Thanks.

clang/lib/Sema/SemaChecking.cpp
5221

Ah yes, this seems much clearer to the user now IMO, thanks

aaron.ballman accepted this revision.Feb 8 2022, 8:42 AM

LGTM, thank you!

This revision is now accepted and ready to land.Feb 8 2022, 8:42 AM

After offline discussion with @sfertile , the warning should occur only when the struct member is passed on the stack. I will be updating the patch shortly.

@aaron.ballman Thank you for the thorough reviews comments and sorry for the churn.

ZarkoCA planned changes to this revision.Feb 16 2022, 2:52 PM

Hey Zarko. I really like how we only issue the warning when the struct is used, however I think this is still overly broad because of where the incompatibility lies between xlc and clang. I believe the layout of the structures will be the same for both compilers, and globals of this type will have the same alignment restrictions. A function like void baz(int *); will be compatible between the 2 compilers since the argument is just a pointer. The difference occurs when passing the structure by value on the stack, where xlc doesn't align the struct to the expected alignment, and clang/llvm does. Since the incompatibility is in the calling convention only when the struct is passed byval, that should be the only time we emit the diagnostic.

There are 2 other things we should verify since I'm not sure if they are compatible or not:

  1. When passing these structures byval but in argument passing registers, I'm guessing that xlc doesn't skip registers whose image in the PSA is under-aligned while llvm will.
  2. Whether xlc passes these misaligned when its done through va_args.

The answers to those 2 questions will determine if we need to warn for all byval arguments that have alignments from attribute that is greater than 8, or if we can limit it a bit further.

ZarkoCA updated this revision to Diff 411912.Feb 28 2022, 3:33 PM
ZarkoCA retitled this revision from [Clang][Sema][AIX][PowerPC] Emit byval alignment warning only when struct member is passed to a function to [Clang][Sema][AIX][PowerPC] Emit byval alignment warning only when struct is passed to a function.
ZarkoCA edited the summary of this revision. (Show Details)

Reworked implementation so the diagnosis is more correct:

  • Warn when the struct is passed that contains the member
  • Warn when alignment is 16 and not 16 and greater
This revision is now accepted and ready to land.Feb 28 2022, 3:33 PM
ZarkoCA requested review of this revision.Feb 28 2022, 3:33 PM
sfertile added inline comments.Mar 2 2022, 10:52 AM
clang/lib/Sema/SemaChecking.cpp
5212

Nit: To avoid the deep nesting, can we instead have a series of casts, and if the resulting pointer is null we return early?

clang/test/Sema/aix-attr-align.c
10

As far as I am aware, the layout of a 16-byte aligned member is exactly the same between the all the compilers on AIX, and the only incompatibility is when passing them byval. If that's true then warning on the declaration here is much too verbose, as most uses will be fine and warning on the callsite (and later on the function definition) calls attention to it only when there is indeed the possibility of an incompatability.

35

I get the following diagnostic from the compiler now:

baz(p1, p2, s.b, p3, b, p5, s);        // expected-note {{'b' used with potentially incompatible alignment here}}
                            ^

I can't seem to get the formatting exact, but the caret is pointing to 's' which is the correct argument to warn on, but the note uses the name 'b'. Before adjusting the warning using the member name made sense, but I think now that we are warning on the byval argument, we should be using s, and also reword the note to something like
passing byval argument 's' which is 16 byte aligned may be incompatible with IBM XL C/C++ for AIX 16.1.0 or older

Herald added a project: Restricted Project. · View Herald TranscriptMar 2 2022, 10:52 AM
ZarkoCA updated this revision to Diff 412826.Mar 3 2022, 1:27 PM
  • Try to remove deeply nested ifs by using early returns
  • Fix note so it refers to struct
  • Add a struct that isn't called byval in test case to make it clearer that

warning isn't emitted on every declaration

ZarkoCA updated this revision to Diff 412840.Mar 3 2022, 2:29 PM
  • Remove formatting changes to unrelated code
ZarkoCA added inline comments.Mar 3 2022, 2:33 PM
clang/lib/Sema/SemaChecking.cpp
5212

Reworked it to use a few early returns. Does that work better?

clang/test/Sema/aix-attr-align.c
10

The way this test case was written it made it seem as if it would warn on any such declaration. I added struct R here where it has a member aligned 16 but it's not passed byval anywhere and no warning is expected. I also added a comment to make it clearer.

Thanks for the updates Zarko. I think we are almost there.

clang/lib/Sema/SemaChecking.cpp
5208

Real minor nit: Missing space after period.

5221

I find these longer lines hard to read. I way you had the original checks structured was good, my suggestion was really meant to change only the nesting. I think keeping the same format you would have ended up with something that looks like

const auto *ICE = dyn_cast<ImplicitCastExpr>(Arg->IgnoreParens());
if (!ICE)
  return;

const auto *DR = dyn_cast<DeclRefExpr>(ICE->getSubExpr());
if (!DR)
  return;

auto *PD = dyn_cast<ParmVarDecl>(DR->getDecl();
if (!PD || !PD->getType()->isRecordType())
  return;
ZarkoCA updated this revision to Diff 413818.Mar 8 2022, 8:29 AM
  • Restructured checks
  • fixed comment
  • removed unnecessary parameter passed to function
  • slightly reworded summary of patch
ZarkoCA marked 8 inline comments as done.Mar 8 2022, 8:31 AM
ZarkoCA added inline comments.
clang/lib/Sema/SemaChecking.cpp
5221

I agree I find it easier to read this way as well. Thanks for clearing that up.

sfertile accepted this revision.Jul 11 2022, 11:09 AM

LGTM Zarko, sorry about taking so long to review this.

This revision is now accepted and ready to land.Jul 11 2022, 11:09 AM
ZarkoCA updated this revision to Diff 443812.Jul 11 2022, 6:37 PM
  • Rebase and add FDecl check before calling checkAIXMemberAlignment()
sfertile accepted this revision.Jul 13 2022, 8:38 AM