rsmith added inline comments.

================
Comment at: include/clang/AST/Expr.h:441
@@ +440,3 @@
+  /// Likewise bitfields, we model gl-values referring to packed-fields as
+  /// an aspect of the value-kind type system.
+  bool refersToPackedField() const { return getObjectKind() == OK_PackedField; 
}
----------------
value-kind -> object kind.

================
Comment at: include/clang/Basic/Specifiers.h:119-140
@@ -118,21 +118,24 @@
   /// l-value or x-value.
   enum ExprObjectKind {
     /// An ordinary object is located at an address in memory.
     OK_Ordinary,
 
     /// A bitfield object is a bitfield on a C or C++ record.
     OK_BitField,
 
+    /// A packed-field is a field on a C or C++ packed record.
+    OK_PackedField,
+
     /// A vector component is an element or range of elements on a vector.
     OK_VectorComponent,
 
     /// An Objective-C property is a logical field of an Objective-C
     /// object which is read and written via Objective-C method calls.
     OK_ObjCProperty,
     
     /// An Objective-C array/dictionary subscripting which reads an
     /// object or writes at the subscripted array/dictionary element via
     /// Objective-C method calls.
     OK_ObjCSubscript
   };
 
----------------
Wait a second, how did this fit into 2 bits before your change?!

================
Comment at: lib/AST/Decl.cpp:3523
@@ +3522,3 @@
+  return !isBitField() &&
+         (this->hasAttr<PackedAttr>() || getParent()->hasAttr<PackedAttr>()) &&
+         Context.getDeclAlign(this) <
----------------
Does this properly handle anonymous struct/union members:

  struct A __attribute__((packed)) {
    char a;
    union { int b; };
  } a;
  int &r = a.b;

================
Comment at: lib/CodeGen/CGCall.cpp:3278
@@ -3277,3 +3277,3 @@
   if (E->isGLValue()) {
-    assert(E->getObjectKind() == OK_Ordinary);
+    assert(E->getObjectKind() == OK_Ordinary || E->getObjectKind() == 
OK_PackedField);
     return args.add(EmitReferenceBindingToExpr(E), type);
----------------
This looks wrong: we shouldn't be emitting reference bindings to packed fields. 
We should have rejected them in Sema.

================
Comment at: lib/Sema/SemaCast.cpp:1912
@@ -1911,2 +1911,3 @@
     case OK_Ordinary:
+    case OK_PackedField:
       break;
----------------
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.

================
Comment at: lib/Sema/SemaExprMember.cpp:1772-1774
@@ -1771,4 +1771,5 @@
   if (!IsArrow) {
-    if (BaseExpr->getObjectKind() == OK_Ordinary)
+    if (BaseExpr->getObjectKind() == OK_Ordinary ||
+        BaseExpr->getObjectKind() == OK_PackedField)
       VK = BaseExpr->getValueKind();
     else
----------------
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...

================
Comment at: lib/Sema/SemaExprMember.cpp:1782
@@ +1781,3 @@
+      OK = OK_BitField;
+    else if (Field->isPackedField(S.Context) || 
BaseExpr->refersToPackedField())
+      OK = OK_PackedField;
----------------
... 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

================
Comment at: lib/Sema/SemaInit.cpp:4186
@@ -4184,1 +4185,3 @@
 
+    if (IsLValueRef && Initializer->refersToPackedField() &&
+        Initializer->getType()->getAsCXXRecordDecl()) {
----------------
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.

================
Comment at: lib/Sema/SemaInit.cpp:4186
@@ -4184,1 +4185,3 @@
 
+    if (IsLValueRef && Initializer->refersToPackedField() &&
+        Initializer->getType()->getAsCXXRecordDecl()) {
----------------
rsmith wrote:
> 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.
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.

================
Comment at: lib/Sema/SemaInit.cpp:4202-4204
@@ +4201,5 @@
+
+       It is not possible to bind w to a temporary of a.x because this
+       would require (recursively) invoking the copy constructor of
+       std::vector to obtain first a (properly aligned) temporary of a.x.
+      */
----------------
rogfer01 wrote:
> Rereading this makes no sense to me now. I'll adress this in a later update.
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."

================
Comment at: test/SemaCXX/bind-packed-member.cpp:68-73
@@ +67,8 @@
+
+struct F
+{
+    char c;
+    NonTrivialCopy x __attribute__((packed));
+    int w __attribute__((packed));
+} f;
+
----------------
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.


https://reviews.llvm.org/D23325



_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to