PR c++/16387, c++/16389
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 10 Mar 2006 22:40:41 +0000 (22:40 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 10 Mar 2006 22:40:41 +0000 (22:40 +0000)
        * typeck.c (cxx_alignof_expr, cxx_sizeof_expr): New functions.
        (cxx_sizeof_or_alignof_expr): Split out from here.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@111945 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/typeck.c
gcc/testsuite/g++.dg/ext/alignof2.C [new file with mode: 0644]

index 60c1917..77c0309 100644 (file)
@@ -1,3 +1,9 @@
+2006-03-09  Jason Merrill  <jason@redhat.com>
+
+       PR c++/16387, c++/16389
+       * typeck.c (cxx_alignof_expr, cxx_sizeof_expr): New functions.
+       (cxx_sizeof_or_alignof_expr): Split out from here.
+
 2006-03-09  Diego Novillo  <dnovillo@redhat.com>
 
        Merge from gomp-20050608-branch
                * decl.c (poplevel_named_label_1): Restore creation of the
                bad_decls list.
                (decl_jump_unsafe): Check for error_mark_node types.
-               (check_goto): Don't check cdtor_label.  Don't use identify_goto.                * semantics.c (finish_return_stmt): Do check_omp_return before
+               (check_goto): Don't check cdtor_label.  Don't use identify_goto.
+                * semantics.c (finish_return_stmt): Do check_omp_return before
                converting to cdtor_label goto.
 
        2005-10-21  Richard Henderson  <rth@redhat.com>
index 52e7fb6..f94f095 100644 (file)
@@ -1267,20 +1267,17 @@ cxx_sizeof_or_alignof_type (tree type, enum tree_code op, bool complain)
   return value;
 }
 
-/* Process a sizeof or alignof expression where the operand is an
-   expression.  */
+/* Process a sizeof expression where the operand is an expression.  */
 
-tree
-cxx_sizeof_or_alignof_expr (tree e, enum tree_code op)
+static tree
+cxx_sizeof_expr (tree e)
 {
-  const char *op_name = operator_name_info[(int) op].name;
-
   if (e == error_mark_node)
     return error_mark_node;
 
   if (processing_template_decl)
     {
-      e = build_min (op, size_type_node, e);
+      e = build_min (SIZEOF_EXPR, size_type_node, e);
       TREE_SIDE_EFFECTS (e) = 0;
       TREE_READONLY (e) = 1;
 
@@ -1291,13 +1288,13 @@ cxx_sizeof_or_alignof_expr (tree e, enum tree_code op)
       && TREE_CODE (TREE_OPERAND (e, 1)) == FIELD_DECL
       && DECL_C_BIT_FIELD (TREE_OPERAND (e, 1)))
     {
-      error ("invalid application of %qs to a bit-field", op_name);
+      error ("invalid application of %<sizeof%> to a bit-field");
       e = char_type_node;
     }
   else if (is_overloaded_fn (e))
     {
-      pedwarn ("ISO C++ forbids applying %qs to an expression of "
-              "function type", op_name);
+      pedwarn ("ISO C++ forbids applying %<sizeof%> to an expression of "
+              "function type");
       e = char_type_node;
     }
   else if (type_unknown_p (e))
@@ -1308,9 +1305,71 @@ cxx_sizeof_or_alignof_expr (tree e, enum tree_code op)
   else
     e = TREE_TYPE (e);
 
-  return cxx_sizeof_or_alignof_type (e, op, true);
+  return cxx_sizeof_or_alignof_type (e, SIZEOF_EXPR, true);
 }
 
+/* Implement the __alignof keyword: Return the minimum required
+   alignment of EXPR, measured in bytes.  For VAR_DECL's and
+   FIELD_DECL's return DECL_ALIGN (which can be set from an
+   "aligned" __attribute__ specification).  */
+
+static tree
+cxx_alignof_expr (tree e)
+{
+  tree t;
+  
+  if (e == error_mark_node)
+    return error_mark_node;
+
+  if (processing_template_decl)
+    {
+      e = build_min (ALIGNOF_EXPR, size_type_node, e);
+      TREE_SIDE_EFFECTS (e) = 0;
+      TREE_READONLY (e) = 1;
+
+      return e;
+    }
+
+  if (TREE_CODE (e) == VAR_DECL)
+    t = size_int (DECL_ALIGN_UNIT (e));
+  else if (TREE_CODE (e) == COMPONENT_REF
+          && TREE_CODE (TREE_OPERAND (e, 1)) == FIELD_DECL
+          && DECL_C_BIT_FIELD (TREE_OPERAND (e, 1)))
+    {
+      error ("invalid application of %<__alignof%> to a bit-field");
+      t = size_one_node;
+    }
+  else if (TREE_CODE (e) == COMPONENT_REF
+          && TREE_CODE (TREE_OPERAND (e, 1)) == FIELD_DECL)
+    t = size_int (DECL_ALIGN_UNIT (TREE_OPERAND (e, 1)));
+  else if (is_overloaded_fn (e))
+    {
+      pedwarn ("ISO C++ forbids applying %<__alignof%> to an expression of "
+              "function type");
+      t = size_one_node;
+    }
+  else if (type_unknown_p (e))
+    {
+      cxx_incomplete_type_error (e, TREE_TYPE (e));
+      t = size_one_node;
+    }
+  else
+    return cxx_sizeof_or_alignof_type (TREE_TYPE (e), ALIGNOF_EXPR, true);
+
+  return fold_convert (size_type_node, t);
+}
+
+/* Process a sizeof or alignof expression where the operand is an
+   expression.  */
+
+tree
+cxx_sizeof_or_alignof_expr (tree e, enum tree_code op)
+{
+  if (op == SIZEOF_EXPR)
+    return cxx_sizeof_expr (e);
+  else
+    return cxx_alignof_expr (e);
+}
 \f
 /* EXPR is being used in a context that is not a function call.
    Enforce:
diff --git a/gcc/testsuite/g++.dg/ext/alignof2.C b/gcc/testsuite/g++.dg/ext/alignof2.C
new file mode 100644 (file)
index 0000000..81e1ef4
--- /dev/null
@@ -0,0 +1,23 @@
+// PRs 16387 and 16389
+// We were treating alignof (sa.a) as alignof (typeof (sa.a)), which is
+// wrong for some fields.
+
+extern "C" void abort();
+
+struct A
+{
+  double a; 
+} sa;
+
+struct B
+{
+  char c;
+  double b;
+} sb;
+
+int main()
+{
+  if (__alignof (sa) != __alignof (sa.a)
+      || __alignof (sb) != __alignof (sb.b))
+    abort();
+}