re PR c++/21336 (Internal compiler error when using custom new operators)
authorMark Mitchell <mark@codesourcery.com>
Fri, 3 Jun 2005 16:16:46 +0000 (16:16 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Fri, 3 Jun 2005 16:16:46 +0000 (16:16 +0000)
PR c++/21336
* cp-tree.h (grok_op_properties): Remove friendp parameter.
* decl.c (grokfndecl): Adjust call.
(grok_op_properties): Determine the class of which the function is
a member by looking at its DECL_CONTEXT, not current_class_type.
* pt.c (tsubst_decl): Adjust call to grok_op_properties.

PR c++/21336
* g++.dg/template/new2.C: New test.

From-SVN: r100541

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/new2.C [new file with mode: 0644]

index 8b687062ea79d1e50549dee2caec79782a93415e..28dc483398b8c46730e460fcb1edede484741be5 100644 (file)
@@ -1,3 +1,12 @@
+2005-06-03  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/21336
+       * cp-tree.h (grok_op_properties): Remove friendp parameter.
+       * decl.c (grokfndecl): Adjust call.
+       (grok_op_properties): Determine the class of which the function is
+       a member by looking at its DECL_CONTEXT, not current_class_type.
+       * pt.c (tsubst_decl): Adjust call to grok_op_properties.
+
 2005-06-02  Nathan Sidwell  <nathan@codesourcery.com>
 
        * method.c (synthesize_method): Add addtional arg to warning call.
index f4f5a12c79bb753f03f2e54b639a72be847d88c9..0f3dfa5c89049e4765fe6ffb12c980bb7a2a0eaa 100644 (file)
@@ -3766,7 +3766,7 @@ extern int copy_fn_p                              (tree);
 extern tree get_scope_of_declarator             (const cp_declarator *);
 extern void grok_special_member_properties     (tree);
 extern int grok_ctor_properties                        (tree, tree);
-extern void grok_op_properties                 (tree, int, bool);
+extern void grok_op_properties                 (tree, bool);
 extern tree xref_tag                           (enum tag_types, tree, tag_scope, bool);
 extern tree xref_tag_from_type                 (tree, tree, tag_scope);
 extern void xref_basetypes                     (tree, tree);
index 6f1394ba5131a5bf78c167b4eb08762a081a84ac..6b278ae2878e61710fbe8a631873e3cdb31d8be0 100644 (file)
@@ -5610,7 +5610,7 @@ grokfndecl (tree ctype,
     }
 
   if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)))
-    grok_op_properties (decl, friendp, /*complain=*/true);
+    grok_op_properties (decl, /*complain=*/true);
 
   if (ctype && decl_function_context (decl))
     DECL_NO_STATIC_CHAIN (decl) = 1;
@@ -8608,7 +8608,7 @@ unary_op_p (enum tree_code code)
    errors are issued for invalid declarations.  */
 
 void
