PR c++/39367
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 7 Mar 2009 16:21:05 +0000 (16:21 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 7 Mar 2009 16:21:05 +0000 (16:21 +0000)
        * init.c (build_new_1): Don't use a VLA type.
        (build_vec_init): Handle getting a pointer for BASE.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@144697 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/init.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/opt/new1.C [new file with mode: 0644]

index dcf3158..368843f 100644 (file)
@@ -1,3 +1,9 @@
+2009-03-07  Jason Merrill  <jason@redhat.com>
+
+       PR c++/39367
+       * init.c (build_new_1): Don't use a VLA type.
+       (build_vec_init): Handle getting a pointer for BASE.
+
 2009-03-06  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR c++/37520
index 85c496b..8e3e489 100644 (file)
@@ -1787,23 +1787,14 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
   /* True iff this is a call to "operator new[]" instead of just
      "operator new".  */
   bool array_p = false;
-  /* True iff ARRAY_P is true and the bound of the array type is
-     not necessarily a compile time constant.  For example, VLA_P is
-     true for "new int[f()]".  */
-  bool vla_p = false;
-  /* The type being allocated.  If ARRAY_P is true, this will be an
-     ARRAY_TYPE.  */
-  tree full_type;
-  /* If ARRAY_P is true, the element type of the array.  This is an
-     never ARRAY_TYPE; for something like "new int[3][4]", the
+  /* If ARRAY_P is true, the element type of the array.  This is never
+     an ARRAY_TYPE; for something like "new int[3][4]", the
      ELT_TYPE is "int".  If ARRAY_P is false, this is the same type as
-     FULL_TYPE.  */
+     TYPE.  */
   tree elt_type;
   /* The type of the new-expression.  (This type is always a pointer
      type.)  */
   tree pointer_type;
-  /* A pointer type pointing to the FULL_TYPE.  */
-  tree full_pointer_type;
   tree outer_nelts = NULL_TREE;
   tree alloc_call, alloc_expr;
   /* The address returned by the call to "operator new".  This node is
@@ -1834,35 +1825,15 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
 
   if (nelts)
     {
-      tree index;
-
       outer_nelts = nelts;
       array_p = true;
-
-      /* ??? The middle-end will error on us for building a VLA outside a
-        function context.  Methinks that's not it's purvey.  So we'll do
-        our own VLA layout later.  */
-      vla_p = true;
-      index = convert (sizetype, nelts);
-      index = size_binop (MINUS_EXPR, index, size_one_node);
-      index = build_index_type (index);
-      full_type = build_cplus_array_type (type, NULL_TREE);
-      /* We need a copy of the type as build_array_type will return a shared copy
-         of the incomplete array type.  */
-      full_type = build_distinct_type_copy (full_type);
-      TYPE_DOMAIN (full_type) = index;
-      SET_TYPE_STRUCTURAL_EQUALITY (full_type);
     }
-  else
+  else if (TREE_CODE (type) == ARRAY_TYPE)
     {
-      full_type = type;
-      if (TREE_CODE (type) == ARRAY_TYPE)
-       {
-         array_p = true;
-         nelts = array_type_nelts_top (type);
-         outer_nelts = nelts;
-         type = TREE_TYPE (type);
-       }
+      array_p = true;
+      nelts = array_type_nelts_top (type);
+      outer_nelts = nelts;
+      type = TREE_TYPE (type);
     }
 
   /* If our base type is an array, then make sure we know how many elements
@@ -1897,21 +1868,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
 
   size = size_in_bytes (elt_type);
   if (array_p)
-    {
-      size = size_binop (MULT_EXPR, size, convert (sizetype, nelts));
-      if (vla_p)
-       {
-         tree n, bitsize;
-
-         /* Do our own VLA layout.  Setting TYPE_SIZE/_UNIT is
-            necessary in order for the <INIT_EXPR <*foo> <CONSTRUCTOR
-            ...>> to be valid.  */
-         TYPE_SIZE_UNIT (full_type) = size;
-         n = convert (bitsizetype, nelts);
-         bitsize = size_binop (MULT_EXPR, TYPE_SIZE (elt_type), n);
-         TYPE_SIZE (full_type) = bitsize;
-       }
-    }
+    size = size_binop (MULT_EXPR, size, convert (sizetype, nelts));
 
   alloc_fn = NULL_TREE;
 
@@ -2139,8 +2096,9 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
     }
 
   /* Now use a pointer to the type we've actually allocated.  */
