diff options
author | Patrick Palka <ppalka@redhat.com> | 2020-11-11 14:43:39 -0500 |
---|---|---|
committer | Patrick Palka <ppalka@redhat.com> | 2020-11-11 14:43:38 -0500 |
commit | 61827d5d9a5a09a8c05d5e41f95b03ebc6c43f61 (patch) | |
tree | 01d00c1d17c121c5ee65f3f76afd5f2a44f3c59a | |
parent | d6e5745a9a88314e27f387b2277299076862af67 (diff) | |
download | gcc-61827d5d9a5a09a8c05d5e41f95b03ebc6c43f61.zip gcc-61827d5d9a5a09a8c05d5e41f95b03ebc6c43f61.tar.gz gcc-61827d5d9a5a09a8c05d5e41f95b03ebc6c43f61.tar.bz2 |
c++: Correct the handling of alignof(expr) [PR88115]
We're currently neglecting to set the ALIGNOF_EXPR_STD_P flag on an
ALIGNOF_EXPR when its operand is an expression. This leads to us
handling alignof(expr) as if it were written __alignof__(expr), and
returning the preferred alignment instead of the ABI alignment. In the
testcase below, this causes the first and third static_assert to fail on
x86.
gcc/cp/ChangeLog:
PR c++/88115
* cp-tree.h (cxx_sizeof_or_alignof_expr): Add bool parameter.
* decl.c (fold_sizeof_expr): Pass false to
cxx_sizeof_or_alignof_expr.
* parser.c (cp_parser_unary_expression): Pass std_alignof to
cxx_sizeof_or_alignof_expr.
* pt.c (tsubst_copy): Pass false to cxx_sizeof_or_alignof_expr.
(tsubst_copy_and_build): Pass std_alignof to
cxx_sizeof_or_alignof_expr.
* typeck.c (cxx_alignof_expr): Add std_alignof bool parameter
and pass it to cxx_sizeof_or_alignof_type. Set ALIGNOF_EXPR_STD_P
appropriately.
(cxx_sizeof_or_alignof_expr): Add std_alignof bool parameter
and pass it to cxx_alignof_expr. Assert op is either
SIZEOF_EXPR or ALIGNOF_EXPR.
libcc1/ChangeLog:
PR c++/88115
* libcp1plugin.cc (plugin_build_unary_expr): Pass true to
cxx_sizeof_or_alignof_expr.
gcc/testsuite/ChangeLog:
PR c++/88115
* g++.dg/cpp0x/alignof6.C: New test.
-rw-r--r-- | gcc/cp/cp-tree.h | 2 | ||||
-rw-r--r-- | gcc/cp/decl.c | 2 | ||||
-rw-r--r-- | gcc/cp/parser.c | 4 | ||||
-rw-r--r-- | gcc/cp/pt.c | 3 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/alignof6.C | 19 | ||||
-rw-r--r-- | libcc1/libcp1plugin.cc | 2 |
7 files changed, 37 insertions, 12 deletions
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 230a1525..63724c0 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7461,7 +7461,7 @@ extern int comp_cv_qualification (const_tree, const_tree); extern int comp_cv_qualification (int, int); extern int comp_cv_qual_signature (tree, tree); extern tree cxx_sizeof_or_alignof_expr (location_t, tree, - enum tree_code, bool); + enum tree_code, bool, bool); extern tree cxx_sizeof_or_alignof_type (location_t, tree, enum tree_code, bool, bool); extern tree cxx_alignas_expr (tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 42e704e..c52111e 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -10335,7 +10335,7 @@ fold_sizeof_expr (tree t) else r = cxx_sizeof_or_alignof_expr (EXPR_LOCATION (t), TREE_OPERAND (t, 0), SIZEOF_EXPR, - false); + false, false); if (r == error_mark_node) r = size_one_node; return r; diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 3632281..4f59fc4 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -8335,8 +8335,8 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk, "ISO C++ does not allow %<alignof%> " "with a non-type"); - ret = cxx_sizeof_or_alignof_expr (compound_loc, - operand, op, true); + ret = cxx_sizeof_or_alignof_expr (compound_loc, operand, op, + std_alignof, true); } /* For SIZEOF_EXPR, just issue diagnostics, but keep SIZEOF_EXPR with the original operand. */ diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index c592461..a932c21 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -16790,6 +16790,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) else return cxx_sizeof_or_alignof_expr (input_location, expanded, SIZEOF_EXPR, + false, complain & tf_error); } else @@ -19732,7 +19733,7 @@ tsubst_copy_and_build (tree t, complain & tf_error); else r = cxx_sizeof_or_alignof_expr (input_location, - op1, TREE_CODE (t), + op1, TREE_CODE (t), std_alignof, complain & tf_error); if (TREE_CODE (t) == SIZEOF_EXPR && r != error_mark_node) { diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 08e0c80..700e166 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1832,10 +1832,12 @@ cxx_sizeof_expr (location_t loc, tree e, tsubst_flags_t complain) /* Implement the __alignof keyword: Return the minimum required alignment of E, measured in bytes. For VAR_DECL's and FIELD_DECL's return DECL_ALIGN (which can be set from an - "aligned" __attribute__ specification). */ + "aligned" __attribute__ specification). STD_ALIGNOF acts + like in cxx_sizeof_or_alignof_type. */ static tree -cxx_alignof_expr (location_t loc, tree e, tsubst_flags_t complain) +cxx_alignof_expr (location_t loc, tree e, bool std_alignof, + tsubst_flags_t complain) { tree t; @@ -1848,6 +1850,7 @@ cxx_alignof_expr (location_t loc, tree e, tsubst_flags_t complain) TREE_SIDE_EFFECTS (e) = 0; TREE_READONLY (e) = 1; SET_EXPR_LOCATION (e, loc); + ALIGNOF_EXPR_STD_P (e) = std_alignof; return e; } @@ -1900,23 +1903,25 @@ cxx_alignof_expr (location_t loc, tree e, tsubst_flags_t complain) } else return cxx_sizeof_or_alignof_type (loc, TREE_TYPE (e), - ALIGNOF_EXPR, false, + ALIGNOF_EXPR, std_alignof, complain & tf_error); return fold_convert_loc (loc, size_type_node, t); } /* Process a sizeof or alignof expression E with code OP where the operand - is an expression. */ + is an expression. STD_ALIGNOF acts like in cxx_sizeof_or_alignof_type. */ tree cxx_sizeof_or_alignof_expr (location_t loc, tree e, enum tree_code op, - bool complain) + bool std_alignof, bool complain) { + gcc_assert (op == SIZEOF_EXPR || op == ALIGNOF_EXPR); if (op == SIZEOF_EXPR) return cxx_sizeof_expr (loc, e, complain? tf_warning_or_error : tf_none); else - return cxx_alignof_expr (loc, e, complain? tf_warning_or_error : tf_none); + return cxx_alignof_expr (loc, e, std_alignof, + complain? tf_warning_or_error : tf_none); } /* Build a representation of an expression 'alignas(E).' Return the diff --git a/gcc/testsuite/g++.dg/cpp0x/alignof6.C b/gcc/testsuite/g++.dg/cpp0x/alignof6.C new file mode 100644 index 0000000..b1a463d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/alignof6.C @@ -0,0 +1,19 @@ +// PR c++/88115 +// { dg-do compile { target c++11 } } +// { dg-additional-options "-Wno-pedantic" } + +// Verify the non-standard extension alignof(expr) behaves like +// alignof(type) to yield the ABI alignment of the type, and that +// __alignof__(expr) behaves like __alignof__(type) to yield the +// preferred alignment of the type. + +static_assert(alignof(double{}) == alignof(double), ""); +static_assert(__alignof__(double{}) == __alignof__(double), ""); + +template <class T> +void f() { + static_assert(alignof(T{}) == alignof(T), ""); + static_assert(__alignof__(T{}) == __alignof__(T), ""); +} + +template void f<double>(); diff --git a/libcc1/libcp1plugin.cc b/libcc1/libcp1plugin.cc index 67a235f..6483683 100644 --- a/libcc1/libcp1plugin.cc +++ b/libcc1/libcp1plugin.cc @@ -2806,7 +2806,7 @@ plugin_build_unary_expr (cc1_plugin::connection *self, case SIZEOF_EXPR: case ALIGNOF_EXPR: result = cxx_sizeof_or_alignof_expr (input_location, - op0, opcode, true); + op0, opcode, true, true); break; case DELETE_EXPR: |