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.
This commit is contained in:
parent
d6e5745a9a
commit
61827d5d9a
|
@ -7461,7 +7461,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 (location_t, 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,
|
extern tree cxx_sizeof_or_alignof_type (location_t, tree,
|
||||||
enum tree_code, bool, bool);
|
enum tree_code, bool, bool);
|
||||||
extern tree cxx_alignas_expr (tree);
|
extern tree cxx_alignas_expr (tree);
|
||||||
|
|
|
@ -10335,7 +10335,7 @@ fold_sizeof_expr (tree t)
|
||||||
else
|
else
|
||||||
r = cxx_sizeof_or_alignof_expr (EXPR_LOCATION (t),
|
r = cxx_sizeof_or_alignof_expr (EXPR_LOCATION (t),
|
||||||
TREE_OPERAND (t, 0), SIZEOF_EXPR,
|
TREE_OPERAND (t, 0), SIZEOF_EXPR,
|
||||||
false);
|
false, false);
|
||||||
if (r == error_mark_node)
|
if (r == error_mark_node)
|
||||||
r = size_one_node;
|
r = size_one_node;
|
||||||
return r;
|
return r;
|
||||||
|
|
|
@ -8335,8 +8335,8 @@ cp_parser_unary_expression (cp_parser *parser, cp_id_kind * pidk,
|
||||||
"ISO C++ does not allow %<alignof%> "
|
"ISO C++ does not allow %<alignof%> "
|
||||||
"with a non-type");
|
"with a non-type");
|
||||||
|
|
||||||
ret = cxx_sizeof_or_alignof_expr (compound_loc,
|
ret = cxx_sizeof_or_alignof_expr (compound_loc, operand, op,
|
||||||
operand, op, true);
|
std_alignof, true);
|
||||||
}
|
}
|
||||||
/* For SIZEOF_EXPR, just issue diagnostics, but keep
|
/* For SIZEOF_EXPR, just issue diagnostics, but keep
|
||||||
SIZEOF_EXPR with the original operand. */
|
SIZEOF_EXPR with the original operand. */
|
||||||
|
|
|
@ -16790,6 +16790,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
|
||||||
else
|
else
|
||||||
return cxx_sizeof_or_alignof_expr (input_location,
|
return cxx_sizeof_or_alignof_expr (input_location,
|
||||||
expanded, SIZEOF_EXPR,
|
expanded, SIZEOF_EXPR,
|
||||||
|
false,
|
||||||
complain & tf_error);
|
complain & tf_error);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -19732,7 +19733,7 @@ tsubst_copy_and_build (tree t,
|
||||||
complain & tf_error);
|
complain & tf_error);
|
||||||
else
|
else
|
||||||
r = cxx_sizeof_or_alignof_expr (input_location,
|
r = cxx_sizeof_or_alignof_expr (input_location,
|
||||||
op1, TREE_CODE (t),
|
op1, TREE_CODE (t), std_alignof,
|
||||||
complain & tf_error);
|
complain & tf_error);
|
||||||
if (TREE_CODE (t) == SIZEOF_EXPR && r != error_mark_node)
|
if (TREE_CODE (t) == SIZEOF_EXPR && r != error_mark_node)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1832,10 +1832,12 @@ cxx_sizeof_expr (location_t loc, tree e, tsubst_flags_t complain)
|
||||||
/* Implement the __alignof keyword: Return the minimum required
|
/* Implement the __alignof keyword: Return the minimum required
|
||||||
alignment of E, measured in bytes. For VAR_DECL's and
|
alignment of E, measured in bytes. For VAR_DECL's and
|
||||||
FIELD_DECL's return DECL_ALIGN (which can be set from an
|
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
|
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;
|
tree t;
|
||||||
|
|
||||||
|
@ -1848,6 +1850,7 @@ cxx_alignof_expr (location_t loc, tree e, tsubst_flags_t complain)
|
||||||
TREE_SIDE_EFFECTS (e) = 0;
|
TREE_SIDE_EFFECTS (e) = 0;
|
||||||
TREE_READONLY (e) = 1;
|
TREE_READONLY (e) = 1;
|
||||||
SET_EXPR_LOCATION (e, loc);
|
SET_EXPR_LOCATION (e, loc);
|
||||||
|
ALIGNOF_EXPR_STD_P (e) = std_alignof;
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
@ -1900,23 +1903,25 @@ cxx_alignof_expr (location_t loc, tree e, tsubst_flags_t complain)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return cxx_sizeof_or_alignof_type (loc, TREE_TYPE (e),
|
return cxx_sizeof_or_alignof_type (loc, TREE_TYPE (e),
|
||||||
ALIGNOF_EXPR, false,
|
ALIGNOF_EXPR, std_alignof,
|
||||||
complain & tf_error);
|
complain & tf_error);
|
||||||
|
|
||||||
return fold_convert_loc (loc, size_type_node, t);
|
return fold_convert_loc (loc, size_type_node, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process a sizeof or alignof expression E with code OP where the operand
|
/* 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
|
tree
|
||||||
cxx_sizeof_or_alignof_expr (location_t loc, tree e, enum tree_code op,
|
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)
|
if (op == SIZEOF_EXPR)
|
||||||
return cxx_sizeof_expr (loc, e, complain? tf_warning_or_error : tf_none);
|
return cxx_sizeof_expr (loc, e, complain? tf_warning_or_error : tf_none);
|
||||||
else
|
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
|
/* Build a representation of an expression 'alignas(E).' Return the
|
||||||
|
|
|
@ -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>();
|
|
@ -2806,7 +2806,7 @@ plugin_build_unary_expr (cc1_plugin::connection *self,
|
||||||
case SIZEOF_EXPR:
|
case SIZEOF_EXPR:
|
||||||
case ALIGNOF_EXPR:
|
case ALIGNOF_EXPR:
|
||||||
result = cxx_sizeof_or_alignof_expr (input_location,
|
result = cxx_sizeof_or_alignof_expr (input_location,
|
||||||
op0, opcode, true);
|
op0, opcode, true, true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DELETE_EXPR:
|
case DELETE_EXPR:
|
||||||
|
|
Loading…
Reference in New Issue