From aa2b10551159df9eb1b33e049eb36ee53d379b4e Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 23 Apr 2018 16:49:38 -0400 Subject: [PATCH] PR c++/69560 - wrong alignof(double) on x86. CWG 1879 - Inadequate definition of alignment requirement. * cp-tree.h (ALIGNOF_EXPR_STD_P): New. * typeck.c (cxx_sizeof_or_alignof_type): Add std_alignof parm. (cxx_sizeof_expr, cxx_sizeof_nowarn, cxx_alignas_expr) (cxx_alignof_expr): Pass it. * parser.c (cp_parser_unary_expression): Pass it. * pt.c (tsubst_copy): Copy it. (tsubst_copy_and_build): Pass it. * decl.c (fold_sizeof_expr): Pass it. From-SVN: r259578 --- gcc/cp/ChangeLog | 13 +++++++++++++ gcc/cp/cp-tree.h | 9 +++++++-- gcc/cp/decl.c | 4 ++-- gcc/cp/parser.c | 7 +++++-- gcc/cp/pt.c | 12 +++++++++--- gcc/cp/typeck.c | 19 ++++++++++++------- gcc/testsuite/g++.dg/abi/align2.C | 5 +++++ libcc1/libcp1plugin.cc | 3 ++- 8 files changed, 55 insertions(+), 17 deletions(-) create mode 100644 gcc/testsuite/g++.dg/abi/align2.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index aaed5d4d01b..365592f5657 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +2018-04-23 Jason Merrill + + PR c++/69560 - wrong alignof(double) on x86. + CWG 1879 - Inadequate definition of alignment requirement. + * cp-tree.h (ALIGNOF_EXPR_STD_P): New. + * typeck.c (cxx_sizeof_or_alignof_type): Add std_alignof parm. + (cxx_sizeof_expr, cxx_sizeof_nowarn, cxx_alignas_expr) + (cxx_alignof_expr): Pass it. + * parser.c (cp_parser_unary_expression): Pass it. + * pt.c (tsubst_copy): Copy it. + (tsubst_copy_and_build): Pass it. + * decl.c (fold_sizeof_expr): Pass it. + 2018-04-23 Jakub Jelinek Jason Merrill diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 5af4928e2fb..37770770acb 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -372,6 +372,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX]; TEMPLATE_TYPE_PARM_FOR_CLASS (TEMPLATE_TYPE_PARM) DECL_NAMESPACE_INLINE_P (in NAMESPACE_DECL) SWITCH_STMT_ALL_CASES_P (in SWITCH_STMT) + ALIGNOF_EXPR_STD_P (in ALIGNOF_EXPR) 1: IDENTIFIER_KIND_BIT_1 (in IDENTIFIER_NODE) TI_PENDING_TEMPLATE_FLAG. TEMPLATE_PARMS_FOR_INLINE. @@ -4954,6 +4955,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) #define SIZEOF_EXPR_TYPE_P(NODE) \ TREE_LANG_FLAG_0 (SIZEOF_EXPR_CHECK (NODE)) +/* True if the ALIGNOF_EXPR was spelled "alignof". */ +#define ALIGNOF_EXPR_STD_P(NODE) \ + TREE_LANG_FLAG_0 (ALIGNOF_EXPR_CHECK (NODE)) + /* An enumeration of the kind of tags that C++ accepts. */ enum tag_types { none_type = 0, /* Not a tag type. */ @@ -7195,7 +7200,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 (tree, enum tree_code, bool); -extern tree cxx_sizeof_or_alignof_type (tree, enum tree_code, bool); +extern tree cxx_sizeof_or_alignof_type (tree, enum tree_code, bool, bool); extern tree cxx_alignas_expr (tree); extern tree cxx_sizeof_nowarn (tree); extern tree is_bitfield_expr_with_lowered_type (const_tree); @@ -7292,7 +7297,7 @@ extern tree cp_build_binary_op (location_t, extern tree build_x_vec_perm_expr (location_t, tree, tree, tree, tsubst_flags_t); -#define cxx_sizeof(T) cxx_sizeof_or_alignof_type (T, SIZEOF_EXPR, true) +#define cxx_sizeof(T) cxx_sizeof_or_alignof_type (T, SIZEOF_EXPR, false, true) extern tree build_simple_component_ref (tree, tree); extern tree build_ptrmemfunc_access_expr (tree, tree); extern tree build_address (tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index d822745b81f..55e234334ac 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -9542,10 +9542,10 @@ fold_sizeof_expr (tree t) tree r; if (SIZEOF_EXPR_TYPE_P (t)) r = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (t, 0)), - SIZEOF_EXPR, false); + SIZEOF_EXPR, false, false); else if (TYPE_P (TREE_OPERAND (t, 0))) r = cxx_sizeof_or_alignof_type (TREE_OPERAND (t, 0), SIZEOF_EXPR, - false); + false, false); else r = cxx_sizeof_or_alignof_expr (TREE_OPERAND (t, 0), SIZEOF_EXPR, false); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index bf46165f5ae..d8ce28a6d61 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -7993,19 +7993,22 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk, location_t start_loc = token->location; op = keyword == RID_ALIGNOF ? ALIGNOF_EXPR : SIZEOF_EXPR; + bool std_alignof = id_equal (token->u.value, "alignof"); + /* Consume the token. */ cp_lexer_consume_token (parser->lexer); /* Parse the operand. */ operand = cp_parser_sizeof_operand (parser, keyword); if (TYPE_P (operand)) - ret = cxx_sizeof_or_alignof_type (operand, op, true); + ret = cxx_sizeof_or_alignof_type (operand, op, std_alignof, + true); else { /* ISO C++ defines alignof only with types, not with expressions. So pedwarn if alignof is used with a non- type expression. However, __alignof__ is ok. */ - if (id_equal (token->u.value, "alignof")) + if (std_alignof) pedwarn (token->location, OPT_Wpedantic, "ISO C++ does not allow % " "with a non-type"); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index e2a12b963ad..9fb819722ec 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -15598,7 +15598,8 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) expanded = make_argument_pack (expanded); if (TYPE_P (expanded)) - return cxx_sizeof_or_alignof_type (expanded, SIZEOF_EXPR, + return cxx_sizeof_or_alignof_type (expanded, SIZEOF_EXPR, + false, complain & tf_error); else return cxx_sizeof_or_alignof_expr (expanded, SIZEOF_EXPR, @@ -15636,7 +15637,10 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) { tree type = tsubst (TREE_TYPE (t), args, complain, in_decl); tree op0 = tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl); - return build1 (code, type, op0); + r = build1 (code, type, op0); + if (code == ALIGNOF_EXPR) + ALIGNOF_EXPR_STD_P (r) = ALIGNOF_EXPR_STD_P (t); + return r; } case COMPONENT_REF: @@ -18002,6 +18006,8 @@ tsubst_copy_and_build (tree t, op1 = TREE_OPERAND (t, 0); if (TREE_CODE (t) == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (t)) op1 = TREE_TYPE (op1); + bool std_alignof = (TREE_CODE (t) == ALIGNOF_EXPR + && ALIGNOF_EXPR_STD_P (t)); if (!args) { /* When there are no ARGS, we are trying to evaluate a @@ -18025,7 +18031,7 @@ tsubst_copy_and_build (tree t, --c_inhibit_evaluation_warnings; } if (TYPE_P (op1)) - r = cxx_sizeof_or_alignof_type (op1, TREE_CODE (t), + r = cxx_sizeof_or_alignof_type (op1, TREE_CODE (t), std_alignof, complain & tf_error); else r = cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t), diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index f5081c1661c..01baf6c17a3 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1597,10 +1597,13 @@ compparms (const_tree parms1, const_tree parms2) /* Process a sizeof or alignof expression where the operand is a - type. */ + type. STD_ALIGNOF indicates whether an alignof has C++11 (minimum alignment) + or GNU (preferred alignment) semantics; it is ignored if op is + SIZEOF_EXPR. */ tree -cxx_sizeof_or_alignof_type (tree type, enum tree_code op, bool complain) +cxx_sizeof_or_alignof_type (tree type, enum tree_code op, bool std_alignof, + bool complain) { tree value; bool dependent_p; @@ -1637,11 +1640,13 @@ cxx_sizeof_or_alignof_type (tree type, enum tree_code op, bool complain) { value = build_min (op, size_type_node, type); TREE_READONLY (value) = 1; + if (op == ALIGNOF_EXPR && std_alignof) + ALIGNOF_EXPR_STD_P (value) = true; return value; } return c_sizeof_or_alignof_type (input_location, complete_type (type), - op == SIZEOF_EXPR, false, + op == SIZEOF_EXPR, std_alignof, complain); } @@ -1659,7 +1664,7 @@ cxx_sizeof_nowarn (tree type) else if (!COMPLETE_TYPE_P (type)) return size_zero_node; else - return cxx_sizeof_or_alignof_type (type, SIZEOF_EXPR, false); + return cxx_sizeof_or_alignof_type (type, SIZEOF_EXPR, false, false); } /* Process a sizeof expression where the operand is an expression. */ @@ -1725,7 +1730,7 @@ cxx_sizeof_expr (tree e, tsubst_flags_t complain) else e = TREE_TYPE (e); - return cxx_sizeof_or_alignof_type (e, SIZEOF_EXPR, complain & tf_error); + return cxx_sizeof_or_alignof_type (e, SIZEOF_EXPR, false, complain & tf_error); } /* Implement the __alignof keyword: Return the minimum required @@ -1786,7 +1791,7 @@ cxx_alignof_expr (tree e, tsubst_flags_t complain) t = size_one_node; } else - return cxx_sizeof_or_alignof_type (TREE_TYPE (e), ALIGNOF_EXPR, + return cxx_sizeof_or_alignof_type (TREE_TYPE (e), ALIGNOF_EXPR, false, complain & tf_error); return fold_convert (size_type_node, t); @@ -1825,7 +1830,7 @@ cxx_alignas_expr (tree e) alignas(type-id ), it shall have the same effect as alignas(alignof(type-id )). */ - return cxx_sizeof_or_alignof_type (e, ALIGNOF_EXPR, false); + return cxx_sizeof_or_alignof_type (e, ALIGNOF_EXPR, true, false); /* If we reach this point, it means the alignas expression if of the form "alignas(assignment-expression)", so we should follow diff --git a/gcc/testsuite/g++.dg/abi/align2.C b/gcc/testsuite/g++.dg/abi/align2.C new file mode 100644 index 00000000000..c9f3a8fae24 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/align2.C @@ -0,0 +1,5 @@ +// PR c++/69560 +// { dg-do compile { target { ia32 && c++11 } } } + +#define SA(X) static_assert ((X), #X) +SA(alignof(double) == 4); diff --git a/libcc1/libcp1plugin.cc b/libcc1/libcp1plugin.cc index 0137cc9e4e1..10341477c56 100644 --- a/libcc1/libcp1plugin.cc +++ b/libcc1/libcp1plugin.cc @@ -3046,7 +3046,8 @@ plugin_build_unary_type_expr (cc1_plugin::connection *self, break; default: - result = cxx_sizeof_or_alignof_type (type, opcode, true); + /* Use the C++11 alignof semantics. */ + result = cxx_sizeof_or_alignof_type (type, opcode, true, true); } if (template_dependent_p) -- 2.30.2