From ed1c8ebca8637c25962256bc87767d226ca85609 Mon Sep 17 00:00:00 2001
From: jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Fri, 10 Mar 2006 22:40:41 +0000
Subject: [PATCH]         PR c++/16387, c++/16389         * 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                    |  9 +++-
 gcc/cp/typeck.c                     | 81 +++++++++++++++++++++++++----
 gcc/testsuite/g++.dg/ext/alignof2.C | 23 ++++++++
 3 files changed, 101 insertions(+), 12 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/ext/alignof2.C

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 60c191713030..77c03091754d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
@@ -209,7 +215,8 @@
 		* 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>
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 52e7fb6d2d35..f94f09504fb5 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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);
+}
 
 /* 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
index 000000000000..81e1ef48fbf1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/alignof2.C
@@ -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();
+}
-- 
GitLab