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