]> gcc.gnu.org Git - gcc.git/commitdiff
re PR c++/26122 (Pure specifiers for templates causing trouble)
authorMark Mitchell <mark@codesourcery.com>
Tue, 11 Apr 2006 22:59:57 +0000 (22:59 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Tue, 11 Apr 2006 22:59:57 +0000 (22:59 +0000)
* g++.dg/parse/dtor7.C: New test.
* g++.dg/parse/new1.C: Add error marker.
* g++.dg/template/new3.C: New test.

PR c++/26122
* g++.dg/template/pure1.C: New test.

PR c++/26295
* g++.dg/parse/ptrmem4.C: New test.

From-SVN: r112869

15 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/init.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/cp/typeck2.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/parse/dtor7.C
gcc/testsuite/g++.dg/parse/new1.C
gcc/testsuite/g++.dg/parse/ptrmem4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/new3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/pure1.C [new file with mode: 0644]

index ea00b4b398bd3544d7470b4300b4d140e78e7640..a292155f839aa22f00a60294086218cb25609515 100644 (file)
@@ -1,3 +1,38 @@
+2006-04-11  Mark Mitchell  <mark@codesourcery.com>
+
+       * cp-tree.h (build_operator_new_call): Adjust prototype.
+       (build_new_method_call): Likewise.
+       (build_op_delete_call): Likewise.
+       * init.c (build_raw_new_expr): New function.
+       (build_new_1): Pass information as parameters, rather than
+       bundling it into a NEW_EXPR.
+       (build_new): Adjust accordingly.
+       (build_vec_delete_1): Adjust for changes to build_op_delete_call.
+       (build_delete): Likewise.
+       * decl.c (finish_destructor_body): Likewise.
+       * call.c (build_operator_new_call): Return the allocation function
+       used.
+       (build_op_delete_call): Take allocation function as parameter.
+       (build_special_member_call): Adjust call to build_new_method_call.
+       (build_new_method_call): Return function called.
+       * pt.c (tsubst_copy_and_build): Adjust call to
+       build_new_method_call.
+       * semantics.c (finish_call_expr): Likewise.
+       * parser.c (cp_parser_postfix_expression): Likewise.
+       * typeck2.c (cxx_incomplete_type_diagnostic): Refer to
+       "incomplete", not "undefined", types. 
+
+       PR c++/26295
+       * decl.c (grokdeclarator): Remove namespace-handling code for
+       pointers-to-members.  
+       * parser.c (cp_parser_ptr_operator): Check for qualified names
+       using namespaces.
+
+       PR c++/26122
+       * parser.c (cp_parser_init_declarator): Adjust logic for deciding
+       whether or not to look for a pure-specifier.
+       (cp_parser_member_declaration): Likewise.
+
 2006-04-08  Kazu Hirata  <kazu@codesourcery.com>
 
        * decl2.c, pt.c, semantics.c: Fix comment typos.
index 0413a9885ddb39bc987ac0d31299dcf0bfbe6ed7..b79d03b2be979b6f2594918f39c27a6a257fe3b7 100644 (file)
@@ -2817,16 +2817,21 @@ build_new_function_call (tree fn, tree args, bool koenig_p)
    required by the allocation, and is updated if that is changed here.
    *COOKIE_SIZE is non-NULL if a cookie should be used.  If this
    function determines that no cookie should be used, after all,
-   *COOKIE_SIZE is set to NULL_TREE.  */
+   *COOKIE_SIZE is set to NULL_TREE.  If FN is non-NULL, it will be
+   set, upon return, to the allocation function called.  */
 
 tree
-build_operator_new_call (tree fnname, tree args, tree *size, tree *cookie_size)
+build_operator_new_call (tree fnname, tree args, 
+                        tree *size, tree *cookie_size,
+                        tree *fn)
 {
   tree fns;
   struct z_candidate *candidates;
   struct z_candidate *cand;
   bool any_viable_p;
 
+  if (fn)
+    *fn = NULL_TREE;
   args = tree_cons (NULL_TREE, *size, args);
   args = resolve_args (args);
   if (args == error_mark_node)
@@ -2904,6 +2909,10 @@ build_operator_new_call (tree fnname, tree args, tree *size, tree *cookie_size)
         *cookie_size = NULL_TREE;
      }
 
+   /* Tell our caller which function we decided to call.  */
+   if (fn)
+     *fn = cand->fn;
+
    /* Build the CALL_EXPR.  */
    return build_over_call (cand, LOOKUP_NORMAL);
 }
@@ -3930,11 +3939,14 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
    SIZE is the size of the memory block to be deleted.
    GLOBAL_P is true if the delete-expression should not consider
    class-specific delete operators.
