]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/69958 (sizeof... computes wrong size)
authorJason Merrill <jason@redhat.com>
Fri, 26 Feb 2016 19:54:33 +0000 (14:54 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 26 Feb 2016 19:54:33 +0000 (14:54 -0500)
PR c++/69958
* pt.c (make_argument_pack): New.
(tsubst_copy) [SIZEOF_EXPR]: Handle partial expansion.
(tsubst_copy_and_build): Likewise.

From-SVN: r233758

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp0x/variadic-sizeof4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/variadic-sizeof4a.C [new file with mode: 0644]

index ecab54585f52640e19fccaa04f59a7fc6198dd32..ec991201009f365a2bd89eaf49c64c020a428dd8 100644 (file)
@@ -1,3 +1,10 @@
+2016-02-26  Jason Merrill  <jason@redhat.com>
+
+       PR c++/69958
+       * pt.c (make_argument_pack): New.
+       (tsubst_copy) [SIZEOF_EXPR]: Handle partial expansion.
+       (tsubst_copy_and_build): Likewise.
+
 2016-02-25  Jason Merrill  <jason@redhat.com>
 
        PR c++/69889
index cd3eb6757cf9c906ef03f739a9fefe41e1483f81..b5855a8d13ccf5e503ecf5c98a2f49907b1e62d3 100644 (file)
@@ -11117,6 +11117,25 @@ get_pattern_parm (tree parm, tree tmpl)
   return patparm;
 }
 
+/* Make an argument pack out of the TREE_VEC VEC.  */
+
+static tree
+make_argument_pack (tree vec)
+{
+  tree pack;
+  tree elt = TREE_VEC_ELT (vec, 0);
+  if (TYPE_P (elt))
+    pack = cxx_make_type (TYPE_ARGUMENT_PACK);
+  else
+    {
+      pack = make_node (NONTYPE_ARGUMENT_PACK);
+      TREE_TYPE (pack) = TREE_TYPE (elt);
+      TREE_CONSTANT (pack) = 1;
+    }
+  SET_ARGUMENT_PACK_ARGS (pack, vec);
+  return pack;
+}
+
 /* Substitute ARGS into the vector or list of template arguments T.  */
 
 static tree
@@ -14066,7 +14085,8 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       }
 
     case SIZEOF_EXPR:
-      if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
+      if (PACK_EXPANSION_P (TREE_OPERAND (t, 0))
+         || ARGUMENT_PACK_P (TREE_OPERAND (t, 0)))
         {
           tree expanded, op = TREE_OPERAND (t, 0);
          int len = 0;
@@ -14077,7 +14097,11 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
          ++cp_unevaluated_operand;
          ++c_inhibit_evaluation_warnings;
          /* We only want to compute the number of arguments.  */
-         expanded = tsubst_pack_expansion (op, args, complain, in_decl);
+         if (PACK_EXPANSION_P (op))
+           expanded = tsubst_pack_expansion (op, args, complain, in_decl);
+         else
+           expanded = tsubst_template_args (ARGUMENT_PACK_ARGS (op),
+                                            args, complain, in_decl);
          --cp_unevaluated_operand;
          --c_inhibit_evaluation_warnings;
 
@@ -14093,13 +14117,15 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
            return error_mark_node;
          else if (PACK_EXPANSION_P (expanded)
                   || (TREE_CODE (expanded) == TREE_VEC
-                      && len > 0
-                      && PACK_EXPANSION_P (TREE_VEC_ELT (expanded, len-1))))
+                      && pack_expansion_args_count (expanded)))
+
            {
-             if (TREE_CODE (expanded) == TREE_VEC)
-               expanded = TREE_VEC_ELT (expanded, len - 1);
+             if (PACK_EXPANSION_P (expanded))
+               /* OK.  */;
+             else if (TREE_VEC_LENGTH (expanded) == 1)
+               expanded = TREE_VEC_ELT (expanded, 0);
              else
-               PACK_EXPANSION_SIZEOF_P (expanded) = true;
+               expanded = make_argument_pack (expanded);
 
              if (TYPE_P (expanded))
                return cxx_sizeof_or_alignof_type (expanded, SIZEOF_EXPR, 
@@ -16162,7 +16188,8 @@ tsubst_copy_and_build (tree t,
                                          length, stride, TREE_TYPE (op1)));
       }
     case SIZEOF_EXPR:
-      if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
+      if (PACK_EXPANSION_P (TREE_OPERAND (t, 0))
+         || ARGUMENT_PACK_P (TREE_OPERAND (t, 0)))
        RETURN (tsubst_copy (t, args, complain, in_decl));
       /* Fall through */
       
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-sizeof4.C b/gcc/testsuite/g++.dg/cpp0x/variadic-sizeof4.C
new file mode 100644 (file)
index 0000000..1187429
--- /dev/null
@@ -0,0 +1,33 @@
+// PR c++/69958
+// { dg-do compile { target c++11 } }
+
+typedef decltype(sizeof(int)) size_t;
+
+template <typename...Ts>
+struct list { };
+
+template <size_t N>
+struct size {  };
+
+template <typename...Ts>
+using size_for = size<sizeof...(Ts)>;
+
+template<class T, class U> struct assert_same;
+template<class T> struct assert_same<T,T> {};
+
+template <typename T, typename...Ts>
+using wrapped = list<T, size_for<T, Ts...>>;
+
+// This assertion fails (produces size<4>)
+assert_same<
+    list<float, size<5>>,
+    wrapped<float, int, double, char, unsigned>> a3;
+
+
+template <typename T, typename...Ts>
+using wrapped2 = list<T, size_for<Ts..., T>>;
+
+// This assertion fails (produces size<2>)
+assert_same<
+    list<float, size<5>>,
+    wrapped2<float, int, double, char, unsigned>> a4;
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-sizeof4a.C b/gcc/testsuite/g++.dg/cpp0x/variadic-sizeof4a.C
new file mode 100644 (file)
index 0000000..0e8096d
--- /dev/null
@@ -0,0 +1,33 @@
+// PR c++/69958
+// { dg-do compile { target c++11 } }
+
+typedef decltype(sizeof(int)) size_t;
+
+template <typename...Ts>
+struct list { };
+
+template <size_t N>
+struct size {  };
+
+template <unsigned...Ts>
+using size_for = size<sizeof...(Ts)>;
+
+template<class T, class U> struct assert_same;
+template<class T> struct assert_same<T,T> {};
+
+template <typename T, unsigned...Ts>
+using wrapped = list<T, size_for<0, Ts...>>;
+
+// This assertion fails (produces size<4>)
+assert_same<
+    list<float, size<5>>,
+  wrapped<float,2,3,4,5>> a3;
+
+
+template <typename T, unsigned...Ts>
+using wrapped2 = list<T, size_for<Ts..., 0>>;
+
+// This assertion fails (produces size<2>)
+assert_same<
+    list<float, size<5>>,
+  wrapped2<float,2,3,4,5>> a4;