re PR c++/57509 (Segmentation fault when using __builtin_shuffle in templated class.)
authorMarc Glisse <marc.glisse@inria.fr>
Thu, 27 Jun 2013 21:29:22 +0000 (23:29 +0200)
committerMarc Glisse <glisse@gcc.gnu.org>
Thu, 27 Jun 2013 21:29:22 +0000 (21:29 +0000)
2013-06-27  Marc Glisse  <marc.glisse@inria.fr>

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
gcc/c-family/c-common.c
gcc/c-family/c-common.h
gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/pr57509.C [new file with mode: 0644]

index bc73a809a555a3ff9a75249050d0c5e0dc7fc3c1..c9a4f70e8bcc0396328d0414f9493ce30a5c68c7 100644 (file)
@@ -1,3 +1,10 @@
+2013-06-27  Marc Glisse  <marc.glisse@inria.fr>
+
+       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  <gdr@integrable-solutions.net>
 
        * c-common.c (c_common_nodes_and_builtins): Use cxx11 in lieu of cxx0x.
index 8b780c20845363253bc10ef8966a56bcb6be58c1..8f7f5e52b0a9b487b1cbcbaeda5e0293a74ad06e 100644 (file)
@@ -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);
 
index 625c3011460c5d0a00c4fdc03ae63bcca091bc55..6dfcffd79218395f029f5dd833f278453a3ef486 100644 (file)
@@ -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 *);
 
index 93e639e868711900b00fea2c616674fb34a90445..4f74133c2e7521b01e55782d17fae2e58b0bc7be 100644 (file)
@@ -1,3 +1,12 @@
+2013-06-27  Marc Glisse  <marc.glisse@inria.fr>
+
+       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  <marc.glisse@inria.fr>
 
        PR c++/57172
index 00ee45013b3313f91ab2e82b2b513f4388c46a02..4b2cd512f1c6cbae065c451c83e0dcc87311e19f 100644 (file)
@@ -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);
index ec8ad46dd44d7aaf9c1b2a3a4c990257f79a0deb..ad2fe257731a9d7ce2262d7c3455d97685165053 100644 (file)
@@ -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 "
index e2ffe7314c44b9bb2bcd783bc7728f26a917851f..4ab64c9d826a5ba4a93f9bf9b4ab942c8cba75eb 100644 (file)
@@ -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.  */
       {
index 5b321ce5a7f9df7001d4e29608d9e41f22b828cd..4a7f1f68c71c46f06546b963d66bc49eeaaacc4a 100644 (file)
@@ -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);
+}
 \f
 /* Return a tree for the sum or difference (RESULTCODE says which)
    of pointer PTROP and integer INTOP.  */
index 7bf618df1af01fb6740361d4fb621925509384e5..22b10523acb1f217c59755d8797dafcbe58c45de 100644 (file)
@@ -1,3 +1,8 @@
+2013-06-27  Marc Glisse  <marc.glisse@inria.fr>
+
+       PR c++/57509
+       * g++.dg/ext/pr57509.C: New file.
+
 2013-06-27  Jakub Jelinek  <jakub@redhat.com>
 
        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 (file)
index 0000000..d44ee81
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c++11" } */
+
+template <bool> struct enable_if {};
+template <> struct enable_if<true> {typedef void type;};
+template <class T> void f (T& v) { v = __builtin_shuffle (v, v); }
+template <class T> void g (T) {}
+template <class T> auto g (T x) -> typename enable_if<sizeof(__builtin_shuffle(x,x))!=2>::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);
+}