-grok_op_properties (tree decl, int friendp, bool complain)
+grok_op_properties (tree decl, bool complain)
 {
   tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
   tree argtype;
@@ -8616,6 +8616,7 @@ grok_op_properties (tree decl, int friendp, bool complain)
   tree name = DECL_NAME (decl);
   enum tree_code operator_code;
   int arity;
+  tree class_type;
 
   /* Count the number of arguments.  */
   for (argtype = argtypes, arity = 0;
@@ -8623,8 +8624,9 @@ grok_op_properties (tree decl, int friendp, bool complain)
        argtype = TREE_CHAIN (argtype))
     ++arity;
 
-  if (current_class_type == NULL_TREE)
-    friendp = 1;
+  class_type = DECL_CONTEXT (decl);
+  if (class_type && !CLASS_TYPE_P (class_type))
+    class_type = NULL_TREE;
 
   if (DECL_CONV_FN_P (decl))
     operator_code = TYPE_EXPR;
@@ -8653,30 +8655,28 @@ grok_op_properties (tree decl, int friendp, bool complain)
   gcc_assert (operator_code != LAST_CPLUS_TREE_CODE);
   SET_OVERLOADED_OPERATOR_CODE (decl, operator_code);
 
-  if (! friendp)
-    {
-      switch (operator_code)
-       {
-       case NEW_EXPR:
-         TYPE_HAS_NEW_OPERATOR (current_class_type) = 1;
-         break;
+  if (class_type)
+    switch (operator_code)
+      {
+      case NEW_EXPR:
+       TYPE_HAS_NEW_OPERATOR (class_type) = 1;
+       break;
 
-       case DELETE_EXPR:
-         TYPE_GETS_DELETE (current_class_type) |= 1;
-         break;
+      case DELETE_EXPR:
+       TYPE_GETS_DELETE (class_type) |= 1;
+       break;
 
-       case VEC_NEW_EXPR:
-         TYPE_HAS_ARRAY_NEW_OPERATOR (current_class_type) = 1;
-         break;
+      case VEC_NEW_EXPR:
+       TYPE_HAS_ARRAY_NEW_OPERATOR (class_type) = 1;
+       break;
 
-       case VEC_DELETE_EXPR:
-         TYPE_GETS_DELETE (current_class_type) |= 2;
-         break;
+      case VEC_DELETE_EXPR:
+       TYPE_GETS_DELETE (class_type) |= 2;
+       break;
 
-       default:
-         break;
-       }
-    }
+      default:
+       break;
+      }
 
     /* [basic.std.dynamic.allocation]/1:
 
@@ -8755,32 +8755,38 @@ grok_op_properties (tree decl, int friendp, bool complain)
       if (operator_code == CALL_EXPR)
        return;
 
-      if (IDENTIFIER_TYPENAME_P (name) && ! DECL_TEMPLATE_INFO (decl))
+      /* Warn about conversion operators that will never be used.  */
+      if (IDENTIFIER_TYPENAME_P (name) 
+         && ! DECL_TEMPLATE_INFO (decl)
+         && warn_conversion
+         /* Warn only declaring the function; there is no need to
+            warn again about out-of-class definitions.  */
+         && class_type == current_class_type)
        {
          tree t = TREE_TYPE (name);
-         if (! friendp)
-           {
-             int ref = (TREE_CODE (t) == REFERENCE_TYPE);
-             const char *what = 0;
+         int ref = (TREE_CODE (t) == REFERENCE_TYPE);
+         const char *what = 0;
 
-             if (ref)
-               t = TYPE_MAIN_VARIANT (TREE_TYPE (t));
+         if (ref)
+           t = TYPE_MAIN_VARIANT (TREE_TYPE (t));
 
-             if (TREE_CODE (t) == VOID_TYPE)
-               what = "void";
-             else if (t == current_class_type)
+         if (TREE_CODE (t) == VOID_TYPE)
+           what = "void";
+         else if (class_type)
+           {
+             if (t == class_type)
                what = "the same type";
              /* Don't force t to be complete here.  */
              else if (IS_AGGR_TYPE (t)
                       && COMPLETE_TYPE_P (t)
-                      && DERIVED_FROM_P (t, current_class_type))
+                      && DERIVED_FROM_P (t, class_type))
                what = "a base class";
-
-             if (what && warn_conversion)
-               warning (0, "conversion to %s%s will never use a type "
-                         "conversion operator",
-                        ref ? "a reference to " : "", what);
            }
+
+         if (what)
+           warning (0, "conversion to %s%s will never use a type "
+                    "conversion operator",
+                    ref ? "a reference to " : "", what);
        }
       if (operator_code == COND_EXPR)
        {
index 8a0a430add26b789f1a58f6aa24cbc49fd6c814d..ad1e5f33bfd4fb86020050fab857617c2611120f 100644 (file)
@@ -6494,8 +6494,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
              clone_function_decl (r, /*update_method_vec_p=*/0);
          }
        else if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
-         grok_op_properties (r, DECL_FRIEND_P (r),
-                             (complain & tf_error) != 0);
+         grok_op_properties (r, (complain & tf_error) != 0);
 
        if (DECL_FRIEND_P (t) && DECL_FRIEND_CONTEXT (t))
          SET_DECL_FRIEND_CONTEXT (r,
index 2b3cbc23b5355f42f9968523a1540c5ce4fafd6e..523873461f4571f9989425dea28fe7424bfe2341 100644 (file)
@@ -1,3 +1,8 @@
+2005-06-03  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/21336
+       * g++.dg/template/new2.C: New test.
+
 2005-06-03  Josh Conner  <jconner@apple.com>
 
        * gcc.dg/ppc-vector-memcpy.c (foo): Use non-zero values for
diff --git a/gcc/testsuite/g++.dg/template/new2.C b/gcc/testsuite/g++.dg/template/new2.C
new file mode 100644 (file)
index 0000000..682ca6e
--- /dev/null
@@ -0,0 +1,14 @@
+// PR c++/21336
+
+typedef __SIZE_TYPE__ size_t;
+template<class _T> void* operator new( size_t Size, _T&);
+struct B {
+  int a;
+  int* m() {
+    return new(a) int;
+  }
+};
+B* n() {
+  return new B();
+}
+