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

Reply via email to