-  full_pointer_type = build_pointer_type (full_type);
-  data_addr = fold_convert (full_pointer_type, data_addr);
+  data_addr = fold_convert (pointer_type, data_addr);
+  /* Any further uses of alloc_node will want this type, too.  */
+  alloc_node = fold_convert (pointer_type, alloc_node);
 
   /* Now initialize the allocated object.  Note that we preevaluate the
      initialization expression, apart from the actual constructor call or
@@ -2152,8 +2110,6 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
       bool stable;
       bool explicit_value_init_p = false;
 
-      init_expr = cp_build_indirect_ref (data_addr, NULL, complain);
-
       if (init == void_zero_node)
        {
          init = NULL_TREE;
@@ -2170,7 +2126,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
                 return error_mark_node;
             }
          init_expr
-           = build_vec_init (init_expr,
+           = build_vec_init (data_addr,
                              cp_build_binary_op (input_location,
                                                  MINUS_EXPR, outer_nelts,
                                                  integer_one_node,
@@ -2187,6 +2143,8 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
        }
       else
        {
+         init_expr = cp_build_indirect_ref (data_addr, NULL, complain);
+
          if (TYPE_NEEDS_CONSTRUCTING (type) && !explicit_value_init_p)
            {
              init_expr = build_special_member_call (init_expr,
@@ -2198,8 +2156,8 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
          else if (explicit_value_init_p)
            {
              /* Something like `new int()'.  */
