aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@gcc.gnu.org>2006-03-10 17:40:41 -0500
committerJason Merrill <jason@gcc.gnu.org>2006-03-10 17:40:41 -0500
commit229970c41d7a84ee408a5d8e75b6b153ce82bc35 (patch)
treebef2e9f13e59886c83e1b826a130b6382dfc13b2
parent1a919c563225a398a53fff2a735f37fcf6a2c617 (diff)
downloadgcc-229970c41d7a84ee408a5d8e75b6b153ce82bc35.zip
gcc-229970c41d7a84ee408a5d8e75b6b153ce82bc35.tar.gz
gcc-229970c41d7a84ee408a5d8e75b6b153ce82bc35.tar.bz2
PR c++/16387, c++/16389
PR c++/16387, c++/16389 * typeck.c (cxx_alignof_expr, cxx_sizeof_expr): New functions. (cxx_sizeof_or_alignof_expr): Split out from here. From-SVN: r111945
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/typeck.c81
-rw-r--r--gcc/testsuite/g++.dg/ext/alignof2.C23
3 files changed, 101 insertions, 12 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 60c1917..77c0309 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 52e7fb6..f94f095 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 0000000..81e1ef4
--- /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();
+}