-   PLACEMENT is the corresponding placement new call, or NULL_TREE.  */
+   PLACEMENT is the corresponding placement new call, or NULL_TREE.
+   If PLACEMENT is non-NULL, then ALLOC_FN is the allocation function
+   called to perform the placement new.  */
 
 tree
 build_op_delete_call (enum tree_code code, tree addr, tree size,
-                     bool global_p, tree placement)
+                     bool global_p, tree placement,
+                     tree alloc_fn)
 {
   tree fn = NULL_TREE;
   tree fns, fnname, argtypes, args, type;
@@ -3970,18 +3982,12 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
 
   if (placement)
     {
-      tree alloc_fn;
-      tree call_expr;
-
-      /* Find the allocation function that is being called.  */
-      call_expr = placement;
-      /* Extract the function.  */
-      alloc_fn = get_callee_fndecl (call_expr);
+      /* Get the parmaeter types for the allocation function that is
+        being called.  */
       gcc_assert (alloc_fn != NULL_TREE);
-      /* Then the second parm type.  */
       argtypes = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (alloc_fn)));
       /* Also the second argument.  */
-      args = TREE_CHAIN (TREE_OPERAND (call_expr, 1));
+      args = TREE_CHAIN (TREE_OPERAND (placement, 1));
     }
   else
     {
@@ -5181,7 +5187,7 @@ build_special_member_call (tree instance, tree name, tree args,
 
   return build_new_method_call (instance, fns, args,
                                TYPE_BINFO (BINFO_TYPE (binfo)),
-                               flags);
+                               flags, /*fn=*/NULL);
 }
 
 /* Return the NAME, as a C string.  The NAME indicates a function that
@@ -5229,11 +5235,13 @@ name_as_c_string (tree name, tree type, bool *free_p)
   return pretty_name;
 }
 
-/* Build a call to "INSTANCE.FN (ARGS)".  */
+/* Build a call to "INSTANCE.FN (ARGS)".  If FN_P is non-NULL, it will
+   be set, upon return, to the function called.  */
 
 tree
 build_new_method_call (tree instance, tree fns, tree args,
-                      tree conversion_path, int flags)
+                      tree conversion_path, int flags,
+                      tree *fn_p)
 {
   struct z_candidate *candidates = 0, *cand;
   tree explicit_targs = NULL_TREE;
@@ -5255,6 +5263,10 @@ build_new_method_call (tree instance, tree fns, tree args,
 
   gcc_assert (instance != NULL_TREE);
 
+  /* We don't know what function we're going to call, yet.  */
+  if (fn_p)
+    *fn_p = NULL_TREE;
+
   if (error_operand_p (instance)
       || error_operand_p (fns)
       || args == error_mark_node)
@@ -5411,8 +5423,10 @@ build_new_method_call (tree instance, tree fns, tree args,
        }
       else
        {
+         fn = cand->fn;
+
          if (!(flags & LOOKUP_NONVIRTUAL)
-             && DECL_PURE_VIRTUAL_P (cand->fn)
+             && DECL_PURE_VIRTUAL_P (fn)
              && instance == current_class_ref
              && (DECL_CONSTRUCTOR_P (current_function_decl)
                  || DECL_DESTRUCTOR_P (current_function_decl)))
@@ -5421,27 +5435,29 @@ build_new_method_call (tree instance, tree fns, tree args,
            warning (0, (DECL_CONSTRUCTOR_P (current_function_decl) ?
                      "abstract virtual %q#D called from constructor"
                      : "abstract virtual %q#D called from destructor"),
-                    cand->fn);
+                    fn);
 
-         if (TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE
+         if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE
              && is_dummy_object (instance_ptr))
            {
              error ("cannot call member function %qD without object",
-                    cand->fn);
+                    fn);
              call = error_mark_node;
            }
          else
            {
-             if (DECL_VINDEX (cand->fn) && ! (flags & LOOKUP_NONVIRTUAL)
+             if (DECL_VINDEX (fn) && ! (flags & LOOKUP_NONVIRTUAL)
                  && resolves_to_fixed_type_p (instance, 0))
                flags |= LOOKUP_NONVIRTUAL;
-
+             /* Now we know what function is being called.  */
+             if (fn_p)
+               *fn_p = fn;
+             /* Build the actuall CALL_EXPR.  */
              call = build_over_call (cand, flags);
-
              /* In an expression of the form `a->f()' where `f' turns
                 out to be a static member function, `a' is
                 none-the-less evaluated.  */
-             if (TREE_CODE (TREE_TYPE (cand->fn)) != METHOD_TYPE
+             if (TREE_CODE (TREE_TYPE (fn)) != METHOD_TYPE
                  && !is_dummy_object (instance_ptr)
                  && TREE_SIDE_EFFECTS (instance))
                call = build2 (COMPOUND_EXPR, TREE_TYPE (call),
index 4b155735427598ecbca14e627c1bd692b22b14a7..b488be62789104ab8d5888231869106e18b1d9d9 100644 (file)
@@ -3710,11 +3710,13 @@ extern bool sufficient_parms_p                  (tree);
 extern tree type_decays_to                     (tree);
 extern tree build_user_type_conversion         (tree, tree, int);
 extern tree build_new_function_call            (tree, tree, bool);
-extern tree build_operator_new_call            (tree, tree, tree *, tree *);
-extern tree build_new_method_call              (tree, tree, tree, tree, int);
+extern tree build_operator_new_call            (tree, tree, tree *, tree *,
+                                                tree *);
+extern tree build_new_method_call              (tree, tree, tree, tree, int,
+                                                tree *);
 extern tree build_special_member_call          (tree, tree, tree, tree, int);
 extern tree build_new_op                       (enum tree_code, int, tree, tree, tree, bool *);
-extern tree build_op_delete_call               (enum tree_code, tree, tree, bool, tree);
+extern tree build_op_delete_call               (enum tree_code, tree, tree, bool, tree, tree);
 extern bool can_convert                                (tree, tree);
 extern bool can_convert_arg                    (tree, tree, tree, int);
 extern bool can_convert_arg_bad                        (tree, tree, tree);
index 45feb9f0c589ced38afd134141a613bd6892e13a..3d8c2f84ba34e2f4ff8d7c886b619f526a706c45 100644 (file)
@@ -7619,15 +7619,9 @@ grokdeclarator (const cp_declarator *declarator,
            type = build_ptrmemfunc_type (build_pointer_type (type));
          else if (declarator->kind == cdk_ptrmem)
            {
-             /* We might have parsed a namespace as the class type.  */
-             if (TREE_CODE (declarator->u.pointer.class_type)
-                 == NAMESPACE_DECL)
-               {
-                 error ("%qD is a namespace",
-                        declarator->u.pointer.class_type);
-                 type = build_pointer_type (type);
-               }
-             else if (declarator->u.pointer.class_type == error_mark_node)
+             gcc_assert (TREE_CODE (declarator->u.pointer.class_type)
+                         != NAMESPACE_DECL);
+             if (declarator->u.pointer.class_type == error_mark_node)
                /* We will already have complained.  */
                type = error_mark_node;
              else
@@ -10801,9 +10795,11 @@ finish_destructor_body (void)
       an implicit definition), non-placement operator delete shall
       be looked up in the scope of the destructor's class and if
       found shall be accessible and unambiguous.  */
-      exprstmt = build_op_delete_call
-       (DELETE_EXPR, current_class_ptr, virtual_size,
-        /*global_p=*/false, NULL_TREE);
+      exprstmt = build_op_delete_call(DELETE_EXPR, current_class_ptr, 
+                                     virtual_size,
+                                     /*global_p=*/false, 
+                                     /*placement=*/NULL_TREE, 
+                                     /*alloc_fn=*/NULL_TREE);
 
       if_stmt = begin_if_stmt ();
       finish_if_stmt_cond (build2 (BIT_AND_EXPR, integer_type_node,
index 194b29baea8afc3372f918f9d7cc6281c09ae3a7..0439e92209a9a7dde00d30b6dffdf3a5ccf5a5e6 100644 (file)
@@ -52,7 +52,6 @@ static void expand_cleanup_for_base (tree, tree);
 static tree get_temp_regvar (tree, tree);
 static tree dfs_initialize_vtbl_ptrs (tree, void *);
 static tree build_default_init (tree, tree);
-static tree build_new_1        (tree);
 static tree build_dtor_call (tree, special_function_kind, int);
 static tree build_field_list (tree, tree, int *);
 static tree build_vtbl_address (tree);
@@ -1560,127 +1559,38 @@ build_builtin_delete_call (tree addr)
   return build_call (global_delete_fndecl, build_tree_list (NULL_TREE, addr));
 }
 \f
-/* Generate a representation for a C++ "new" expression.  PLACEMENT is
-   a TREE_LIST of placement-new arguments (or NULL_TREE if none).  If
-   NELTS is NULL, TYPE is the type of the storage to be allocated.  If
-   NELTS is not NULL, then this is an array-new allocation; TYPE is
-   the type of the elements in the array and NELTS is the number of
-   elements in the array.  INIT, if non-NULL, is the initializer for
-   the new object.  If USE_GLOBAL_NEW is true, then the user
-   explicitly wrote "::new" rather than just "new".  */
-
-tree
-build_new (tree placement, tree type, tree nelts, tree init,
-          int use_global_new)
-{
-  tree rval;
-
-  if (type == error_mark_node)
-    return error_mark_node;
-
-  if (processing_template_decl)
-    {
-      rval = build_min (NEW_EXPR, build_pointer_type (type),
-                       placement, type, nelts, init);
-      NEW_EXPR_USE_GLOBAL (rval) = use_global_new;
-      TREE_SIDE_EFFECTS (rval) = 1;
-      return rval;
-    }
-
-  if (nelts)
-    {
-      if (!build_expr_type_conversion (WANT_INT | WANT_ENUM, nelts, false))
-       pedwarn ("size in array new must have integral type");
-      nelts = save_expr (cp_convert (sizetype, nelts));
-      if (nelts == integer_zero_node)
-       warning (0, "zero size array reserves no space");
-    }
-
-  /* ``A reference cannot be created by the new operator.  A reference
-     is not an object (8.2.2, 8.4.3), so a pointer to it could not be
-     returned by new.'' ARM 5.3.3 */
-  if (TREE_CODE (type) == REFERENCE_TYPE)
-    {
-      error ("new cannot be applied to a reference type");
-      type = TREE_TYPE (type);
-    }
-
-  if (TREE_CODE (type) == FUNCTION_TYPE)
-    {
-      error ("new cannot be applied to a function type");
-      return error_mark_node;
-    }
-
-  rval = build4 (NEW_EXPR, build_pointer_type (type), placement, type,
-                nelts, init);
-  NEW_EXPR_USE_GLOBAL (rval) = use_global_new;
-  TREE_SIDE_EFFECTS (rval) = 1;
-  rval = build_new_1 (rval);
-  if (rval == error_mark_node)
-    return error_mark_node;
-
-  /* Wrap it in a NOP_EXPR so warn_if_unused_value doesn't complain.  */
-  rval = build1 (NOP_EXPR, TREE_TYPE (rval), rval);
-  TREE_NO_WARNING (rval) = 1;
-
-  return rval;
-}
+/* Build and return a NEW_EXPR.  If NELTS is non-NULL, TYPE[NELTS] is
+   the type of the object being allocated; otherwise, it's just TYPE.
+   INIT is the initializer, if any.  USE_GLOBAL_NEW is true if the
+   user explicitly wrote "::operator new".  PLACEMENT, if non-NULL, is
+   the TREE_LIST of arguments to be provided as arguments to a
+   placement new operator.  This routine performs no semantic checks;
+   it just creates and returns a NEW_EXPR.  */
 
-/* Given a Java class, return a decl for the corresponding java.lang.Class.  */
-
-tree
-build_java_class_ref (tree type)
+static tree
+build_raw_new_expr (tree placement, tree type, tree nelts, tree init,
+                   int use_global_new)
 {
-  tree name = NULL_TREE, class_decl;
-  static tree CL_suffix = NULL_TREE;
-  if (CL_suffix == NULL_TREE)
-    CL_suffix = get_identifier("class$");
-  if (jclass_node == NULL_TREE)
-    {
-      jclass_node = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jclass"));
-      if (jclass_node == NULL_TREE)
-       fatal_error ("call to Java constructor, while %<jclass%> undefined");
-
-      jclass_node = TREE_TYPE (jclass_node);
-    }
-
-  /* Mangle the class$ field.  */
-  {
-    tree field;
-    for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
-      if (DECL_NAME (field) == CL_suffix)
-       {
-         mangle_decl (field);
-         name = DECL_ASSEMBLER_NAME (field);
-         break;
-       }
-    if (!field)
-      internal_error ("can't find class$");
-    }
-
-  class_decl = IDENTIFIER_GLOBAL_VALUE (name);
-  if (class_decl == NULL_TREE)
-    {
-      class_decl = build_decl (VAR_DECL, name, TREE_TYPE (jclass_node));
-      TREE_STATIC (class_decl) = 1;
-      DECL_EXTERNAL (class_decl) = 1;
-      TREE_PUBLIC (class_decl) = 1;
-      DECL_ARTIFICIAL (class_decl) = 1;
-      DECL_IGNORED_P (class_decl) = 1;
-      pushdecl_top_level (class_decl);
-      make_decl_rtl (class_decl);
-    }
-  return class_decl;
+  tree new_expr;
+  
+  new_expr = build4 (NEW_EXPR, build_pointer_type (type), placement, type, 
+                    nelts, init); 
+  NEW_EXPR_USE_GLOBAL (new_expr) = use_global_new;
+  TREE_SIDE_EFFECTS (new_expr) = 1;
+
+  return new_expr;
 }
 
-
-/* Called from cplus_expand_expr when expanding a NEW_EXPR.  The return
-   value is immediately handed to expand_expr.  */
+/* Generate code for a new-expression, including calling the "operator
+   new" function, initializing the object, and, if an exception occurs
+   during construction, cleaning up.  The arguments are as for
+   build_raw_new_expr.  */
 
 static tree
-build_new_1 (tree exp)
+build_new_1 (tree placement, tree type, tree nelts, tree init,
+            bool globally_qualified_p)
+            
 {
-  tree placement, init;
   tree size, rval;
   /* True iff this is a call to "operator new[]" instead of just
      "operator new".  */
@@ -1700,14 +1610,9 @@ build_new_1 (tree exp)
   /* The type of the new-expression.  (This type is always a pointer
      type.)  */
   tree pointer_type;
-  /* The type pointed to by POINTER_TYPE.  This type may be different
-     from ELT_TYPE for a multi-dimensional array; ELT_TYPE is never an
-     ARRAY_TYPE, but TYPE may be an ARRAY_TYPE.  */
-  tree type;
   /* A pointer type pointing to the FULL_TYPE.  */
   tree full_pointer_type;
   tree outer_nelts = NULL_TREE;
-  tree nelts = NULL_TREE;
   tree alloc_call, alloc_expr;
   /* The address returned by the call to "operator new".  This node is
      a VAR_DECL and is therefore reusable.  */
@@ -1715,8 +1620,6 @@ build_new_1 (tree exp)
   tree alloc_fn;
   tree cookie_expr, init_expr;
   int nothrow, check_new;
-  /* Nonzero if the user wrote `::new' rather than just `new'.  */
-  int globally_qualified_p;
   int use_java_new = 0;
   /* If non-NULL, the number of extra bytes to allocate at the
      beginning of the storage allocated for an array-new expression in
@@ -1736,12 +1639,6 @@ build_new_1 (tree exp)
   tree data_addr;
   tree init_preeval_expr = NULL_TREE;
 
-  placement = TREE_OPERAND (exp, 0);
-  type = TREE_OPERAND (exp, 1);
-  nelts = TREE_OPERAND (exp, 2);
-  init = TREE_OPERAND (exp, 3);
-  globally_qualified_p = NEW_EXPR_USE_GLOBAL (exp);
-
   if (nelts)
     {
       tree index;
@@ -1770,7 +1667,7 @@ build_new_1 (tree exp)
        }
     }
 
-  if (!complete_type_or_else (type, exp))
+  if (!complete_type_or_else (type, NULL_TREE))
     return error_mark_node;
 
   /* If our base type is an array, then make sure we know how many elements
@@ -1815,30 +1712,31 @@ build_new_1 (tree exp)
        }
     }
 
+  alloc_fn = NULL_TREE;
+
   /* Allocate the object.  */
   if (! placement && TYPE_FOR_JAVA (elt_type))
     {
-      tree class_addr, alloc_decl;
+      tree class_addr;
       tree class_decl = build_java_class_ref (elt_type);
       static const char alloc_name[] = "_Jv_AllocObject";
 
       use_java_new = 1;
-      alloc_decl = NULL;
       if (!get_global_value_if_present (get_identifier (alloc_name),
-                                       &alloc_decl))
+                                       &alloc_fn))
        {
          error ("call to Java constructor with %qs undefined", alloc_name);
          return error_mark_node;
        }
-      else if (really_overloaded_fn (alloc_decl))
+      else if (really_overloaded_fn (alloc_fn))
        {
-         error ("%qD should never be overloaded", alloc_decl);
+         error ("%qD should never be overloaded", alloc_fn);
          return error_mark_node;
        }
-      alloc_decl = OVL_CURRENT (alloc_decl);
+      alloc_fn = OVL_CURRENT (alloc_fn);
       class_addr = build1 (ADDR_EXPR, jclass_node, class_decl);
       alloc_call = (build_function_call
-                   (alloc_decl,
+                   (alloc_fn,
                     build_tree_list (NULL_TREE, class_addr)));
     }
   else
@@ -1879,7 +1777,8 @@ build_new_1 (tree exp)
          alloc_call = build_new_method_call (build_dummy_object (elt_type),
                                              fns, args,
                                              /*conversion_path=*/NULL_TREE,
-                                             LOOKUP_NORMAL);
+                                             LOOKUP_NORMAL,
+                                             &alloc_fn);
        }
       else
        {
@@ -1891,13 +1790,16 @@ build_new_1 (tree exp)
            cookie_size = NULL_TREE;
 
          alloc_call = build_operator_new_call (fnname, placement,
-                                               &size, &cookie_size);
+                                               &size, &cookie_size,
+                                               &alloc_fn);
        }
     }
 
   if (alloc_call == error_mark_node)
     return error_mark_node;
 
+  gcc_assert (alloc_fn != NULL_TREE);
+
   /* In the simple case, we can stop now.  */
   pointer_type = build_pointer_type (type);
   if (!cookie_size && !is_initialized)
@@ -1913,8 +1815,6 @@ build_new_1 (tree exp)
   /* Strip any COMPOUND_EXPRs from ALLOC_CALL.  */
   while (TREE_CODE (alloc_call) == COMPOUND_EXPR)
     alloc_call = TREE_OPERAND (alloc_call, 1);
-  alloc_fn = get_callee_fndecl (alloc_call);
-  gcc_assert (alloc_fn != NULL_TREE);
 
   /* Now, check to see if this function is actually a placement
      allocation function.  This can happen even when PLACEMENT is NULL
@@ -2079,7 +1979,9 @@ build_new_1 (tree exp)
          cleanup = build_op_delete_call (dcode, alloc_node, size,
                                          globally_qualified_p,
                                          (placement_allocation_fn_p
-                                          ? alloc_call : NULL_TREE));
+                                          ? alloc_call : NULL_TREE),
+                                         (placement_allocation_fn_p
+                                          ? alloc_fn : NULL_TREE));
 
          if (!cleanup)
            /* We're done.  */;
@@ -2163,6 +2065,134 @@ build_new_1 (tree exp)
 
   return rval;
 }
+
+/* Generate a representation for a C++ "new" expression.  PLACEMENT is
+   a TREE_LIST of placement-new arguments (or NULL_TREE if none).  If
+   NELTS is NULL, TYPE is the type of the storage to be allocated.  If
+   NELTS is not NULL, then this is an array-new allocation; TYPE is
+   the type of the elements in the array and NELTS is the number of
+   elements in the array.  INIT, if non-NULL, is the initializer for
+   the new object, or void_zero_node to indicate an initializer of
+   "()".  If USE_GLOBAL_NEW is true, then the user explicitly wrote
+   "::new" rather than just "new".  */
+
+tree
+build_new (tree placement, tree type, tree nelts, tree init,
+          int use_global_new)
+{
+  tree rval;
+  tree orig_placement;
+  tree orig_nelts;
+  tree orig_init;
+
+  if (type == error_mark_node)
+    return error_mark_node;
+
+  orig_placement = placement;
+  orig_nelts = nelts;
+  orig_init = init;
+
+  if (processing_template_decl)
+    {
+      if (dependent_type_p (type)
+         || any_type_dependent_arguments_p (placement)
+         || (nelts && type_dependent_expression_p (nelts))
+         || (init != void_zero_node
+             && any_type_dependent_arguments_p (init)))
+       return build_raw_new_expr (placement, type, nelts, init,
+                                  use_global_new);
+      placement = build_non_dependent_args (placement);
+      if (nelts)
+       nelts = build_non_dependent_expr (nelts);
+      if (init != void_zero_node)
+       init = build_non_dependent_args (init);
+    }
+
+  if (nelts)
+    {
+      if (!build_expr_type_conversion (WANT_INT | WANT_ENUM, nelts, false))
+       pedwarn ("size in array new must have integral type");
+      nelts = save_expr (cp_convert (sizetype, nelts));
+      if (nelts == integer_zero_node)
+       warning (0, "zero size array reserves no space");
+    }
+
+  /* ``A reference cannot be created by the new operator.  A reference
+     is not an object (8.2.2, 8.4.3), so a pointer to it could not be
+     returned by new.'' ARM 5.3.3 */
+  if (TREE_CODE (type) == REFERENCE_TYPE)
+    {
+      error ("new cannot be applied to a reference type");
+      type = TREE_TYPE (type);
+    }
+
+  if (TREE_CODE (type) == FUNCTION_TYPE)
+    {
+      error ("new cannot be applied to a function type");
+      return error_mark_node;
+    }
+
+  rval = build_new_1 (placement, type, nelts, init, use_global_new);
+  if (rval == error_mark_node)
+    return error_mark_node;
+
+  if (processing_template_decl)
+    return build_raw_new_expr (orig_placement, type, orig_nelts, orig_init,
+                              use_global_new);
+
+  /* Wrap it in a NOP_EXPR so warn_if_unused_value doesn't complain.  */
+  rval = build1 (NOP_EXPR, TREE_TYPE (rval), rval);
+  TREE_NO_WARNING (rval) = 1;
+
+  return rval;
+}
+
+/* Given a Java class, return a decl for the corresponding java.lang.Class.  */
+
+tree
+build_java_class_ref (tree type)
+{
+  tree name = NULL_TREE, class_decl;
+  static tree CL_suffix = NULL_TREE;
+  if (CL_suffix == NULL_TREE)
+    CL_suffix = get_identifier("class$");
+  if (jclass_node == NULL_TREE)
+    {
+      jclass_node = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jclass"));
+      if (jclass_node == NULL_TREE)
+       fatal_error ("call to Java constructor, while %<jclass%> undefined");
+
+      jclass_node = TREE_TYPE (jclass_node);
+    }
+
+  /* Mangle the class$ field.  */
+  {
+    tree field;
+    for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+      if (DECL_NAME (field) == CL_suffix)
+       {
+         mangle_decl (field);
+         name = DECL_ASSEMBLER_NAME (field);
+         break;
+       }
+    if (!field)
+      internal_error ("can't find class$");
+    }
+
+  class_decl = IDENTIFIER_GLOBAL_VALUE (name);
+  if (class_decl == NULL_TREE)
+    {
+      class_decl = build_decl (VAR_DECL, name, TREE_TYPE (jclass_node));
+      TREE_STATIC (class_decl) = 1;
+      DECL_EXTERNAL (class_decl) = 1;
+      TREE_PUBLIC (class_decl) = 1;
+      DECL_ARTIFICIAL (class_decl) = 1;
+      DECL_IGNORED_P (class_decl) = 1;
+      pushdecl_top_level (class_decl);
+      make_decl_rtl (class_decl);
+    }
+  return class_decl;
+}
 \f
 static tree
 build_vec_delete_1 (tree base, tree maxindex, tree type,
@@ -2257,7 +2287,8 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
        deallocate_expr = build_op_delete_call (VEC_DELETE_EXPR,
                                                base_tbd, virtual_size,
                                                use_global_delete & 1,
-                                               NULL_TREE);
+                                               /*placement=*/NULL_TREE, 
+                                               /*alloc_fn=*/NULL_TREE);
     }
 
   body = loop;
@@ -2646,7 +2677,8 @@ build_dtor_call (tree exp, special_function_kind dtor_kind, int flags)
   return build_new_method_call (exp, fn,
                                /*args=*/NULL_TREE,
                                /*conversion_path=*/NULL_TREE,
-                               flags);
+                               flags,
+                               /*fn_p=*/NULL);
 }
 
 /* Generate a call to a destructor. TYPE is the type to cast ADDR to.
@@ -2742,9 +2774,11 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
       if (auto_delete != sfk_deleting_destructor)
        return void_zero_node;
 
-      return build_op_delete_call
-       (DELETE_EXPR, addr, cxx_sizeof_nowarn (type), use_global_delete,
-        NULL_TREE);
+      return build_op_delete_call (DELETE_EXPR, addr, 
+                                  cxx_sizeof_nowarn (type), 
+                                  use_global_delete,
+                                  /*placement=*/NULL_TREE,
+                                  /*alloc_fn=*/NULL_TREE);
     }
   else
     {
@@ -2780,7 +2814,8 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
                                            addr,
                                            cxx_sizeof_nowarn (type),
                                            /*global_p=*/false,
-                                           NULL_TREE);
+                                           /*placement=*/NULL_TREE,
+                                           /*alloc_fn=*/NULL_TREE);
          /* Call the complete object destructor.  */
          auto_delete = sfk_complete_destructor;
        }
@@ -2790,7 +2825,9 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
          /* Make sure we have access to the member op delete, even though
             we'll actually be calling it from the destructor.  */
          build_op_delete_call (DELETE_EXPR, addr, cxx_sizeof_nowarn (type),
-                               /*global_p=*/false, NULL_TREE);
+                               /*global_p=*/false, 
+                               /*placement=*/NULL_TREE,
+                               /*alloc_fn=*/NULL_TREE);
        }
 
       expr = build_dtor_call (build_indirect_ref (addr, NULL),
index c5e6b1781e665854b2660cd16bd4fa7e595df046..4c0678439bba817359b69c42975ca1a49cb11d57 100644 (file)
@@ -4262,7 +4262,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
                    = (build_new_method_call
                       (instance, fn, args, NULL_TREE,
                        (idk == CP_ID_KIND_QUALIFIED
-                        ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL)));
+                        ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL),
+                       /*fn_p=*/NULL));
                else
                  postfix_expression
                    = finish_call_expr (postfix_expression, args,
@@ -10887,6 +10888,10 @@ cp_parser_init_declarator (cp_parser* parser,
   tree decl = NULL_TREE;
   tree scope;
   bool is_initialized;
+  /* Only valid if IS_INITIALIZED is true.  In that case, CPP_EQ if
+     initialized with "= ..", CPP_OPEN_PAREN if initialized with
+     "(...)".  */
+  enum cpp_ttype initialization_kind;
   bool is_parenthesized_init;
   bool is_non_constant_init;
   int ctor_dtor_or_conv_p;
@@ -11001,16 +11006,24 @@ cp_parser_init_declarator (cp_parser* parser,
     }
 
   /* An `=' or an `(' indicates an initializer.  */
-  is_initialized = (token->type == CPP_EQ
-                    || token->type == CPP_OPEN_PAREN);
-  /* If the init-declarator isn't initialized and isn't followed by a
-     `,' or `;', it's not a valid init-declarator.  */
-  if (!is_initialized
-      && token->type != CPP_COMMA
-      && token->type != CPP_SEMICOLON)
+  if (token->type == CPP_EQ
+      || token->type == CPP_OPEN_PAREN)
     {
-      cp_parser_error (parser, "expected initializer");
-      return error_mark_node;
+      is_initialized = true;
+      initialization_kind = token->type;
+    }
+  else
+    {
+      /* If the init-declarator isn't initialized and isn't followed by a
+        `,' or `;', it's not a valid init-declarator.  */
+      if (token->type != CPP_COMMA
+         && token->type != CPP_SEMICOLON)
+       {
+         cp_parser_error (parser, "expected initializer");
+         return error_mark_node;
+       }
+      is_initialized = false;
+      initialization_kind = CPP_EOF;
     }
 
   /* Because start_decl has side-effects, we should only call it if we
@@ -11081,9 +11094,16 @@ cp_parser_init_declarator (cp_parser* parser,
 
   /* Parse the initializer.  */
   if (is_initialized)
-    initializer = cp_parser_initializer (parser,
-                                        &is_parenthesized_init,
-                                        &is_non_constant_init);
+    {
+      if (declarator->kind == cdk_function
+         && declarator->declarator->kind == cdk_id
+         && initialization_kind == CPP_EQ)
+       initializer = cp_parser_pure_specifier (parser);
+      else
+       initializer = cp_parser_initializer (parser,
+                                            &is_parenthesized_init,
+                                            &is_non_constant_init);
+    }
   else
     {
       initializer = NULL_TREE;
@@ -11730,17 +11750,23 @@ cp_parser_ptr_operator (cp_parser* parser,
       if (!cp_parser_error_occurred (parser)
          && cp_parser_require (parser, CPP_MULT, "`*'"))
        {
-         /* The type of which the member is a member is given by the
-            current SCOPE.  */
-         *type = parser->scope;
-         /* The next name will not be qualified.  */
-         parser->scope = NULL_TREE;
-         parser->qualifying_scope = NULL_TREE;
-         parser->object_scope = NULL_TREE;
          /* Indicate that the `*' operator was used.  */
          code = INDIRECT_REF;
-         /* Look for the optional cv-qualifier-seq.  */
-         *cv_quals = cp_parser_cv_qualifier_seq_opt (parser);
+
+         if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
+           error ("%qD is a namespace", parser->scope);
+         else
+           {
+             /* The type of which the member is a member is given by the
+                current SCOPE.  */
+             *type = parser->scope;
+             /* The next name will not be qualified.  */
+             parser->scope = NULL_TREE;
+             parser->qualifying_scope = NULL_TREE;
+             parser->object_scope = NULL_TREE;
+             /* Look for the optional cv-qualifier-seq.  */
+             *cv_quals = cp_parser_cv_qualifier_seq_opt (parser);
+           }
        }
       /* If that didn't work we don't have a ptr-operator.  */
       if (!cp_parser_parse_definitely (parser))
@@ -13710,7 +13736,8 @@ cp_parser_member_declaration (cp_parser* parser)
                     for a pure-specifier; otherwise, we look for a
                     constant-initializer.  When we call `grokfield', it will
                     perform more stringent semantics checks.  */
-                 if (declarator->kind == cdk_function)
+                 if (declarator->kind == cdk_function
+                     && declarator->declarator->kind == cdk_id)
                    initializer = cp_parser_pure_specifier (parser);
                  else
                    /* Parse the initializer.  */
index adabe7698dce9249129a0adb333dc96581e0f760..b0650bfc33320037d6e82c72ddd8d3dc05ca2c65 100644 (file)
@@ -8896,7 +8896,8 @@ tsubst_copy_and_build (tree t,
                      (TREE_OPERAND (function, 0),
                       TREE_OPERAND (function, 1),
                       call_args, NULL_TREE,
-                      qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL));
+                      qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL,
+                      /*fn_p=*/NULL));
          }
        return finish_call_expr (function, call_args,
                                 /*disallow_virtual=*/qualified_p,
index 114f3d221459e4397b488b4dbd58c4548bfb80d9..23ab2d8a132da86a7aa1aa1f91dee2aef2bed90f 100644 (file)
@@ -1844,7 +1844,8 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p)
 
       result = build_new_method_call (object, fn, args, NULL_TREE,
                                      (disallow_virtual
-                                      ? LOOKUP_NONVIRTUAL : 0));
+                                      ? LOOKUP_NONVIRTUAL : 0),
+                                     /*fn_p=*/NULL);
     }
   else if (is_overloaded_fn (fn))
     {
index 49c58f8e51ee3ff189768269b7582d01ffc2d4e4..8227a54cd6656f483538ca268dabe60ab5917812 100644 (file)
@@ -377,7 +377,7 @@ cxx_incomplete_type_diagnostic (tree value, tree type, int diag_type)
     case UNION_TYPE:
     case ENUMERAL_TYPE:
       if (!decl)
-       p_msg ("invalid use of undefined type %q#T", type);
+       p_msg ("invalid use of incomplete type %q#T", type);
       if (!TYPE_TEMPLATE_INFO (type))
        p_msg ("forward declaration of %q+#T", type);
       else
index f71c86bc6c2ac516cb4cf6bc61f2e0d91498fd82..565b64e8bbdee896e9372c3c56c8d204be50eece 100644 (file)
@@ -1,3 +1,15 @@
+2006-04-11  Mark Mitchell  <mark@codesourcery.com>
+
+       * g++.dg/parse/dtor7.C: New test.
+       * g++.dg/parse/new1.C: Add error marker.
+       * g++.dg/template/new3.C: New test.
+
+       PR c++/26122
+       * g++.dg/template/pure1.C: New test.
+
+       PR c++/26295
+       * g++.dg/parse/ptrmem4.C: New test.
+
 2006-04-10  Jeff Law  <law@redhat.com>
 
        PR/27087
index 3525624e18d3ba28161bc7e050a5de0451741fdb..a8095126667f8836ca65ac2fc24aab1cfc1244fe 100644 (file)
@@ -1,4 +1,4 @@
 // PR c++/25856
 
 struct A; // { dg-error "forward" } 
-A::~A() {} // { dg-error "undefined" }
+A::~A() {} // { dg-error "incomplete" }
index 31dad773935233e98201a1735bd71e150b44ca57..d61c44633cef2c3747663a1415b1c23ff013bf83 100644 (file)
@@ -1,7 +1,7 @@
-struct T;
+struct T; // { dg-error "forward" }
 T* manage(T* t);
 template <class Obj> struct ObjectSlot0_ {
   void create() {
-    void* tmp = manage(new T());
+    void* tmp = manage(new T()); // { dg-error "incomplete" }
   }
 };
diff --git a/gcc/testsuite/g++.dg/parse/ptrmem4.C b/gcc/testsuite/g++.dg/parse/ptrmem4.C
new file mode 100644 (file)
index 0000000..fea08f2
--- /dev/null
@@ -0,0 +1,4 @@
+// PR c++/26295
+
+namespace A {}
+int (A::*B)(); // { dg-error "namespace" }
diff --git a/gcc/testsuite/g++.dg/template/new3.C b/gcc/testsuite/g++.dg/template/new3.C
new file mode 100644 (file)
index 0000000..c6c1089
--- /dev/null
@@ -0,0 +1,17 @@
+extern void *operator new(__SIZE_TYPE__); // { dg-error "candidate" }
+
+template <class T >
+struct C
+{
+  void f() {
+    int* node;
+    new (&node) int(0); // { dg-error "new" }
+  }
+};
+
+void* operator new(__SIZE_TYPE__, void* __p);
+
+void g() {
+  C<int> c;
+  c.f();
+} 
diff --git a/gcc/testsuite/g++.dg/template/pure1.C b/gcc/testsuite/g++.dg/template/pure1.C
new file mode 100644 (file)
index 0000000..ca9b94e
--- /dev/null
@@ -0,0 +1,6 @@
+// PR c++/26122
+
+struct A
+{
+  template<int> void foo() = 1; // { dg-error "pure" }
+};
This page took 0.149142 seconds and 5 git commands to generate.