mirror of git://gcc.gnu.org/git/gcc.git
Implement LWG2296 helper intrinsic c-family/
Implement LWG2296 helper intrinsic c-family/ * c-common.h (enum rid): Add RID_ADDRESSOF. * c-common.c (c_common_reswords): Add __builtin_addressof. cp/ * parser.c (cp_parser_postfix_expression): Handle RID_ADDRESSOF. * cp-objcp-common.c (cp_common_init_ts): Handle ADDRESSOF_EXPR. * constexpr.c (potential_constant_expression_1): Likewise. * error.c (dump_expr): Likewise. * typeck.c (cp_build_addressof): New function. * cp-tree.h (cp_build_addressof): Declare. * cxx-pretty-print.h (pp_cxx_addressof_expression): Declare. * cp-tree.def (ADDRESSOF_EXPR): New tree code. * cxx-pretty-print.c (cxx_pretty_printer::primary_expression): Handle ADDRESSOF_EXPR. Add __builtin_addressof and __has_unique_object_representations into syntax in function comment. (pp_cxx_addressof_expression): New function. * pt.c (tsubst_copy_and_build): Handle ADDRESSOF_EXPR. testsuite/ * g++.dg/cpp0x/addressof1.C: New test. * g++.dg/cpp0x/addressof2.C: New test. From-SVN: r240873
This commit is contained in:
parent
082139830a
commit
be845b04a8
|
|
@ -1,3 +1,9 @@
|
|||
2016-10-07 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
Implement LWG2296 helper intrinsic
|
||||
* c-common.h (enum rid): Add RID_ADDRESSOF.
|
||||
* c-common.c (c_common_reswords): Add __builtin_addressof.
|
||||
|
||||
2016-10-07 Bernd Edlinger <bernd.edlinger@hotmail.de>
|
||||
|
||||
PR c++/77700
|
||||
|
|
|
|||
|
|
@ -463,6 +463,7 @@ const struct c_common_resword c_common_reswords[] =
|
|||
{ "__attribute__", RID_ATTRIBUTE, 0 },
|
||||
{ "__auto_type", RID_AUTO_TYPE, D_CONLY },
|
||||
{ "__bases", RID_BASES, D_CXXONLY },
|
||||
{ "__builtin_addressof", RID_ADDRESSOF, D_CXXONLY },
|
||||
{ "__builtin_call_with_static_chain",
|
||||
RID_BUILTIN_CALL_WITH_STATIC_CHAIN, D_CONLY },
|
||||
{ "__builtin_choose_expr", RID_CHOOSE_EXPR, D_CONLY },
|
||||
|
|
|
|||
|
|
@ -146,6 +146,7 @@ enum rid
|
|||
RID_CONSTCAST, RID_DYNCAST, RID_REINTCAST, RID_STATCAST,
|
||||
|
||||
/* C++ extensions */
|
||||
RID_ADDRESSOF,
|
||||
RID_BASES, RID_DIRECT_BASES,
|
||||
RID_HAS_NOTHROW_ASSIGN, RID_HAS_NOTHROW_CONSTRUCTOR,
|
||||
RID_HAS_NOTHROW_COPY, RID_HAS_TRIVIAL_ASSIGN,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,20 @@
|
|||
2016-10-07 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
Implement LWG2296 helper intrinsic
|
||||
* parser.c (cp_parser_postfix_expression): Handle RID_ADDRESSOF.
|
||||
* cp-objcp-common.c (cp_common_init_ts): Handle ADDRESSOF_EXPR.
|
||||
* constexpr.c (potential_constant_expression_1): Likewise.
|
||||
* error.c (dump_expr): Likewise.
|
||||
* typeck.c (cp_build_addressof): New function.
|
||||
* cp-tree.h (cp_build_addressof): Declare.
|
||||
* cxx-pretty-print.h (pp_cxx_addressof_expression): Declare.
|
||||
* cp-tree.def (ADDRESSOF_EXPR): New tree code.
|
||||
* cxx-pretty-print.c (cxx_pretty_printer::primary_expression): Handle
|
||||
ADDRESSOF_EXPR. Add __builtin_addressof and
|
||||
__has_unique_object_representations into syntax in function comment.
|
||||
(pp_cxx_addressof_expression): New function.
|
||||
* pt.c (tsubst_copy_and_build): Handle ADDRESSOF_EXPR.
|
||||
|
||||
2016-10-07 Bernd Edlinger <bernd.edlinger@hotmail.de>
|
||||
|
||||
PR c++/77700
|
||||
|
|
|
|||
|
|
@ -5025,6 +5025,11 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict,
|
|||
return (RECUR (from, TREE_CODE (t) != VIEW_CONVERT_EXPR));
|
||||
}
|
||||
|
||||
case ADDRESSOF_EXPR:
|
||||
/* This is like ADDR_EXPR, except it won't form pointer-to-member. */
|
||||
t = TREE_OPERAND (t, 0);
|
||||
goto handle_addr_expr;
|
||||
|
||||
case ADDR_EXPR:
|
||||
/* -- a unary operator & that is applied to an lvalue that
|
||||
designates an object with thread or automatic storage
|
||||
|
|
@ -5035,6 +5040,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict,
|
|||
/* A pointer-to-member constant. */
|
||||
return true;
|
||||
|
||||
handle_addr_expr:
|
||||
#if 0
|
||||
/* FIXME adjust when issue 1197 is fully resolved. For now don't do
|
||||
any checking here, as we might dereference the pointer later. If
|
||||
|
|
|
|||
|
|
@ -315,6 +315,7 @@ cp_common_init_ts (void)
|
|||
MARK_TS_TYPED (STMT_EXPR);
|
||||
MARK_TS_TYPED (OFFSET_REF);
|
||||
MARK_TS_TYPED (OFFSETOF_EXPR);
|
||||
MARK_TS_TYPED (ADDRESSOF_EXPR);
|
||||
MARK_TS_TYPED (PTRMEM_CST);
|
||||
MARK_TS_TYPED (EMPTY_CLASS_EXPR);
|
||||
MARK_TS_TYPED (VEC_INIT_EXPR);
|
||||
|
|
|
|||
|
|
@ -334,6 +334,11 @@ DEFTREECODE (TAG_DEFN, "tag_defn", tcc_expression, 0)
|
|||
/* Represents an 'offsetof' expression during template expansion. */
|
||||
DEFTREECODE (OFFSETOF_EXPR, "offsetof_expr", tcc_expression, 1)
|
||||
|
||||
/* Represents an '__builtin_addressof' expression during template
|
||||
expansion. This is similar to ADDR_EXPR, but it doesn't invoke
|
||||
overloaded & operators. */
|
||||
DEFTREECODE (ADDRESSOF_EXPR, "addressof_expr", tcc_expression, 1)
|
||||
|
||||
/* Represents the -> operator during template expansion. */
|
||||
DEFTREECODE (ARROW_EXPR, "arrow_expr", tcc_expression, 1)
|
||||
|
||||
|
|
|
|||
|
|
@ -6658,6 +6658,8 @@ extern tree build_x_array_ref (location_t, tree, tree,
|
|||
extern tree build_x_unary_op (location_t,
|
||||
enum tree_code, cp_expr,
|
||||
tsubst_flags_t);
|
||||
extern tree cp_build_addressof (location_t, tree,
|
||||
tsubst_flags_t);
|
||||
extern tree cp_build_addr_expr (tree, tsubst_flags_t);
|
||||
extern tree cp_build_unary_op (enum tree_code, tree, bool,
|
||||
tsubst_flags_t);
|
||||
|
|
|
|||
|
|
@ -380,6 +380,7 @@ pp_cxx_userdef_literal (cxx_pretty_printer *pp, tree t)
|
|||
GNU Extensions:
|
||||
__builtin_va_arg ( assignment-expression , type-id )
|
||||
__builtin_offsetof ( type-id, offsetof-expression )
|
||||
__builtin_addressof ( expression )
|
||||
|
||||
__has_nothrow_assign ( type-id )
|
||||
__has_nothrow_constructor ( type-id )
|
||||
|
|
@ -387,6 +388,7 @@ pp_cxx_userdef_literal (cxx_pretty_printer *pp, tree t)
|
|||
__has_trivial_assign ( type-id )
|
||||
__has_trivial_constructor ( type-id )
|
||||
__has_trivial_copy ( type-id )
|
||||
__has_unique_object_representations ( type-id )
|
||||
__has_trivial_destructor ( type-id )
|
||||
__has_virtual_destructor ( type-id )
|
||||
__is_abstract ( type-id )
|
||||
|
|
@ -456,6 +458,10 @@ cxx_pretty_printer::primary_expression (tree t)
|
|||
pp_cxx_offsetof_expression (this, t);
|
||||
break;
|
||||
|
||||
case ADDRESSOF_EXPR:
|
||||
pp_cxx_addressof_expression (this, t);
|
||||
break;
|
||||
|
||||
case REQUIRES_EXPR:
|
||||
pp_cxx_requires_expr (this, t);
|
||||
break;
|
||||
|
|
@ -2437,6 +2443,15 @@ pp_cxx_offsetof_expression (cxx_pretty_printer *pp, tree t)
|
|||
pp_cxx_right_paren (pp);
|
||||
}
|
||||
|
||||
void
|
||||
pp_cxx_addressof_expression (cxx_pretty_printer *pp, tree t)
|
||||
{
|
||||
pp_cxx_ws_string (pp, "__builtin_addressof");
|
||||
pp_cxx_left_paren (pp);
|
||||
pp->expression (TREE_OPERAND (t, 0));
|
||||
pp_cxx_right_paren (pp);
|
||||
}
|
||||
|
||||
static char const*
|
||||
get_fold_operator (tree t)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ void pp_cxx_canonical_template_parameter (cxx_pretty_printer *, tree);
|
|||
void pp_cxx_trait_expression (cxx_pretty_printer *, tree);
|
||||
void pp_cxx_va_arg_expression (cxx_pretty_printer *, tree);
|
||||
void pp_cxx_offsetof_expression (cxx_pretty_printer *, tree);
|
||||
void pp_cxx_addressof_expression (cxx_pretty_printer *, tree);
|
||||
void pp_cxx_userdef_literal (cxx_pretty_printer *, tree);
|
||||
void pp_cxx_requires_clause (cxx_pretty_printer *, tree);
|
||||
void pp_cxx_requires_expr (cxx_pretty_printer *, tree);
|
||||
|
|
|
|||
|
|
@ -2678,6 +2678,10 @@ dump_expr (cxx_pretty_printer *pp, tree t, int flags)
|
|||
pp_cxx_offsetof_expression (pp, t);
|
||||
break;
|
||||
|
||||
case ADDRESSOF_EXPR:
|
||||
pp_cxx_addressof_expression (pp, t);
|
||||
break;
|
||||
|
||||
case SCOPE_REF:
|
||||
dump_decl (pp, t, flags);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -6602,6 +6602,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
|
|||
break;
|
||||
}
|
||||
|
||||
case RID_ADDRESSOF:
|
||||
case RID_BUILTIN_SHUFFLE:
|
||||
{
|
||||
vec<tree, va_gc> *vec;
|
||||
|
|
@ -6618,19 +6619,29 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
|
|||
FOR_EACH_VEC_ELT (*vec, i, p)
|
||||
mark_exp_read (p);
|
||||
|
||||
if (vec->length () == 2)
|
||||
return build_x_vec_perm_expr (loc, (*vec)[0], NULL_TREE, (*vec)[1],
|
||||
tf_warning_or_error);
|
||||
else if (vec->length () == 3)
|
||||
return build_x_vec_perm_expr (loc, (*vec)[0], (*vec)[1], (*vec)[2],
|
||||
tf_warning_or_error);
|
||||
else
|
||||
{
|
||||
error_at (loc, "wrong number of arguments to "
|
||||
"%<__builtin_shuffle%>");
|
||||
return error_mark_node;
|
||||
}
|
||||
break;
|
||||
switch (keyword)
|
||||
{
|
||||
case RID_ADDRESSOF:
|
||||
if (vec->length () == 1)
|
||||
return cp_build_addressof (loc, (*vec)[0], tf_warning_or_error);
|
||||
error_at (loc, "wrong number of arguments to "
|
||||
"%<__builtin_addressof%>");
|
||||
return error_mark_node;
|
||||
|
||||
case RID_BUILTIN_SHUFFLE:
|
||||
if (vec->length () == 2)
|
||||
return build_x_vec_perm_expr (loc, (*vec)[0], NULL_TREE,
|
||||
(*vec)[1], tf_warning_or_error);
|
||||
else if (vec->length () == 3)
|
||||
return build_x_vec_perm_expr (loc, (*vec)[0], (*vec)[1],
|
||||
(*vec)[2], tf_warning_or_error);
|
||||
error_at (loc, "wrong number of arguments to "
|
||||
"%<__builtin_shuffle%>");
|
||||
return error_mark_node;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -17204,6 +17204,10 @@ tsubst_copy_and_build (tree t,
|
|||
RETURN (finish_offsetof (RECUR (TREE_OPERAND (t, 0)),
|
||||
EXPR_LOCATION (t)));
|
||||
|
||||
case ADDRESSOF_EXPR:
|
||||
RETURN (cp_build_addressof (EXPR_LOCATION (t),
|
||||
RECUR (TREE_OPERAND (t, 0)), complain));
|
||||
|
||||
case TRAIT_EXPR:
|
||||
{
|
||||
tree type1 = tsubst (TRAIT_EXPR_TYPE1 (t), args,
|
||||
|
|
|
|||
|
|
@ -5456,6 +5456,29 @@ build_x_unary_op (location_t loc, enum tree_code code, cp_expr xarg,
|
|||
return exp;
|
||||
}
|
||||
|
||||
/* Construct and perhaps optimize a tree representation
|
||||
for __builtin_addressof operation. ARG specifies the operand. */
|
||||
|
||||
tree
|
||||
cp_build_addressof (location_t loc, tree arg, tsubst_flags_t complain)
|
||||
{
|
||||
tree orig_expr = arg;
|
||||
|
||||
if (processing_template_decl)
|
||||
{
|
||||
if (type_dependent_expression_p (arg))
|
||||
return build_min_nt_loc (loc, ADDRESSOF_EXPR, arg, NULL_TREE);
|
||||
|
||||
arg = build_non_dependent_expr (arg);
|
||||
}
|
||||
|
||||
tree exp = cp_build_addr_expr_strict (arg, complain);
|
||||
|
||||
if (processing_template_decl && exp != error_mark_node)
|
||||
exp = build_min_non_dep (ADDRESSOF_EXPR, exp, orig_expr, NULL_TREE);
|
||||
return exp;
|
||||
}
|
||||
|
||||
/* Like c_common_truthvalue_conversion, but handle pointer-to-member
|
||||
constants, where a null value is represented by an INTEGER_CST of
|
||||
-1. */
|
||||
|
|
|
|||
|
|
@ -1,3 +1,8 @@
|
|||
2016-10-07 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* g++.dg/cpp0x/addressof1.C: New test.
|
||||
* g++.dg/cpp0x/addressof2.C: New test.
|
||||
|
||||
2016-10-06 Michael Meissner <meissner@linux.vnet.ibm.com>
|
||||
|
||||
* gcc.target/powerpc/float128-type-1.c: New test to check that
|
||||
|
|
|
|||
|
|
@ -0,0 +1,96 @@
|
|||
// LWG2296 - addressof should be constexpr
|
||||
// { dg-do run { target c++11 } }
|
||||
|
||||
template <typename T>
|
||||
constexpr inline T *
|
||||
addressof (T &x) noexcept
|
||||
{
|
||||
return __builtin_addressof (x);
|
||||
}
|
||||
|
||||
int i;
|
||||
static_assert (__builtin_addressof (i) == &i, "");
|
||||
static_assert (addressof (i) == &i, "");
|
||||
|
||||
constexpr int &j = i;
|
||||
static_assert (__builtin_addressof (j) == &i, "");
|
||||
static_assert (addressof (j) == &i, "");
|
||||
|
||||
struct S { int s; } s;
|
||||
static_assert (__builtin_addressof (s) == &s, "");
|
||||
static_assert ((int *) __builtin_addressof (s) == &s.s, "");
|
||||
static_assert (addressof (s) == &s, "");
|
||||
static_assert ((int *) addressof (s) == &s.s, "");
|
||||
|
||||
struct T
|
||||
{
|
||||
static T tt;
|
||||
constexpr T () : p (addressof (tt)) {}
|
||||
constexpr T *operator & () const { return p; }
|
||||
T *p;
|
||||
};
|
||||
constexpr T t;
|
||||
T T::tt;
|
||||
static_assert (__builtin_addressof (t) == (const T *) &t.p, "");
|
||||
static_assert (&t == __builtin_addressof (T::tt), "");
|
||||
static_assert (addressof (t) == (const T *) &t.p, "");
|
||||
static_assert (&t == addressof (T::tt), "");
|
||||
|
||||
struct S x, y;
|
||||
|
||||
constexpr S *
|
||||
foo (bool b)
|
||||
{
|
||||
return __builtin_addressof (b ? x : y);
|
||||
}
|
||||
|
||||
constexpr S *
|
||||
bar (bool b, S &c, S &d)
|
||||
{
|
||||
return __builtin_addressof (b ? c : d);
|
||||
}
|
||||
|
||||
static_assert (foo (false) == &y, "");
|
||||
static_assert (foo (true) == &x, "");
|
||||
static_assert (bar (false, y, x) == &x, "");
|
||||
static_assert (bar (true, y, x) == &y, "");
|
||||
|
||||
constexpr S *
|
||||
foo2 (bool b)
|
||||
{
|
||||
return addressof (b ? x : y);
|
||||
}
|
||||
|
||||
constexpr S *
|
||||
bar2 (bool b, S &c, S &d)
|
||||
{
|
||||
return addressof (b ? c : d);
|
||||
}
|
||||
|
||||
static_assert (foo2 (false) == &y, "");
|
||||
static_assert (foo2 (true) == &x, "");
|
||||
static_assert (bar2 (false, y, x) == &x, "");
|
||||
static_assert (bar2 (true, y, x) == &y, "");
|
||||
|
||||
constexpr int a = 1;
|
||||
static_assert (__builtin_addressof (a) == &a, "");
|
||||
static_assert (addressof (a) == &a, "");
|
||||
constexpr int c[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
|
||||
static_assert ((const int *) __builtin_addressof (c) == &c[0], "");
|
||||
static_assert ((const int *) addressof (c) == &c[0], "");
|
||||
|
||||
void
|
||||
baz ()
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
if (__builtin_addressof (T::tt) == __builtin_addressof (t)
|
||||
|| addressof (T::tt) == addressof (t)
|
||||
|| &T::tt != &t
|
||||
|| __builtin_addressof (baz) != baz
|
||||
|| addressof (baz) != baz)
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// LWG2296 - addressof should be constexpr
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
template <typename T>
|
||||
constexpr inline T *
|
||||
addressof (T &x) noexcept
|
||||
{
|
||||
return __builtin_addressof (x);
|
||||
}
|
||||
|
||||
auto a = __builtin_addressof (1); // { dg-error "lvalue required as unary" }
|
||||
auto b = addressof (1); // { dg-error "cannot bind non-const lvalue reference of type" }
|
||||
|
||||
struct S { int s : 5; int t; void foo (); } s;
|
||||
|
||||
auto c = __builtin_addressof (s);
|
||||
auto d = addressof (s);
|
||||
auto e = __builtin_addressof (s.s); // { dg-error "attempt to take address of bit-field structure member" }
|
||||
auto f = addressof (s.s); // { dg-error "cannot bind bitfield" }
|
||||
auto g = __builtin_addressof (S{}); // { dg-error "taking address of temporary" }
|
||||
auto h = addressof (S{}); // { dg-error "cannot bind non-const lvalue reference of type" }
|
||||
auto i = __builtin_addressof (S::t); // { dg-error "invalid use of non-static data member" }
|
||||
auto j = __builtin_addressof (S::foo); // { dg-error "invalid use of non-static member function" }
|
||||
|
||||
void
|
||||
foo (bool b)
|
||||
{
|
||||
lab:;
|
||||
char c;
|
||||
long long int d;
|
||||
auto k = __builtin_addressof (lab); // { dg-error "was not declared in this scope" }
|
||||
auto l = __builtin_addressof (b ? c : d); // { dg-error "lvalue required as unary" }
|
||||
}
|
||||
Loading…
Reference in New Issue