-             init_expr = build2 (INIT_EXPR, full_type,
-                                 init_expr, build_value_init (full_type));
+             init_expr = build2 (INIT_EXPR, type,
+                                 init_expr, build_value_init (type));
            }
          else
            {
@@ -2240,7 +2198,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
             functions that we use for finding allocation functions.  */
          cleanup = (build_op_delete_call
                     (dcode,
-                     fold_convert (full_pointer_type, alloc_node),
+                     alloc_node,
                      size,
                      globally_qualified_p,
                      placement_allocation_fn_p ? alloc_call : NULL_TREE,
@@ -2323,9 +2281,6 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
   if (init_preeval_expr)
     rval = build2 (COMPOUND_EXPR, TREE_TYPE (rval), init_preeval_expr, rval);
 
-  /* Convert to the final type.  */
-  rval = build_nop (pointer_type, rval);
-
   /* A new-expression is never an lvalue.  */
   gcc_assert (!lvalue_p (rval));
 
@@ -2665,9 +2620,10 @@ get_temp_regvar (tree type, tree init)
 /* `build_vec_init' returns tree structure that performs
    initialization of a vector of aggregate types.
 
-   BASE is a reference to the vector, of ARRAY_TYPE.
+   BASE is a reference to the vector, of ARRAY_TYPE, or a pointer
+     to the first element, of POINTER_TYPE.
    MAXINDEX is the maximum index of the array (one less than the
-     number of elements).  It is only used if
+     number of elements).  It is only used if BASE is a pointer or
      TYPE_DOMAIN (TREE_TYPE (BASE)) == NULL_TREE.
 
    INIT is the (possibly NULL) initializer.
@@ -2692,7 +2648,7 @@ build_vec_init (tree base, tree maxindex, tree init,
   tree size;
   tree itype = NULL_TREE;
   tree iterator;
-  /* The type of the array.  */
+  /* The type of BASE.  */
   tree atype = TREE_TYPE (base);
   /* The type of an element in the array.  */
   tree type = TREE_TYPE (atype);
@@ -2708,7 +2664,7 @@ build_vec_init (tree base, tree maxindex, tree init,
   int num_initialized_elts = 0;
   bool is_global;
 
-  if (TYPE_DOMAIN (atype))
+  if (TREE_CODE (atype) == ARRAY_TYPE && TYPE_DOMAIN (atype))
     maxindex = array_type_nelts (atype);
 
   if (maxindex == NULL_TREE || maxindex == error_mark_node)
@@ -2717,7 +2673,7 @@ build_vec_init (tree base, tree maxindex, tree init,
   if (explicit_value_init_p)
     gcc_assert (!init);
 
-  inner_elt_type = strip_array_types (atype);
+  inner_elt_type = strip_array_types (type);
   if (init
       && (from_array == 2
          ? (!CLASS_TYPE_P (inner_elt_type)
@@ -2734,15 +2690,20 @@ build_vec_init (tree base, tree maxindex, tree init,
         brace-enclosed initializers.  In this case, digest_init and
         store_constructor will handle the semantics for us.  */
 
+      gcc_assert (TREE_CODE (atype) == ARRAY_TYPE);
       stmt_expr = build2 (INIT_EXPR, atype, base, init);
       return stmt_expr;
     }
 
   maxindex = cp_convert (ptrdiff_type_node, maxindex);
-  ptype = build_pointer_type (type);
   size = size_in_bytes (type);
-  if (TREE_CODE (TREE_TYPE (base)) == ARRAY_TYPE)
-    base = cp_convert (ptype, decay_conversion (base));
+  if (TREE_CODE (atype) == ARRAY_TYPE)
+    {
+      ptype = build_pointer_type (type);
+      base = cp_convert (ptype, decay_conversion (base));
+    }
+  else
+    ptype = atype;
 
   /* The code we are generating looks like:
      ({
@@ -2954,10 +2915,13 @@ build_vec_init (tree base, tree maxindex, tree init,
 
   stmt_expr = finish_init_stmts (is_global, stmt_expr, compound_stmt);
 
-  /* Now convert make the result have the correct type.  */
-  atype = build_pointer_type (atype);
-  stmt_expr = build1 (NOP_EXPR, atype, stmt_expr);
-  stmt_expr = cp_build_indirect_ref (stmt_expr, NULL, complain);
+  /* Now make the result have the correct type.  */
+  if (TREE_CODE (atype) == ARRAY_TYPE)
+    {
+      atype = build_pointer_type (atype);
+      stmt_expr = build1 (NOP_EXPR, atype, stmt_expr);
+      stmt_expr = cp_build_indirect_ref (stmt_expr, NULL, complain);
+    }
 
   current_stmt_tree ()->stmts_are_full_exprs_p = destroy_temps;
   return stmt_expr;
index 891bdb7..f424f37 100644 (file)
@@ -1,3 +1,8 @@
+2009-03-07  Jason Merrill  <jason@redhat.com>
+
+       PR c++/39367
+       * g++.dg/opt/new1.C: New.
+
 2009-03-06  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/33492
diff --git a/gcc/testsuite/g++.dg/opt/new1.C b/gcc/testsuite/g++.dg/opt/new1.C
new file mode 100644 (file)
index 0000000..dbcc0f8
--- /dev/null
@@ -0,0 +1,71 @@
+// PR c++/39367
+// { dg-options "-O" }
+
+class QScriptEnginePrivate;
+class QScriptClassInfo;
+namespace QScript {
+    enum Type { InvalidType };
+};
+class QScriptValueImpl {
+public:
+    inline QScriptValueImpl();
+    QScript::Type m_type;
+};
+namespace QScript {
+    namespace Ecma {
+        class Core {
+        public:
+            inline QScriptEnginePrivate *engine() const     { }
+            inline QScriptClassInfo *classInfo() const     { }
+            QScriptValueImpl publicPrototype;
+        };
+        class Boolean: public Core {
+            void newBoolean(QScriptValueImpl *result, bool value = false);
+        };
+    }
+    template <typename T> class Buffer     {
+    public:
+        inline void reserve(int num);
+        inline void resize(int s);
+        T *m_data;
+        int m_capacity;
+        int m_size;
+    };
+}
+template <typename T> void QScript::Buffer<T>::resize(int s) {
+    if (m_capacity < s)
+      reserve (s << 1);
+}
+template <typename T> void QScript::Buffer<T>::reserve(int x) {
+    T *new_data = new T[m_capacity];
+    for (int i=0; i<m_size; ++i)
+      new_data[i] = m_data[i];
+}
+class QScriptObject {
+public:
+    inline void reset();
+    QScript::Buffer<QScriptValueImpl> m_values;
+};
+class QScriptEnginePrivate {
+public:
+  inline QScriptObject *allocObject() { return 0; }
+    inline void newObject(QScriptValueImpl *o, const QScriptValueImpl &proto,
+                          QScriptClassInfo *oc = 0);
+};
+inline void QScriptEnginePrivate::newObject(QScriptValueImpl *o,
+                                            const QScriptValueImpl &proto,
+                                            QScriptClassInfo *oc)
+{
+  QScriptObject *od = allocObject();
+  od->reset();
+}
+inline QScriptValueImpl::QScriptValueImpl() : m_type(QScript::InvalidType) { }
+inline void QScriptObject::reset() { m_values.resize(0); }
+namespace QScript {
+    namespace Ecma {
+        void Boolean::newBoolean(QScriptValueImpl *result, bool value)
+          {
+            engine()->newObject(result, publicPrototype, classInfo());
+          }
+    }
+}