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
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits