From bedc293e87af0c0322a9dac004dc7b7c86a7579b Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 27 Jun 2013 23:29:22 +0200 Subject: [PATCH] re PR c++/57509 (Segmentation fault when using __builtin_shuffle in templated class.) 2013-06-27 Marc Glisse PR c++/57509 gcc/c-family/ * c-common.h (c_build_vec_perm_expr): New complain argument. * c-common.c (c_build_vec_perm_expr): Likewise. Use save_expr also in C++. gcc/cp/ * typeck.c (cp_build_vec_perm_expr): New function. * cp-tree.h: Declare it. * parser.c (cp_parser_postfix_expression): Call it. * pt.c (tsubst_copy): Handle VEC_PERM_EXPR. (tsubst_copy_and_build): Likewise. gcc/testsuite/ * g++.dg/ext/pr57509.C: New file. From-SVN: r200495 --- gcc/c-family/ChangeLog | 7 +++++++ gcc/c-family/c-common.c | 30 +++++++++++++++++++----------- gcc/c-family/c-common.h | 2 +- gcc/cp/ChangeLog | 9 +++++++++ gcc/cp/cp-tree.h | 3 +++ gcc/cp/parser.c | 6 ++++-- gcc/cp/pt.c | 8 ++++++++ gcc/cp/typeck.c | 15 +++++++++++++++ gcc/testsuite/ChangeLog | 5 +++++ gcc/testsuite/g++.dg/ext/pr57509.C | 16 ++++++++++++++++ 10 files changed, 87 insertions(+), 14 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ext/pr57509.C diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index bc73a809a55..c9a4f70e8bc 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,10 @@ +2013-06-27 Marc Glisse + + PR c++/57509 + * c-common.h (c_build_vec_perm_expr): New complain argument. + * c-common.c (c_build_vec_perm_expr): Likewise. + Use save_expr also in C++. + 2013-06-22 Gabriel Dos Reis * c-common.c (c_common_nodes_and_builtins): Use cxx11 in lieu of cxx0x. diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 8b780c20845..8f7f5e52b0a 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -2260,7 +2260,8 @@ vector_types_convertible_p (const_tree t1, const_tree t2, bool emit_lax_note) an implementation accident and this semantics is not guaranteed to the user. */ tree -c_build_vec_perm_expr (location_t loc, tree v0, tree v1, tree mask) +c_build_vec_perm_expr (location_t loc, tree v0, tree v1, tree mask, + bool complain) { tree ret; bool wrap = true; @@ -2280,22 +2281,25 @@ c_build_vec_perm_expr (location_t loc, tree v0, tree v1, tree mask) if (TREE_CODE (TREE_TYPE (mask)) != VECTOR_TYPE || TREE_CODE (TREE_TYPE (TREE_TYPE (mask))) != INTEGER_TYPE) { - error_at (loc, "__builtin_shuffle last argument must " - "be an integer vector"); + if (complain) + error_at (loc, "__builtin_shuffle last argument must " + "be an integer vector"); return error_mark_node; } if (TREE_CODE (TREE_TYPE (v0)) != VECTOR_TYPE || TREE_CODE (TREE_TYPE (v1)) != VECTOR_TYPE) { - error_at (loc, "__builtin_shuffle arguments must be vectors"); + if (complain) + error_at (loc, "__builtin_shuffle arguments must be vectors"); return error_mark_node; } if (TYPE_MAIN_VARIANT (TREE_TYPE (v0)) != TYPE_MAIN_VARIANT (TREE_TYPE (v1))) { - error_at (loc, "__builtin_shuffle argument vectors must be of " - "the same type"); + if (complain) + error_at (loc, "__builtin_shuffle argument vectors must be of " + "the same type"); return error_mark_node; } @@ -2304,17 +2308,19 @@ c_build_vec_perm_expr (location_t loc, tree v0, tree v1, tree mask) && TYPE_VECTOR_SUBPARTS (TREE_TYPE (v1)) != TYPE_VECTOR_SUBPARTS (TREE_TYPE (mask))) { - error_at (loc, "__builtin_shuffle number of elements of the " - "argument vector(s) and the mask vector should " - "be the same"); + if (complain) + error_at (loc, "__builtin_shuffle number of elements of the " + "argument vector(s) and the mask vector should " + "be the same"); return error_mark_node; } if (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (v0)))) != GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (mask))))) { - error_at (loc, "__builtin_shuffle argument vector(s) inner type " - "must have the same size as inner type of the mask"); + if (complain) + error_at (loc, "__builtin_shuffle argument vector(s) inner type " + "must have the same size as inner type of the mask"); return error_mark_node; } @@ -2335,6 +2341,8 @@ c_build_vec_perm_expr (location_t loc, tree v0, tree v1, tree mask) mask = c_fully_fold (mask, false, &maybe_const); wrap &= maybe_const; } + else if (two_arguments) + v1 = v0 = save_expr (v0); ret = build3_loc (loc, VEC_PERM_EXPR, TREE_TYPE (v0), v0, v1, mask); diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 625c3011460..6dfcffd7921 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -911,7 +911,7 @@ extern bool lvalue_p (const_tree); extern bool vector_targets_convertible_p (const_tree t1, const_tree t2); extern bool vector_types_convertible_p (const_tree t1, const_tree t2, bool emit_lax_note); -extern tree c_build_vec_perm_expr (location_t, tree, tree, tree); +extern tree c_build_vec_perm_expr (location_t, tree, tree, tree, bool = true); extern rtx c_expand_expr (tree, rtx, enum machine_mode, int, rtx *); diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 93e639e8687..4f74133c2e7 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,14 @@ 2013-06-27 Marc Glisse + PR c++/57509 + * typeck.c (cp_build_vec_perm_expr): New function. + * cp-tree.h: Declare it. + * parser.c (cp_parser_postfix_expression): Call it. + * pt.c (tsubst_copy): Handle VEC_PERM_EXPR. + (tsubst_copy_and_build): Likewise. + +2013-06-27 Marc Glisse + PR c++/57172 * pt.c (more_specialized_fn): If both arguments are references, give priority to an lvalue. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 00ee45013b3..4b2cd512f1c 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6042,6 +6042,9 @@ extern tree check_return_expr (tree, bool *); extern tree cp_build_binary_op (location_t, enum tree_code, tree, tree, tsubst_flags_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) extern tree build_simple_component_ref (tree, tree); extern tree build_ptrmemfunc_access_expr (tree, tree); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index ec8ad46dd44..ad2fe257731 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -5691,9 +5691,11 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, mark_exp_read (p); if (vec->length () == 2) - return c_build_vec_perm_expr (loc, (*vec)[0], NULL_TREE, (*vec)[1]); + return build_x_vec_perm_expr (loc, (*vec)[0], NULL_TREE, (*vec)[1], + tf_warning_or_error); else if (vec->length () == 3) - return c_build_vec_perm_expr (loc, (*vec)[0], (*vec)[1], (*vec)[2]); + 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 " diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index e2ffe7314c4..4ab64c9d826 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -12464,6 +12464,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) case COND_EXPR: case MODOP_EXPR: case PSEUDO_DTOR_EXPR: + case VEC_PERM_EXPR: { r = build_nt (code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl), @@ -14628,6 +14629,13 @@ tsubst_copy_and_build (tree t, case PAREN_EXPR: RETURN (finish_parenthesized_expr (RECUR (TREE_OPERAND (t, 0)))); + case VEC_PERM_EXPR: + RETURN (build_x_vec_perm_expr (input_location, + RECUR (TREE_OPERAND (t, 0)), + RECUR (TREE_OPERAND (t, 1)), + RECUR (TREE_OPERAND (t, 2)), + complain)); + default: /* Handle Objective-C++ constructs, if appropriate. */ { diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 5b321ce5a7f..4a7f1f68c71 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -4871,6 +4871,21 @@ cp_build_binary_op (location_t location, return result; } + +/* Build a VEC_PERM_EXPR. + This is a simple wrapper for c_build_vec_perm_expr. */ +tree +build_x_vec_perm_expr (location_t loc, + tree arg0, tree arg1, tree arg2, + tsubst_flags_t complain) +{ + if (processing_template_decl + && (type_dependent_expression_p (arg0) + || type_dependent_expression_p (arg1) + || type_dependent_expression_p (arg2))) + return build_min_nt_loc (loc, VEC_PERM_EXPR, arg0, arg1, arg2); + return c_build_vec_perm_expr (loc, arg0, arg1, arg2, complain & tf_error); +} /* Return a tree for the sum or difference (RESULTCODE says which) of pointer PTROP and integer INTOP. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7bf618df1af..22b10523acb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2013-06-27 Marc Glisse + + PR c++/57509 + * g++.dg/ext/pr57509.C: New file. + 2013-06-27 Jakub Jelinek PR target/57623 diff --git a/gcc/testsuite/g++.dg/ext/pr57509.C b/gcc/testsuite/g++.dg/ext/pr57509.C new file mode 100644 index 00000000000..d44ee81e091 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/pr57509.C @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-std=c++11" } */ + +template struct enable_if {}; +template <> struct enable_if {typedef void type;}; +template void f (T& v) { v = __builtin_shuffle (v, v); } +template void g (T) {} +template auto g (T x) -> typename enable_if::type {} +typedef int v4i __attribute__((vector_size(4*sizeof(int)))); +typedef float v4f __attribute__((vector_size(4*sizeof(float)))); +int main(){ + v4i a = {1,2,3,0}; + f(a); + v4f b = {1,2,3,0}; + g(b); +} -- 2.11.4.GIT