On 12/18/18 9:10 AM, H.J. Lu wrote:
+ switch (TREE_CODE (rhs))
+ {
+ case ADDR_EXPR:
+ base = TREE_OPERAND (rhs, 0);
+ while (handled_component_p (base))
+ {
+ if (TREE_CODE (base) == COMPONENT_REF)
+ break;
+ base = TREE_OPERAND (base, 0);
+ }
+ if (TREE_CODE (base) != COMPONENT_REF)
+ return NULL_TREE;
+ object = TREE_OPERAND (base, 0);
+ field = TREE_OPERAND (base, 1);
+ break;
+ case COMPONENT_REF:
+ object = TREE_OPERAND (rhs, 0);
+ field = TREE_OPERAND (rhs, 1);
+ break;
+ default:
+ return NULL_TREE;
+ }
+
+ tree context = check_alignment_of_packed_member (type, field);
+ if (context)
+ return context;
+
+ /* Check alignment of the object. */
+ while (TREE_CODE (object) == COMPONENT_REF)
+ {
+ field = TREE_OPERAND (object, 1);
+ context = check_alignment_of_packed_member (type, field);
+ if (context)
+ return context;
+ object = TREE_OPERAND (object, 0);
+ }
+
You can see interleaved COMPONENT_REF and ARRAY_REF that this still
doesn't look like it will handle, something like
struct A
{
int i;
};
struct B
{
char c;
__attribute ((packed)) A ar[4];
};
B b;
int *p = &b.ar[1].i;
Rather than have a loop in the ADDR_EXPR case of the switch, you can
handle everything in the lower loop. And not have a switch at all, just
strip any ADDR_EXPR before the loop.
+check_and_warn_address_of_packed_member (tree type, tree rhs)
+{
+ if (TREE_CODE (rhs) != COND_EXPR)
+ {
+ tree context = check_address_of_packed_member (type, rhs);
+ if (context)
+ {
+ location_t loc = EXPR_LOC_OR_LOC (rhs, input_location);
+ warning_at (loc, OPT_Waddress_of_packed_member,
+ "taking address of packed member of %qT may result "
+ "in an unaligned pointer value",
+ context);
+ }
+ return;
+ }
+
+ /* Check the THEN path. */
+ check_and_warn_address_of_packed_member (type, TREE_OPERAND (rhs, 1));
+
+ /* Check the ELSE path. */
+ check_and_warn_address_of_packed_member (type, TREE_OPERAND (rhs, 2));
+}
You probably also want to handle COMPOUND_EXPR.
Jason