This is an archive of the discontinued LLVM Phabricator instance.

[WIP] Binding of references to packed fields
Needs ReviewPublic

Authored by rogfer01 on Aug 9 2016, 9:10 AM.

Details

Summary

This is a WIP for PR28571.

As suggested by @rsmith it introduces a new ObjectKind for PackedField's modeled similarly in spirit to BitField's. If the reference is const, the binding is done using a temporary otherwise an error is diagnosed.

Diff Detail

Event Timeline

rogfer01 updated this revision to Diff 67360.Aug 9 2016, 9:10 AM
rogfer01 retitled this revision from to [WIP] Binding of references to packed fields.
rogfer01 updated this object.
rogfer01 added reviewers: aaron.ballman, rsmith.
rogfer01 added subscribers: cfe-commits, rsmith.
rogfer01 added inline comments.
lib/Sema/SemaInit.cpp
4272–4274

Rereading this makes no sense to me now. I'll adress this in a later update.

aaron.ballman added inline comments.Aug 30 2016, 2:35 PM
include/clang/AST/Expr.h
436

s/gl-value/glvalue

438

"that the field has an effectively-reduced alignment"

440

Like bitfields
glvalues

include/clang/AST/Stmt.h
135

This is a bit unfortunate (not that I see a way around it)...

lib/AST/ASTDumper.cpp
1892

packedfield instead?

lib/AST/Decl.cpp
37

This should be removed.

lib/Sema/SemaExprMember.cpp
1790

Formatting of the brace is incorrect.

lib/Sema/SemaInit.cpp
4258

I don't know whether you should use auto here or not, the type is kinda-sorta spelled out in the initialization. At the very least, this should be const auto *.

rsmith added inline comments.Aug 30 2016, 5:32 PM
include/clang/AST/Expr.h
441

value-kind -> object kind.

include/clang/Basic/Specifiers.h
119–140

Wait a second, how did this fit into 2 bits before your change?!

lib/AST/Decl.cpp
3590

Does this properly handle anonymous struct/union members:

struct A __attribute__((packed)) {
  char a;
  union { int b; };
} a;
int &r = a.b;
lib/CodeGen/CGCall.cpp
3278 ↗(On Diff #67360)

This looks wrong: we shouldn't be emitting reference bindings to packed fields. We should have rejected them in Sema.

lib/Sema/SemaCast.cpp
1922

Might be worth adding a comment here, "GCC allows a packed field to be explicitly cast to a reference type as a way of removing the 'packed' taint" or similar.

lib/Sema/SemaExprMember.cpp
1782–1783

If the BaseExpr is an OK_PackedField then the resulting OK for the field should also be an OK_PackedField:

struct Q { int k; };
struct __attribute__((packed)) A { Q k; } a;
int &r = a.k.k; // error, binding reference to packed field

You should handle this here...

1793

... not here. This check does the wrong thing for the IsArrow case:

struct Q { int k; };
struct __attribute__((packed)) A { Q *k; } a;
int &r = a.k->k; // should be valid, not a packed field
lib/Sema/SemaInit.cpp
4256

You don't need to special-case packed fields here. They just happen to be the only non-addressable object kind we have right now that can be a class type. If we had others, they should get this treatment too, so it seems better to remove the check.

4256

Why are you treating lvalue references specially here? GCC doesn't seem to, and it's not obvious to me why rvalue references should get special treatment.

4272–4274

Perhaps replace this entire comment with "If the class doesn't have a trivial copy constructor, we can't create a copy of it for the reference binding because doing so would bind it to a reference in the class's own copy/move constructor, so just give up and allow the error to be diagnosed."

test/SemaCXX/bind-packed-member.cpp
69–74

Another interesting case:

struct __attribute__((packed)) G {
  char c;
  NonTrivialCopy x;
};

Here, GCC ignores the packed attribute entirely (with a warning). For ABI compatibility, we should do the same.

rogfer01 added inline comments.Nov 16 2016, 8:14 AM
include/clang/Basic/Specifiers.h
119–140

It didn't.

I was also really confused when some unrelated Obj-C tests started failing after this change.

rogfer01 marked 15 inline comments as done.Nov 16 2016, 10:10 AM

I am retaking this, will upload an updated patch soon.

lib/AST/Decl.cpp
3590

This test (modulo swapping A and __attribute__((packed)) positions) works. Do you think we may be missing some case here?

test/SemaCXX/bind-packed-member.cpp
69–74

Will do this in a later update of this patch.

I still have to check what is the best place to check this, though I think once the class-specifier has been completed.

rogfer01 updated this revision to Diff 78209.Nov 16 2016, 10:17 AM

Changes:

  • Rebase patch to trunk
  • Fixes as pointed out by reviewers

TODO:

  • Diagnose and drop the packed attribute of a class with a nontrivially constructed data member.
rsmith added inline comments.Nov 16 2016, 2:04 PM
include/clang/AST/Expr.h
440

"Likewise bitfields" -> "Like bitfields" still needs to be done.

Also, "packed-fields" -> "packed fields" throughout this comment.

lib/AST/Decl.cpp
3590

No, I think this is OK, so long as we have a unit test for it. I assume that what happens here is that the implicit a.<anonymous union object> produces a packed lvalue, and then the .b just preserves the packedness -- that is, the anonymous union object is a packed field, but b is not?

lib/Sema/SemaExprMember.cpp
1782–1783

I think the existing code here is checking for a condition that can't happen. Do any tests fail if you replace this if/else block with just VK = BaseExpr->getValueKind();?

lib/Sema/SemaInit.cpp
4256

You don't seem to have addressed this comment: you can delete the refersToPackedField check here; the check for a class type is sufficient.

rogfer01 updated this revision to Diff 80081.Dec 2 2016, 9:28 AM

Drop attribute packed of a class when one of its fields is a non-packed non-pod for compatibility with GCC.

rogfer01 updated this revision to Diff 81955.Dec 19 2016, 8:35 AM

Rebase to current trunk

aaron.ballman added inline comments.Dec 19 2016, 11:43 AM
include/clang/AST/Decl.h
2388

Should be &Context instead of & context.

include/clang/AST/Expr.h
412

bit-field instead of bitfield (we're starting to standardize on the spelling used by the standards).

432

typo: bit-field.

440

s/bitfields/bit-fields

include/clang/Basic/Specifiers.h
126

Remove the hyphen from packed-field.

lib/Sema/SemaInit.cpp
4459

Move the brace to the preceding line.

rogfer01 updated this revision to Diff 82114.Dec 20 2016, 9:07 AM

Minor issues addressed