mirror of git://gcc.gnu.org/git/gcc.git
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@259578 138bc75d-0d04-0410-961f-82ee72b054a4
This commit is contained in:
parent
71ac98c7a7
commit
4ecf2a2a5c
|
|
@ -1,3 +1,16 @@
|
||||||
|
2018-04-23 Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
|
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 <jakub@redhat.com>
|
2018-04-23 Jakub Jelinek <jakub@redhat.com>
|
||||||
Jason Merrill <jason@redhat.com>
|
Jason Merrill <jason@redhat.com>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -372,6 +372,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
|
||||||
TEMPLATE_TYPE_PARM_FOR_CLASS (TEMPLATE_TYPE_PARM)
|
TEMPLATE_TYPE_PARM_FOR_CLASS (TEMPLATE_TYPE_PARM)
|
||||||
DECL_NAMESPACE_INLINE_P (in NAMESPACE_DECL)
|
DECL_NAMESPACE_INLINE_P (in NAMESPACE_DECL)
|
||||||
SWITCH_STMT_ALL_CASES_P (in SWITCH_STMT)
|
SWITCH_STMT_ALL_CASES_P (in SWITCH_STMT)
|
||||||
|
ALIGNOF_EXPR_STD_P (in ALIGNOF_EXPR)
|
||||||
1: IDENTIFIER_KIND_BIT_1 (in IDENTIFIER_NODE)
|
1: IDENTIFIER_KIND_BIT_1 (in IDENTIFIER_NODE)
|
||||||
TI_PENDING_TEMPLATE_FLAG.
|
TI_PENDING_TEMPLATE_FLAG.
|
||||||
TEMPLATE_PARMS_FOR_INLINE.
|
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) \
|
#define SIZEOF_EXPR_TYPE_P(NODE) \
|
||||||
TREE_LANG_FLAG_0 (SIZEOF_EXPR_CHECK (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. */
|
/* An enumeration of the kind of tags that C++ accepts. */
|
||||||
enum tag_types {
|
enum tag_types {
|
||||||
none_type = 0, /* Not a tag type. */
|
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_qualification (int, int);
|
||||||
extern int comp_cv_qual_signature (tree, tree);
|
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_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_alignas_expr (tree);
|
||||||
extern tree cxx_sizeof_nowarn (tree);
|
extern tree cxx_sizeof_nowarn (tree);
|
||||||
extern tree is_bitfield_expr_with_lowered_type (const_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,
|
extern tree build_x_vec_perm_expr (location_t,
|
||||||
tree, tree, tree,
|
tree, tree, tree,
|
||||||
tsubst_flags_t);
|
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_simple_component_ref (tree, tree);
|
||||||
extern tree build_ptrmemfunc_access_expr (tree, tree);
|
extern tree build_ptrmemfunc_access_expr (tree, tree);
|
||||||
extern tree build_address (tree);
|
extern tree build_address (tree);
|
||||||
|
|
|
||||||
|
|
@ -9542,10 +9542,10 @@ fold_sizeof_expr (tree t)
|
||||||
tree r;
|
tree r;
|
||||||
if (SIZEOF_EXPR_TYPE_P (t))
|
if (SIZEOF_EXPR_TYPE_P (t))
|
||||||
r = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (t, 0)),
|
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)))
|
else if (TYPE_P (TREE_OPERAND (t, 0)))
|
||||||
r = cxx_sizeof_or_alignof_type (TREE_OPERAND (t, 0), SIZEOF_EXPR,
|
r = cxx_sizeof_or_alignof_type (TREE_OPERAND (t, 0), SIZEOF_EXPR,
|
||||||
false);
|
false, false);
|
||||||
else
|
else
|
||||||
r = cxx_sizeof_or_alignof_expr (TREE_OPERAND (t, 0), SIZEOF_EXPR,
|
r = cxx_sizeof_or_alignof_expr (TREE_OPERAND (t, 0), SIZEOF_EXPR,
|
||||||
false);
|
false);
|
||||||
|
|
|
||||||
|
|
@ -7993,19 +7993,22 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
|
||||||
location_t start_loc = token->location;
|
location_t start_loc = token->location;
|
||||||
|
|
||||||
op = keyword == RID_ALIGNOF ? ALIGNOF_EXPR : SIZEOF_EXPR;
|
op = keyword == RID_ALIGNOF ? ALIGNOF_EXPR : SIZEOF_EXPR;
|
||||||
|
bool std_alignof = id_equal (token->u.value, "alignof");
|
||||||
|
|
||||||
/* Consume the token. */
|
/* Consume the token. */
|
||||||
cp_lexer_consume_token (parser->lexer);
|
cp_lexer_consume_token (parser->lexer);
|
||||||
/* Parse the operand. */
|
/* Parse the operand. */
|
||||||
operand = cp_parser_sizeof_operand (parser, keyword);
|
operand = cp_parser_sizeof_operand (parser, keyword);
|
||||||
|
|
||||||
if (TYPE_P (operand))
|
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
|
else
|
||||||
{
|
{
|
||||||
/* ISO C++ defines alignof only with types, not with
|
/* ISO C++ defines alignof only with types, not with
|
||||||
expressions. So pedwarn if alignof is used with a non-
|
expressions. So pedwarn if alignof is used with a non-
|
||||||
type expression. However, __alignof__ is ok. */
|
type expression. However, __alignof__ is ok. */
|
||||||
if (id_equal (token->u.value, "alignof"))
|
if (std_alignof)
|
||||||
pedwarn (token->location, OPT_Wpedantic,
|
pedwarn (token->location, OPT_Wpedantic,
|
||||||
"ISO C++ does not allow %<alignof%> "
|
"ISO C++ does not allow %<alignof%> "
|
||||||
"with a non-type");
|
"with a non-type");
|
||||||
|
|
|
||||||
12
gcc/cp/pt.c
12
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);
|
expanded = make_argument_pack (expanded);
|
||||||
|
|
||||||
if (TYPE_P (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);
|
complain & tf_error);
|
||||||
else
|
else
|
||||||
return cxx_sizeof_or_alignof_expr (expanded, SIZEOF_EXPR,
|
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 type = tsubst (TREE_TYPE (t), args, complain, in_decl);
|
||||||
tree op0 = tsubst_copy (TREE_OPERAND (t, 0), 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:
|
case COMPONENT_REF:
|
||||||
|
|
@ -18002,6 +18006,8 @@ tsubst_copy_and_build (tree t,
|
||||||
op1 = TREE_OPERAND (t, 0);
|
op1 = TREE_OPERAND (t, 0);
|
||||||
if (TREE_CODE (t) == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (t))
|
if (TREE_CODE (t) == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (t))
|
||||||
op1 = TREE_TYPE (op1);
|
op1 = TREE_TYPE (op1);
|
||||||
|
bool std_alignof = (TREE_CODE (t) == ALIGNOF_EXPR
|
||||||
|
&& ALIGNOF_EXPR_STD_P (t));
|
||||||
if (!args)
|
if (!args)
|
||||||
{
|
{
|
||||||
/* When there are no ARGS, we are trying to evaluate a
|
/* 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;
|
--c_inhibit_evaluation_warnings;
|
||||||
}
|
}
|
||||||
if (TYPE_P (op1))
|
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);
|
complain & tf_error);
|
||||||
else
|
else
|
||||||
r = cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t),
|
r = cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t),
|
||||||
|
|
|
||||||
|
|
@ -1597,10 +1597,13 @@ compparms (const_tree parms1, const_tree parms2)
|
||||||
|
|
||||||
|
|
||||||
/* Process a sizeof or alignof expression where the operand is a
|
/* 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
|
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;
|
tree value;
|
||||||
bool dependent_p;
|
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);
|
value = build_min (op, size_type_node, type);
|
||||||
TREE_READONLY (value) = 1;
|
TREE_READONLY (value) = 1;
|
||||||
|
if (op == ALIGNOF_EXPR && std_alignof)
|
||||||
|
ALIGNOF_EXPR_STD_P (value) = true;
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return c_sizeof_or_alignof_type (input_location, complete_type (type),
|
return c_sizeof_or_alignof_type (input_location, complete_type (type),
|
||||||
op == SIZEOF_EXPR, false,
|
op == SIZEOF_EXPR, std_alignof,
|
||||||
complain);
|
complain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1659,7 +1664,7 @@ cxx_sizeof_nowarn (tree type)
|
||||||
else if (!COMPLETE_TYPE_P (type))
|
else if (!COMPLETE_TYPE_P (type))
|
||||||
return size_zero_node;
|
return size_zero_node;
|
||||||
else
|
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. */
|
/* Process a sizeof expression where the operand is an expression. */
|
||||||
|
|
@ -1725,7 +1730,7 @@ cxx_sizeof_expr (tree e, tsubst_flags_t complain)
|
||||||
else
|
else
|
||||||
e = TREE_TYPE (e);
|
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
|
/* 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;
|
t = size_one_node;
|
||||||
}
|
}
|
||||||
else
|
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);
|
complain & tf_error);
|
||||||
|
|
||||||
return fold_convert (size_type_node, t);
|
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(type-id ), it shall have the same effect as
|
||||||
alignas(alignof(type-id )). */
|
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
|
/* If we reach this point, it means the alignas expression if of
|
||||||
the form "alignas(assignment-expression)", so we should follow
|
the form "alignas(assignment-expression)", so we should follow
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
@ -3046,7 +3046,8 @@ plugin_build_unary_type_expr (cc1_plugin::connection *self,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
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)
|
if (template_dependent_p)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue