PR c++/25635
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 3 Jan 2006 08:41:21 +0000 (08:41 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 3 Jan 2006 08:41:21 +0000 (08:41 +0000)
* class.c (add_method): Set TYPE_HAS_CONVERSION for classes with a
conversion operator.
* decl.c (grokdeclarator): Do not set TYPE_HAS_CONVERSION here.
PR c++/25638
* class.c (add_method): Never associate more than one destructor
with a single class.
PR c++/25637
* cp-tree.h (do_friend): Adjust prototype.
* decl.c (grokfndecl): Make funcdef_flag a bool, not an int.
(grokdeclarator): Likewise.  Refine check for invalid
declarations/definitions of member functions outside of their own
class.
* friend.c (do_friend): Make funcdef_flag a bool, not an int.
PR c++/25633
* parser.c (cp_parser_mem_initializer_list): Check result of
cp_parser_mem_initializer against error_mark_node, not NULL_TREE.
(cp_parser_mem_initializer): Return error_mark_node for failure.
PR c++/25634
* parser.c (cp_parser_template_parameter_list): Call
begin_template_parm_list and end_template_parm_list here.
(cp_parser_type_parameter): Not here.
(cp_parser_template_declaration_after_export): Or here.
(cp_parser_elaborated_type_specifier): Call
cp_parser_check_template_parameters.
* tree.c (build_target_expr_with_type): Use force_target_expr.
PR c++/25635
* g++.dg/parse/operator6.C: New test.
PR c++/25637
* g++.dg/parse/error29.C: New test.
PR c++/25638
* g++.dg/parse/dtor6.C: New test.
PR c++/25633
* g++.dg/parse/ctor3.C: New test.
PR c++/25634
* g++.dg/template/class3.C: New test.

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

13 files changed:
gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/friend.c
gcc/cp/parser.c
gcc/cp/tree.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/parse/ctor3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/parse/dtor6.C [new file with mode: 0644]
gcc/testsuite/g++.dg/parse/error29.C [new file with mode: 0644]
gcc/testsuite/g++.dg/parse/operator6.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/class3.C [new file with mode: 0644]

index a964986..4c03812 100644 (file)
@@ -1,5 +1,37 @@
 2006-01-02  Mark Mitchell  <mark@codesourcery.com>
 
+       PR c++/25635
+       * class.c (add_method): Set TYPE_HAS_CONVERSION for classes with a
+       conversion operator.
+       * decl.c (grokdeclarator): Do not set TYPE_HAS_CONVERSION here.
+
+       PR c++/25638
+       * class.c (add_method): Never associate more than one destructor
+       with a single class.
+
+       PR c++/25637
+       * cp-tree.h (do_friend): Adjust prototype.
+       * decl.c (grokfndecl): Make funcdef_flag a bool, not an int.
+       (grokdeclarator): Likewise.  Refine check for invalid
+       declarations/definitions of member functions outside of their own
+       class.
+       * friend.c (do_friend): Make funcdef_flag a bool, not an int.
+
+       PR c++/25633
+       * parser.c (cp_parser_mem_initializer_list): Check result of
+       cp_parser_mem_initializer against error_mark_node, not NULL_TREE.
+       (cp_parser_mem_initializer): Return error_mark_node for failure.
+
+       PR c++/25634
+       * parser.c (cp_parser_template_parameter_list): Call
+       begin_template_parm_list and end_template_parm_list here.
+       (cp_parser_type_parameter): Not here.
+       (cp_parser_template_declaration_after_export): Or here.
+       (cp_parser_elaborated_type_specifier): Call
+       cp_parser_check_template_parameters.
+
+       * tree.c (build_target_expr_with_type): Use force_target_expr.
+
        * decl2.c (mark_used): Fix typo in comment.
 
 2006-01-02  Volker Reichelt  <reichelt@igpm.rwth-aachen.de>
index 2ccc724..4509ac2 100644 (file)
@@ -1059,10 +1059,16 @@ add_method (tree type, tree method, tree using_decl)
        }
     }
 
+  /* A class should never have more than one destructor.  */ 
+  if (current_fns && DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (method))
+    return false;
+
   /* Add the new binding.  */
   overload = build_overload (method, current_fns);
 
-  if (!conv_p && slot >= CLASSTYPE_FIRST_CONVERSION_SLOT && !complete_p)
+  if (conv_p)
+    TYPE_HAS_CONVERSION (type) = 1;
+  else if (slot >= CLASSTYPE_FIRST_CONVERSION_SLOT && !complete_p)
     push_class_level_binding (DECL_NAME (method), overload);
 
   if (insert_p)
index 3ac322d..3fbaff8 100644 (file)
@@ -3935,7 +3935,7 @@ extern tree cplus_expand_constant         (tree);
 extern int is_friend                           (tree, tree);
 extern void make_friend_class                  (tree, tree, bool);
 extern void add_friend                         (tree, tree, bool);
-extern tree do_friend                          (tree, tree, tree, tree, enum overload_flags, cp_cv_quals, int);
+extern tree do_friend                          (tree, tree, tree, tree, enum overload_flags, cp_cv_quals, bool);
 
 /* in init.c */
 extern tree expand_member_init                 (tree);
index d6074d7..020d96f 100644 (file)
@@ -5697,7 +5697,7 @@ grokfndecl (tree ctype,
            int publicp,
            int inlinep,
            special_function_kind sfk,
-           int funcdef_flag,
+           bool funcdef_flag,
            int template_count,
            tree in_namespace,
            tree* attrlist)
@@ -5918,7 +5918,7 @@ grokfndecl (tree ctype,
 
   decl = check_explicit_specialization (orig_declarator, decl,
                                        template_count,
-                                       2 * (funcdef_flag != 0) +
+                                       2 * funcdef_flag +
                                        4 * (friendp != 0));
   if (decl == error_mark_node)
     return NULL_TREE;
@@ -5940,27 +5940,26 @@ grokfndecl (tree ctype,
                                 > template_class_depth (ctype))
                                ? current_template_parms
                                : NULL_TREE);
-
-      if (old_decl && TREE_CODE (old_decl) == TEMPLATE_DECL)
-       /* Because grokfndecl is always supposed to return a
-          FUNCTION_DECL, we pull out the DECL_TEMPLATE_RESULT
-          here.  We depend on our callers to figure out that its
-          really a template that's being returned.  */
-       old_decl = DECL_TEMPLATE_RESULT (old_decl);
-
-      if (old_decl && DECL_STATIC_FUNCTION_P (old_decl)
-         && TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
-       /* Remove the `this' parm added by grokclassfn.
-          XXX Isn't this done in start_function, too?  */
-       revert_static_member_fn (decl);
-      if (old_decl && DECL_ARTIFICIAL (old_decl))
-       error ("definition of implicitly-declared %qD", old_decl);
-
       if (old_decl)
        {
          tree ok;
          tree pushed_scope;
 
+         if (TREE_CODE (old_decl) == TEMPLATE_DECL)
+           /* Because grokfndecl is always supposed to return a
+              FUNCTION_DECL, we pull out the DECL_TEMPLATE_RESULT
+              here.  We depend on our callers to figure out that its
+              really a template that's being returned.  */
+           old_decl = DECL_TEMPLATE_RESULT (old_decl);
+
+         if (DECL_STATIC_FUNCTION_P (old_decl)
+             && TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
+           /* Remove the `this' parm added by grokclassfn.
+              XXX Isn't this done in start_function, too?  */
+           revert_static_member_fn (decl);
+         if (DECL_ARTIFICIAL (old_decl))
+           error ("definition of implicitly-declared %qD", old_decl);
+
          /* Since we've smashed OLD_DECL to its
             DECL_TEMPLATE_RESULT, we must do the same to DECL.  */
          if (TREE_CODE (decl) == TEMPLATE_DECL)
@@ -6627,7 +6626,8 @@ grokdeclarator (const cp_declarator *declarator,
   tree typedef_decl = NULL_TREE;
   const char *name = NULL;
   tree typedef_type = NULL_TREE;
-  int funcdef_flag = 0;
+  /* True if this declarator is a function definition.  */
+  bool funcdef_flag = false;
   cp_declarator_kind innermost_code = cdk_error;
   int bitfield = 0;
 #if 0
@@ -6674,9 +6674,9 @@ grokdeclarator (const cp_declarator *declarator,
   thread_p = declspecs->specs[(int)ds_thread];
 
   if (decl_context == FUNCDEF)
-    funcdef_flag = 1, decl_context = NORMAL;
+    funcdef_flag = true, decl_context = NORMAL;
   else if (decl_context == MEMFUNCDEF)
-    funcdef_flag = -1, decl_context = FIELD;
+    funcdef_flag = true, decl_context = FIELD;
   else if (decl_context == BITFIELD)
     bitfield = 1, decl_context = FIELD;
 
@@ -7349,8 +7349,6 @@ grokdeclarator (const cp_declarator *declarator,
                && (friendp == 0 || dname == current_class_name))
              ctype = current_class_type;
 
-           if (ctype && sfk == sfk_conversion)
-             TYPE_HAS_CONVERSION (ctype) = 1;
            if (ctype && (sfk == sfk_constructor
                          || sfk == sfk_destructor))
              {
@@ -7604,22 +7602,25 @@ grokdeclarator (const cp_declarator *declarator,
        {
          tree sname = declarator->u.id.unqualified_name;
 
+         if (current_class_type
+             && (!friendp || funcdef_flag))
+           {
+             error (funcdef_flag
+                    ? "cannot define member function %<%T::%s%> within %<%T%>"
+                    : "cannot declare member function %<%T::%s%> within %<%T%>",
+                    ctype, name, current_class_type);
+             return error_mark_node;
+           }
+
          if (TREE_CODE (sname) == IDENTIFIER_NODE
              && NEW_DELETE_OPNAME_P (sname))
            /* Overloaded operator new and operator delete
               are always static functions.  */
            ;
-         else if (current_class_type == NULL_TREE || friendp)
-           type
-             = build_method_type_directly (ctype,
-                                           TREE_TYPE (type),
-                                           TYPE_ARG_TYPES (type));
          else
-           {
-             error ("cannot declare member function %<%T::%s%> within %<%T%>",
-                    ctype, name, current_class_type);
-             return error_mark_node;
-           }
+           type = build_method_type_directly (ctype,
+                                              TREE_TYPE (type),
+                                              TYPE_ARG_TYPES (type));
        }
       else if (declspecs->specs[(int)ds_typedef]
               || COMPLETE_TYPE_P (complete_type (ctype)))
@@ -8179,7 +8180,7 @@ grokdeclarator (const cp_declarator *declarator,
                  {
                    decl = check_explicit_specialization
                      (unqualified_id, decl, template_count,
-                      2 * (funcdef_flag != 0) + 4);
+                      2 * funcdef_flag + 4);
                    if (decl == error_mark_node)
                      return error_mark_node;
                  }
index c71b90f..0ae9130 100644 (file)
@@ -408,7 +408,7 @@ tree
 do_friend (tree ctype, tree declarator, tree decl,
           tree attrlist, enum overload_flags flags,
           cp_cv_quals quals,
-          int funcdef_flag)
+          bool funcdef_flag)
 {
   /* Every decl that gets here is a friend of something.  */
   DECL_FRIEND_P (decl) = 1;
index 90d1486..bfcf261 100644 (file)
@@ -7808,7 +7808,7 @@ cp_parser_mem_initializer_list (cp_parser* parser)
       /* Parse the mem-initializer.  */
       mem_initializer = cp_parser_mem_initializer (parser);
       /* Add it to the list, unless it was erroneous.  */
-      if (mem_initializer)
+      if (mem_initializer != error_mark_node)
        {
          TREE_CHAIN (mem_initializer) = mem_initializer_list;
          mem_initializer_list = mem_initializer;
@@ -7837,7 +7837,8 @@ cp_parser_mem_initializer_list (cp_parser* parser)
 
    Returns a TREE_LIST.  The TREE_PURPOSE is the TYPE (for a base
    class) or FIELD_DECL (for a non-static data member) to initialize;
-   the TREE_VALUE is the expression-list.  */
+   the TREE_VALUE is the expression-list.  An empty initialization
+   list is represented by void_list_node.  */
 
 static tree
 cp_parser_mem_initializer (cp_parser* parser)
@@ -7862,12 +7863,14 @@ cp_parser_mem_initializer (cp_parser* parser)
     = cp_parser_parenthesized_expression_list (parser, false,
                                               /*cast_p=*/false,
                                               /*non_constant_p=*/NULL);
+  if (expression_list == error_mark_node)
+    return error_mark_node;
   if (!expression_list)
     expression_list = void_type_node;
 
   in_base_initializer = 0;
 
-  return member ? build_tree_list (member, expression_list) : NULL_TREE;
+  return member ? build_tree_list (member, expression_list) : error_mark_node;
 }
 
 /* Parse a mem-initializer-id.
@@ -8277,6 +8280,7 @@ cp_parser_template_parameter_list (cp_parser* parser)
 {
   tree parameter_list = NULL_TREE;
 
+  begin_template_parm_list ();
   while (true)
     {
       tree parameter;
@@ -8299,7 +8303,7 @@ cp_parser_template_parameter_list (cp_parser* parser)
       cp_lexer_consume_token (parser->lexer);
     }
 
-  return parameter_list;
+  return end_template_parm_list (parameter_list);
 }
 
 /* Parse a template-parameter.
@@ -8447,10 +8451,7 @@ cp_parser_type_parameter (cp_parser* parser)
        /* Look for the `<'.  */
        cp_parser_require (parser, CPP_LESS, "`<'");
        /* Parse the template-parameter-list.  */
-       begin_template_parm_list ();
-       parameter_list
-         = cp_parser_template_parameter_list (parser);
-       parameter_list = end_template_parm_list (parameter_list);
+       parameter_list = cp_parser_template_parameter_list (parser);
        /* Look for the `>'.  */
        cp_parser_require (parser, CPP_GREATER, "`>'");
        /* Look for the `class' keyword.  */
@@ -10112,6 +10113,11 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
            (parser->num_template_parameter_lists
             && (cp_parser_next_token_starts_class_definition_p (parser)
                 || cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)));
+         /* An unqualified name was used to reference this type, so
+            there were no qualifying templates.  */
+         if (!cp_parser_check_template_parameters (parser, 
+                                                   /*num_templates=*/0))
+           return error_mark_node;
          type = xref_tag (tag_type, identifier, ts, template_p);
        }
     }
@@ -15259,12 +15265,8 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
       parameter_list = NULL_TREE;
     }
   else
-    {
-      /* Parse the template parameters.  */
-      begin_template_parm_list ();
-      parameter_list = cp_parser_template_parameter_list (parser);
-      parameter_list = end_template_parm_list (parameter_list);
-    }
+    /* Parse the template parameters.  */
+    parameter_list = cp_parser_template_parameter_list (parser);
 
   /* Look for the `>'.  */
   cp_parser_skip_until_found (parser, CPP_GREATER, "`>'");
index 9575c49..df59f50 100644 (file)
@@ -325,8 +325,6 @@ build_cplus_new (tree type, tree init)
 tree
 build_target_expr_with_type (tree init, tree type)
 {
-  tree slot;
-
   gcc_assert (!VOID_TYPE_P (type));
 
   if (TREE_CODE (init) == TARGET_EXPR)
@@ -342,8 +340,7 @@ build_target_expr_with_type (tree init, tree type)
        aggregate; there's no additional work to be done.  */
     return force_rvalue (init);
 
-  slot = build_local_temp (type);
-  return build_target_expr (slot, init);
+  return force_target_expr (type, init);
 }
 
 /* Like the above function, but without the checking.  This function should
index a09d804..f96ba05 100644 (file)
@@ -1,3 +1,20 @@
+2006-01-02  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/25635
+       * g++.dg/parse/operator6.C: New test.
+
+       PR c++/25637
+       * g++.dg/parse/error29.C: New test.
+
+       PR c++/25638
+       * g++.dg/parse/dtor6.C: New test.
+
+       PR c++/25633
+       * g++.dg/parse/ctor3.C: New test.
+
+       PR c++/25634
+       * g++.dg/template/class3.C: New test.
+
 2006-01-02  Geoffrey Keating  <geoffk@apple.com>
 
        * g++.dg/debug/debug9.C: New.
diff --git a/gcc/testsuite/g++.dg/parse/ctor3.C b/gcc/testsuite/g++.dg/parse/ctor3.C
new file mode 100644 (file)
index 0000000..193ffae
--- /dev/null
@@ -0,0 +1,8 @@
+// PR c++/25633
+
+struct A {};
+
+struct B : A
+{
+  B() : A {} // { dg-error "expected" }
+};
diff --git a/gcc/testsuite/g++.dg/parse/dtor6.C b/gcc/testsuite/g++.dg/parse/dtor6.C
new file mode 100644 (file)
index 0000000..3333161
--- /dev/null
@@ -0,0 +1,8 @@
+// PR c++/25638
+
+struct A { ~A(); }; // { dg-error "candidate" }  
+
+struct B : A
+{
+  template<int> friend A::~A(); // { dg-error "match" }
+};
diff --git a/gcc/testsuite/g++.dg/parse/error29.C b/gcc/testsuite/g++.dg/parse/error29.C
new file mode 100644 (file)
index 0000000..b50b275
--- /dev/null
@@ -0,0 +1,12 @@
+// PR c++/25637
+
+struct A { 
+  void foo();
+  A(); 
+  void operator delete(void *);
+};
+struct B { 
+  friend void A::foo() {} // { dg-error "define" }
+  friend void A::operator delete(void*) {} // { dg-error "define" }
+  friend A::A() {} // { dg-error "define" }
+};
diff --git a/gcc/testsuite/g++.dg/parse/operator6.C b/gcc/testsuite/g++.dg/parse/operator6.C
new file mode 100644 (file)
index 0000000..e58a3a6
--- /dev/null
@@ -0,0 +1,5 @@
+// PR c++/25635
+
+struct A {};
+
+A::operator int(); // { dg-error "class" }
diff --git a/gcc/testsuite/g++.dg/template/class3.C b/gcc/testsuite/g++.dg/template/class3.C
new file mode 100644 (file)
index 0000000..44a02a6
--- /dev/null
@@ -0,0 +1,2 @@
+// PR c++/25634
+template<int> template<int> struct A; // { dg-error "too many" }