aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/c-family/ChangeLog5
-rw-r--r--gcc/c-family/c-common.c1
-rw-r--r--gcc/c-family/c-common.h4
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/constexpr.c5
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/parser.c13
-rw-r--r--gcc/cp/pt.c60
-rw-r--r--gcc/cp/semantics.c22
-rw-r--r--gcc/internal-fn.c13
-rw-r--r--gcc/internal-fn.def3
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/launder1.C51
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/launder2.C42
15 files changed, 227 insertions, 19 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index cb290f1..c833186 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,4 +1,10 @@
+2016-10-25 Jakub Jelinek <jakub@redhat.com>
+
+ * internal-fn.def (LAUNDER): New internal function.
+ * internal-fn.c (expand_LAUNDER): New function.
+
2016-10-25 Georg-Johann Lay <avr@gjlay.de>
+ Pitchumani Sivanupandi <pitchumani.sivanupandi@microchip.com>
New avr target pass to work around performance loss by PR fix.
@@ -18,7 +24,7 @@
(avr_optimize_casesi): New functions.
2016-10-25 Georg-Johann Lay <avr@gjlay.de>
- Pitchumani Sivanupandi <pitchumani.sivanupandi@microchip.com>
+ Pitchumani Sivanupandi <pitchumani.sivanupandi@microchip.com>
PR target/71676
PR target/71678
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 6a6dba2..15d7488 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,8 @@
+2016-10-25 Jakub Jelinek <jakub@redhat.com>
+
+ * c-common.h (enum rid): Add RID_BUILTIN_LAUNDER.
+ * c-common.c (c_common_reswords): Add __builtin_launder.
+
2016-10-24 Bernd Edlinger <bernd.edlinger@hotmail.de>
* c-common.c (c_common_truthvalue_conversion): Warn for
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index c0dafc0..307862b 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -375,6 +375,7 @@ const struct c_common_resword c_common_reswords[] =
RID_BUILTIN_CALL_WITH_STATIC_CHAIN, D_CONLY },
{ "__builtin_choose_expr", RID_CHOOSE_EXPR, D_CONLY },
{ "__builtin_complex", RID_BUILTIN_COMPLEX, D_CONLY },
+ { "__builtin_launder", RID_BUILTIN_LAUNDER, D_CXXONLY },
{ "__builtin_shuffle", RID_BUILTIN_SHUFFLE, 0 },
{ "__builtin_offsetof", RID_OFFSETOF, 0 },
{ "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, D_CONLY },
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index bfdbda0..547bab2 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -146,8 +146,8 @@ enum rid
RID_CONSTCAST, RID_DYNCAST, RID_REINTCAST, RID_STATCAST,
/* C++ extensions */
- RID_ADDRESSOF,
- RID_BASES, RID_DIRECT_BASES,
+ RID_ADDRESSOF, RID_BASES,
+ RID_BUILTIN_LAUNDER, RID_DIRECT_BASES,
RID_HAS_NOTHROW_ASSIGN, RID_HAS_NOTHROW_CONSTRUCTOR,
RID_HAS_NOTHROW_COPY, RID_HAS_TRIVIAL_ASSIGN,
RID_HAS_TRIVIAL_CONSTRUCTOR, RID_HAS_TRIVIAL_COPY,
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 744eb52..21c6408 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,12 @@
+2016-10-25 Jakub Jelinek <jakub@redhat.com>
+
+ * cp-tree.h (finish_builtin_launder): Declare.
+ * parser.c (cp_parser_postfix_expression): Handle RID_BUILTIN_LAUNDER.
+ * semantics.c (finish_builtin_launder): New function.
+ * pt.c (tsubst_copy_and_build): Handle instantiation of IFN_LAUNDER.
+ * constexpr.c (cxx_eval_internal_function): Handle IFN_LAUNDER.
+ (potential_constant_expression_1): Likewise.
+
2016-10-24 Jakub Jelinek <jakub@redhat.com>
* cp-objcp-common.c (cp_decl_dwarf_attribute): Handle DW_AT_reference
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 3c4fcfa..8f7b7f3 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -1330,6 +1330,10 @@ cxx_eval_internal_function (const constexpr_ctx *ctx, tree t,
opcode = MULT_EXPR;
break;
+ case IFN_LAUNDER:
+ return cxx_eval_constant_expression (ctx, CALL_EXPR_ARG (t, 0),
+ false, non_constant_p, overflow_p);
+
default:
if (!ctx->quiet)
error_at (EXPR_LOC_OR_LOC (t, input_location),
@@ -4920,6 +4924,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict,
case IFN_ADD_OVERFLOW:
case IFN_SUB_OVERFLOW:
case IFN_MUL_OVERFLOW:
+ case IFN_LAUNDER:
bail = false;
default:
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index f4a8985..c589969 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6494,6 +6494,8 @@ extern bool generic_lambda_fn_p (tree);
extern void maybe_add_lambda_conv_op (tree);
extern bool is_lambda_ignored_entity (tree);
extern bool lambda_static_thunk_p (tree);
+extern tree finish_builtin_launder (location_t, tree,
+ tsubst_flags_t);
/* in tree.c */
extern int cp_tree_operand_length (const_tree);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 643c1e7..f962dfb 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6604,6 +6604,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
case RID_ADDRESSOF:
case RID_BUILTIN_SHUFFLE:
+ case RID_BUILTIN_LAUNDER:
{
vec<tree, va_gc> *vec;
unsigned int i;
@@ -6628,6 +6629,18 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
"%<__builtin_addressof%>");
return error_mark_node;
+ case RID_BUILTIN_LAUNDER:
+ if (vec->length () == 1)
+ postfix_expression = finish_builtin_launder (loc, (*vec)[0],
+ tf_warning_or_error);
+ else
+ {
+ error_at (loc, "wrong number of arguments to "
+ "%<__builtin_launder%>");
+ postfix_expression = error_mark_node;
+ }
+ break;
+
case RID_BUILTIN_SHUFFLE:
if (vec->length () == 2)
return build_x_vec_perm_expr (loc, (*vec)[0], NULL_TREE,
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index aa126a0..c916e58 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -16599,19 +16599,19 @@ tsubst_copy_and_build (tree t,
tree ret;
function = CALL_EXPR_FN (t);
- if (function == NULL_TREE)
- {
- /* If you hit this assert, it means that you're trying to tsubst
- an internal function with arguments. This isn't yet supported,
- so you need to build another internal call with the tsubsted
- arguments after the arguments have been tsubsted down below. */
- gcc_assert (call_expr_nargs (t) == 0);
- RETURN (t);
- }
+ /* Internal function with no arguments. */
+ if (function == NULL_TREE && call_expr_nargs (t) == 0)
+ RETURN (t);
+
/* When we parsed the expression, we determined whether or
not Koenig lookup should be performed. */
koenig_p = KOENIG_LOOKUP_P (t);
- if (TREE_CODE (function) == SCOPE_REF)
+ if (function == NULL_TREE)
+ {
+ koenig_p = false;
+ qualified_p = false;
+ }
+ else if (TREE_CODE (function) == SCOPE_REF)
{
qualified_p = true;
function = tsubst_qualified_id (function, args, complain, in_decl,
@@ -16709,7 +16709,8 @@ tsubst_copy_and_build (tree t,
&& !any_type_dependent_arguments_p (call_args))
function = perform_koenig_lookup (function, call_args, tf_none);
- if (identifier_p (function)
+ if (function != NULL_TREE
+ && identifier_p (function)
&& !any_type_dependent_arguments_p (call_args))
{
if (koenig_p && (complain & tf_warning_or_error))
@@ -16721,7 +16722,10 @@ tsubst_copy_and_build (tree t,
(function, args, complain, in_decl, true,
integral_constant_expression_p));
if (unq == error_mark_node)
- RETURN (error_mark_node);
+ {
+ release_tree_vector (call_args);
+ RETURN (error_mark_node);
+ }
if (unq != function)
{
@@ -16774,14 +16778,40 @@ tsubst_copy_and_build (tree t,
}
/* Remember that there was a reference to this entity. */
- if (DECL_P (function)
+ if (function != NULL_TREE
+ && DECL_P (function)
&& !mark_used (function, complain) && !(complain & tf_error))
- RETURN (error_mark_node);
+ {
+ release_tree_vector (call_args);
+ RETURN (error_mark_node);
+ }
/* Put back tf_decltype for the actual call. */
complain |= decltype_flag;
- if (TREE_CODE (function) == OFFSET_REF)
+ if (function == NULL_TREE)
+ switch (CALL_EXPR_IFN (t))
+ {
+ case IFN_LAUNDER:
+ gcc_assert (nargs == 1);
+ if (vec_safe_length (call_args) != 1)
+ {
+ error_at (EXPR_LOC_OR_LOC (t, input_location),
+ "wrong number of arguments to "
+ "%<__builtin_launder%>");
+ ret = error_mark_node;
+ }
+ else
+ ret = finish_builtin_launder (EXPR_LOC_OR_LOC (t,
+ input_location),
+ (*call_args)[0], complain);
+ break;
+
+ default:
+ /* Unsupported internal function with arguments. */
+ gcc_unreachable ();
+ }
+ else if (TREE_CODE (function) == OFFSET_REF)
ret = build_offset_ref_call_from_tree (function, &call_args,
complain);
else if (TREE_CODE (function) == COMPONENT_REF)
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 968f88b..1a7c478 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -9449,4 +9449,26 @@ finish_binary_fold_expr (tree expr1, tree expr2, int op)
return error_mark_node;
}
+/* Finish __builtin_launder (arg). */
+
+tree
+finish_builtin_launder (location_t loc, tree arg, tsubst_flags_t complain)
+{
+ tree orig_arg = arg;
+ if (!type_dependent_expression_p (arg))
+ arg = decay_conversion (arg, complain);
+ if (error_operand_p (arg))
+ return error_mark_node;
+ if (!type_dependent_expression_p (arg)
+ && TREE_CODE (TREE_TYPE (arg)) != POINTER_TYPE)
+ {
+ error_at (loc, "non-pointer argument to %<__builtin_launder%>");
+ return error_mark_node;
+ }
+ if (processing_template_decl)
+ arg = orig_arg;
+ return build_call_expr_internal_loc (loc, IFN_LAUNDER,
+ TREE_TYPE (arg), 1, arg);
+}
+
#include "gt-cp-semantics.h"
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index 0b32d5f..4477697 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -2207,6 +2207,19 @@ expand_ATOMIC_COMPARE_EXCHANGE (internal_fn, gcall *call)
expand_ifn_atomic_compare_exchange (call);
}
+/* Expand LAUNDER to assignment, lhs = arg0. */
+
+static void
+expand_LAUNDER (internal_fn, gcall *call)
+{
+ tree lhs = gimple_call_lhs (call);
+
+ if (!lhs)
+ return;
+
+ expand_assignment (lhs, gimple_call_arg (call, 0), false);
+}
+
/* Expand a call to FN using the operands in STMT. FN has a single
output operand and NARGS input operands. */
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index d4fbdb2..28863df 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -198,6 +198,9 @@ DEF_INTERNAL_FN (ATOMIC_COMPARE_EXCHANGE, ECF_LEAF | ECF_NOTHROW, NULL)
/* To implement [[fallthrough]]. */
DEF_INTERNAL_FN (FALLTHROUGH, ECF_LEAF | ECF_NOTHROW, NULL)
+/* To implement __builtin_launder. */
+DEF_INTERNAL_FN (LAUNDER, ECF_LEAF | ECF_NOTHROW | ECF_NOVOPS, NULL)
+
#undef DEF_INTERNAL_INT_FN
#undef DEF_INTERNAL_FLT_FN
#undef DEF_INTERNAL_OPTAB_FN
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4fa3b4f..1dc0732 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,11 +1,17 @@
+2016-10-25 Jakub Jelinek <jakub@redhat.com>
+
+ * g++.dg/cpp1z/launder1.C: New test.
+ * g++.dg/cpp1z/launder2.C: New test.
+
2016-10-25 Georg-Johann Lay <avr@gjlay.de>
+ Pitchumani Sivanupandi <pitchumani.sivanupandi@microchip.com>
PR target/71676
PR target/71678
* gcc.target/avr/pr71676-2.c: New test.
2016-10-25 Georg-Johann Lay <avr@gjlay.de>
- Pitchumani Sivanupandi <pitchumani.sivanupandi@microchip.com>
+ Pitchumani Sivanupandi <pitchumani.sivanupandi@microchip.com>
PR target/71676
PR target/71678
diff --git a/gcc/testsuite/g++.dg/cpp1z/launder1.C b/gcc/testsuite/g++.dg/cpp1z/launder1.C
new file mode 100644
index 0000000..8f3b022
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/launder1.C
@@ -0,0 +1,51 @@
+// { dg-do run { target c++11 } }
+// { dg-additional-options "-O2" }
+
+void *
+operator new (decltype (sizeof (0)), void *p)
+{
+ return p;
+}
+
+namespace std
+{
+ template <typename T>
+ T *
+ launder (T *p)
+ {
+ return __builtin_launder (p);
+ }
+}
+
+struct A
+{
+ virtual int f ();
+};
+
+struct B : A
+{
+ virtual int f ()
+ {
+ new (this) A;
+ return 1;
+ }
+};
+
+int
+A::f ()
+{
+ new (this) B;
+ return 2;
+}
+
+static_assert (sizeof (B) == sizeof (A), "");
+
+int
+main ()
+{
+ A a;
+ int n = a.f ();
+ int m = std::launder (&a)->f ();
+ if (n != 2 || m != 1)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/launder2.C b/gcc/testsuite/g++.dg/cpp1z/launder2.C
new file mode 100644
index 0000000..9cd1779
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/launder2.C
@@ -0,0 +1,42 @@
+// { dg-do compile { target c++11 } }
+
+int a;
+int *b = __builtin_launder (); // { dg-error "wrong number of arguments to" }
+int *c = __builtin_launder (&a, 2); // { dg-error "wrong number of arguments to" }
+int *d = __builtin_launder (&a);
+int e = __builtin_launder (a); // { dg-error "non-pointer argument to" }
+int &f = a;
+int g = __builtin_launder (f); // { dg-error "non-pointer argument to" }
+
+template <typename T> T f1 (T x) { return __builtin_launder (x); } // { dg-error "non-pointer argument to" }
+template <typename T> T f2 (T x) { return __builtin_launder (x); }
+
+int h = f1 (a);
+int *i = f2 (&a);
+struct S { long s; int foo (); } *j;
+S *k = f2 (j);
+int l = __builtin_launder (j)->foo ();
+
+template <typename T> T *f3 (T *x) { return __builtin_launder (x); }
+
+long *m;
+long *n = f3 (m);
+int *o = f3 (&a);
+
+template <typename T, typename... U> T *f4 (U... x) { return __builtin_launder (x...); }
+template <typename T, typename... U> T *f5 (U... x) { return __builtin_launder (x...); } // { dg-error "wrong number of arguments to" }
+template <typename T, typename... U> T *f6 (U... x) { return __builtin_launder (x...); } // { dg-error "wrong number of arguments to" }
+template <typename T, typename... U> T f7 (T x, U... y) { return __builtin_launder (x, y...); } // { dg-error "wrong number of arguments to" }
+
+long *p = f4<long, long *> (m);
+long *q = f5<long> ();
+long *r = f6<long, long *, int> (m, 1);
+S s;
+int t = __builtin_launder (&s)->foo ();
+
+constexpr const int *f8 (const int *x) { return __builtin_launder (x); }
+template <typename T> constexpr T f9 (T x) { return __builtin_launder (x); }
+constexpr int u = 6;
+constexpr const int *v = f8 (&u);
+constexpr const int *w = f9 (&u);
+static_assert (*f8 (&u) == 6 && *f9 (&u) == 6, "");