re PR c++/13592 (C++ parser regression)
authorMark Mitchell <mark@codesourcery.com>
Mon, 19 Jan 2004 20:33:29 +0000 (20:33 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Mon, 19 Jan 2004 20:33:29 +0000 (20:33 +0000)
PR c++/13592
* call.c (build_field_call): Remove.
(n_build_method_call): Likewise.
(build_method_call): Likewise.
(build_new_method_call): Do not call build_field_call.
* class.c (n_build_method_call): Remove.
(print_class_statistics): Do not print it.
* cp-tree.h (build_method_call): Remove declaration.
(finish_object_call_expr): Likewise.
(build_new_1): Do not use build_method_call.
* parser.c (cp_parser_postfix_expression): Use finish_call_expr
when the function appearing on the right-hand-side of "." or "->"
is not actually a function.
* pt.c (tsubst_copy_and_build): Likewise.
* semantics.c (finish_object_call_expr): Remove.

PR c++/13592
* g++.dg/template/call2.C: New test.

From-SVN: r76173

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/init.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/call2.C [new file with mode: 0644]

index dd4b7d17c4568fcf497ec624aace72b10bae5c73..976b0752fd638bbe61284dafb586e90ef2cad63e 100644 (file)
@@ -1,3 +1,21 @@
+2004-01-19  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/13592
+       * call.c (build_field_call): Remove.
+       (n_build_method_call): Likewise.
+       (build_method_call): Likewise.
+       (build_new_method_call): Do not call build_field_call.
+       * class.c (n_build_method_call): Remove.
+       (print_class_statistics): Do not print it.
+       * cp-tree.h (build_method_call): Remove declaration.
+       (finish_object_call_expr): Likewise.
+       (build_new_1): Do not use build_method_call.
+       * parser.c (cp_parser_postfix_expression): Use finish_call_expr
+       when the function appearing on the right-hand-side of "." or "->"
+       is not actually a function.
+       * pt.c (tsubst_copy_and_build): Likewise.
+       * semantics.c (finish_object_call_expr): Remove.
+
 2004-01-18  Mark Mitchell  <mark@codesourcery.com>
 
        PR c++/13710
index 7864d08820677d8f2d4055e4c1c0aa3687d4c969..ea4e0669fb45889696fc448a4a67f37d044bab5b 100644 (file)
@@ -40,7 +40,6 @@ Boston, MA 02111-1307, USA.  */
 #include "target.h"
 #include "convert.h"
 
-static tree build_field_call (tree, tree, tree);
 static struct z_candidate * tourney (struct z_candidate *);
 static int equal_functions (tree, tree);
 static int joust (struct z_candidate *, struct z_candidate *, bool);
@@ -128,42 +127,6 @@ build_vfield_ref (tree datum, tree type)
                datum, TYPE_VFIELD (type));
 }
 
-/* Build a call to a member of an object.  I.e., one that overloads
-   operator ()(), or is a pointer-to-function or pointer-to-method.  */
-
-static tree
-build_field_call (tree instance_ptr, tree decl, tree parms)
-{
-  tree instance;
-
-  if (decl == error_mark_node || decl == NULL_TREE)
-    return decl;
-
-  if (TREE_CODE (decl) == FIELD_DECL || TREE_CODE (decl) == VAR_DECL)
-    {
-      /* If it's a field, try overloading operator (),
-        or calling if the field is a pointer-to-function.  */
-      instance = build_indirect_ref (instance_ptr, NULL);
-      instance = build_class_member_access_expr (instance, decl, 
-                                                /*access_path=*/NULL_TREE,
-                                                /*preserve_reference=*/false);
-
-      if (instance == error_mark_node)
-       return error_mark_node;
-
-      if (IS_AGGR_TYPE (TREE_TYPE (instance)))
-       return build_new_op (CALL_EXPR, LOOKUP_NORMAL,
-                            instance, parms, NULL_TREE);
-      else if (TREE_CODE (TREE_TYPE (instance)) == FUNCTION_TYPE
-              || (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE
-                  && (TREE_CODE (TREE_TYPE (TREE_TYPE (instance)))
-                      == FUNCTION_TYPE)))
-       return build_function_call (instance, parms);
-    }
-
-  return NULL_TREE;
-}
-
 /* Returns nonzero iff the destructor name specified in NAME
    (a BIT_NOT_EXPR) matches BASETYPE.  The operand of NAME can take many
    forms...  */
@@ -342,102 +305,6 @@ build_call (tree function, tree parms)
    `operator()()' is defined for the type of that field, then we return
    that result.  */
 
-#ifdef GATHER_STATISTICS
-extern int n_build_method_call;
-#endif
-
-tree
-build_method_call (tree instance, tree name, tree parms,
-                   tree basetype_path, int flags)
-{
-  tree fn;
-  tree object_type;
-  tree template_args = NULL_TREE;
-  bool has_template_args = false;
-
-#ifdef GATHER_STATISTICS
-  n_build_method_call++;
-#endif
-
-  if (error_operand_p (instance)
-      || name == error_mark_node
-      || parms == error_mark_node)
-    return error_mark_node;
-
-  my_friendly_assert (!processing_template_decl, 20030707);
-
-  if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
-    instance = convert_from_reference (instance);
-  object_type = TREE_TYPE (instance);
-
-  if (TREE_CODE (name) == BIT_NOT_EXPR)
-    {
-      tree instance_ptr;
-
-      if (parms)
-       error ("destructors take no parameters");
-
-      if (! check_dtor_name (object_type, name))
-       error
-         ("destructor name `~%T' does not match type `%T' of expression",
-          TREE_OPERAND (name, 0), object_type);
-
-      if (! TYPE_HAS_DESTRUCTOR (complete_type (object_type)))
-       return convert_to_void (instance, /*implicit=*/NULL);
-      instance = default_conversion (instance);
-      instance_ptr = build_unary_op (ADDR_EXPR, instance, 0);
-      return build_delete (build_pointer_type (object_type),
-                          instance_ptr, sfk_complete_destructor,
-                          LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0);
-    }
-
-  if (!CLASS_TYPE_P (object_type))
-    {
-      if ((flags & LOOKUP_COMPLAIN) 
-         && TREE_TYPE (instance) != error_mark_node)
-       error ("request for member `%D' in `%E', which is of non-aggregate type `%T'",
-              name, instance, object_type);
-      return error_mark_node;
-    }
-
-  if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
-    {
-      template_args = TREE_OPERAND (name, 1);
-      has_template_args = true;
-      name = TREE_OPERAND (name, 0);
-    }
-  if (TREE_CODE (name) == OVERLOAD)
-    name = DECL_NAME (get_first_fn (name));
-  else if (DECL_P (name))
-    name = DECL_NAME (name);
-  if (has_template_args)
-    fn = lookup_fnfields (object_type, name, /*protect=*/2);
-  else
-    fn = lookup_member (object_type, name, /*protect=*/2, /*want_type=*/false);
-  
-  if (fn && TREE_CODE (fn) == TREE_LIST)
-    {
-      error ("request for member `%D' is ambiguous", name);
-      print_candidates (fn);
-      return error_mark_node;
-    }
-
-  /* If the name could not be found, issue an error.  */
-  if (!fn)
-    return unqualified_name_lookup_error (name);
-
-  if (BASELINK_P (fn) && has_template_args)
-    BASELINK_FUNCTIONS (fn)
-      = build_nt (TEMPLATE_ID_EXPR,
-                 BASELINK_FUNCTIONS (fn),
-                 template_args);
-  if (BASELINK_P (fn) && basetype_path)
-    BASELINK_ACCESS_BINFO (fn) = basetype_path;
-
-  return build_new_method_call (instance, fn, parms, 
-                               /*conversion_path=*/NULL_TREE, flags);
-}
-
 /* New overloading code.  */
 
 struct z_candidate GTY(()) {
@@ -5058,9 +4925,6 @@ build_new_method_call (tree instance, tree fns, tree args,
 
   if (!BASELINK_P (fns))
     {
-      call = build_field_call (instance_ptr, fns, args);
-      if (call)
-       goto finish;
       error ("call to non-function `%D'", fns);
       return error_mark_node;
     }
@@ -5221,7 +5085,6 @@ build_new_method_call (tree instance, tree fns, tree args,
       if (!is_dummy_object (instance_ptr) && TREE_SIDE_EFFECTS (instance))
        call = build (COMPOUND_EXPR, TREE_TYPE (call), instance, call);
     }
- finish:;
   
   if (processing_template_decl && call != error_mark_node)
     return build_min_non_dep
index b376f99aa218adb0c0bd4e0e9620d91ce7b5a962..af5afb0c7903fe3e2f2b42462408ae6faf5fd32e 100644 (file)
@@ -227,7 +227,6 @@ int n_vtable_searches = 0;
 int n_vtable_elems = 0;
 int n_convert_harshness = 0;
 int n_compute_conversion_costs = 0;
-int n_build_method_call = 0;
 int n_inner_fields_searched = 0;
 #endif
 
@@ -6288,8 +6287,6 @@ print_class_statistics (void)
 #ifdef GATHER_STATISTICS
   fprintf (stderr, "convert_harshness = %d\n", n_convert_harshness);
   fprintf (stderr, "compute_conversion_costs = %d\n", n_compute_conversion_costs);
-  fprintf (stderr, "build_method_call = %d (inner = %d)\n",
-          n_build_method_call, n_inner_fields_searched);
   if (n_vtables)
     {
       fprintf (stderr, "vtables = %d; vtable searches = %d\n",
index ac6ecdfed7c55922a09a4494a73250040de14adb..f7d3a65087830d37af182fba807779fe5768f438 100644 (file)
@@ -3299,7 +3299,7 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
 #define B_CLR(A,X) ((A)[(X)>>3] &= ~(1 << ((X)&7)))
 #define B_TST(A,X) ((A)[(X)>>3] &   (1 << ((X)&7)))
 
-/* These are uses as bits in flags passed to build_method_call
+/* These are uses as bits in flags passed to build_new_method_call
    to control its error reporting behavior.
 
    LOOKUP_PROTECT means flag access violations.
@@ -3512,7 +3512,6 @@ extern tree build_vfield_ref                      (tree, tree);
 extern tree build_conditional_expr             (tree, tree, tree);
 extern tree build_addr_func (tree);
 extern tree build_call (tree, tree);
-extern tree build_method_call (tree, tree, tree, tree, int);
 extern bool null_ptr_cst_p (tree);
 extern bool sufficient_parms_p (tree);
 extern tree type_decays_to (tree);
@@ -4062,7 +4061,6 @@ extern tree perform_koenig_lookup               (tree, tree);
 extern tree finish_call_expr                    (tree, tree, bool, bool);
 extern tree finish_increment_expr               (tree, enum tree_code);
 extern tree finish_this_expr                    (void);
-extern tree finish_object_call_expr             (tree, tree, tree);
 extern tree finish_pseudo_destructor_expr       (tree, tree, tree);
 extern tree finish_unary_op_expr                (enum tree_code, tree);
 extern tree finish_compound_literal             (tree, tree);
index e74a5980098c21cf33959b40f76b73f8aa7118b5..6111f6b768c9105ce0708719cafd9d45ef11b1dd 100644 (file)
@@ -1251,8 +1251,8 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags)
    from TRUE_EXP.  In constructors, we don't know anything about
    the value being initialized.
 
-   FLAGS is just passes to `build_method_call'.  See that function for
-   its description.  */
+   FLAGS is just passed to `build_new_method_call'.  See that function
+   for its description.  */
 
 static void
 expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags)
@@ -2031,6 +2031,7 @@ build_new_1 (tree exp)
   else
     {
       tree fnname;
+      tree fns;
 
       fnname = ansi_opname (code);
 
@@ -2049,11 +2050,18 @@ build_new_1 (tree exp)
            }
          /* Create the argument list.  */
          args = tree_cons (NULL_TREE, size, placement);
-         /* Call the function.  */
-         alloc_call = build_method_call (build_dummy_object (true_type),
-                                         fnname, args, 
-                                         TYPE_BINFO (true_type),
-                                         LOOKUP_NORMAL);
+         /* Do name-lookup to find the appropriate operator.  */
+         fns = lookup_fnfields (true_type, fnname, /*protect=*/2);
+         if (TREE_CODE (fns) == TREE_LIST)
+           {
+             error ("request for member `%D' is ambiguous", fnname);
+             print_candidates (fns);
+             return error_mark_node;
+           }
+         alloc_call = build_new_method_call (build_dummy_object (true_type),
+                                             fns, args,
+                                             /*conversion_path=*/NULL_TREE,
+                                             LOOKUP_NORMAL);
        }
       else
        {
index 481864b10955c1cd573f97a93803c4f0e7ede0ee..a9b62d068b1ca91129211fc5266a94ab7cd1d1a7 100644 (file)
@@ -3761,12 +3761,18 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
                      = build_min_nt (CALL_EXPR, postfix_expression, args);
                    break;
                  }
-                 
-               postfix_expression
-                 = (build_new_method_call 
-                    (instance, fn, args, NULL_TREE, 
-                     (idk == CP_ID_KIND_QUALIFIED 
-                      ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL)));
+
+               if (BASELINK_P (fn))
+                 postfix_expression
+                   = (build_new_method_call 
+                      (instance, fn, args, NULL_TREE, 
+                       (idk == CP_ID_KIND_QUALIFIED 
+                        ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL)));
+               else
+                 postfix_expression
+                   = finish_call_expr (postfix_expression, args,
+                                       /*disallow_virtual=*/false,
+                                       /*koenig_p=*/false);
              }
            else if (TREE_CODE (postfix_expression) == OFFSET_REF
                     || TREE_CODE (postfix_expression) == MEMBER_REF
index 78c2b1348ab576d5a7f52961ae81976d654214f8..967e9d1da8e2c5533846ecf40b7f4abda737b670 100644 (file)
@@ -8279,11 +8279,18 @@ tsubst_copy_and_build (tree t,
        if (TREE_CODE (function) == OFFSET_REF)
          return build_offset_ref_call_from_tree (function, call_args);
        if (TREE_CODE (function) == COMPONENT_REF)
-         return (build_new_method_call 
-                 (TREE_OPERAND (function, 0),
-                  TREE_OPERAND (function, 1),
-                  call_args, NULL_TREE, 
-                  qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL));
+         {
+           if (!BASELINK_P (TREE_OPERAND (function, 1)))
+             return finish_call_expr (function, call_args,
+                                      /*disallow_virtual=*/false,
+                                      /*koenig_p=*/false);
+           else
+             return (build_new_method_call 
+                     (TREE_OPERAND (function, 0),
+                      TREE_OPERAND (function, 1),
+                      call_args, NULL_TREE, 
+                      qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL));
+         }
        return finish_call_expr (function, call_args, 
                                 /*disallow_virtual=*/qualified_p,
                                 koenig_p);
index 00f1a4f2fe9e8b5a6e37f2f41911399754535756..059ed1591e51ebcaae8c242d9e99f271fb6b791c 100644 (file)
@@ -1774,42 +1774,6 @@ finish_this_expr (void)
   return result;
 }
 
-/* Finish a member function call using OBJECT and ARGS as arguments to
-   FN.  Returns an expression for the call.  */
-
-tree 
-finish_object_call_expr (tree fn, tree object, tree args)
-{
-  if (DECL_DECLARES_TYPE_P (fn))
-    {
-      if (processing_template_decl)
-       /* This can happen on code like:
-
-          class X;
-          template <class T> void f(T t) {
-            t.X();
-          }  
-
-          We just grab the underlying IDENTIFIER.  */
-       fn = DECL_NAME (fn);
-      else
-       {
-         error ("calling type `%T' like a method", fn);
-         return error_mark_node;
-       }
-    }
-  
-  if (processing_template_decl)
-    return build_nt (CALL_EXPR,
-                    build_nt (COMPONENT_REF, object, fn),
-                    args);
-
-  if (name_p (fn))
-    return build_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
-  else
-    return build_new_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
-}
-
 /* Finish a pseudo-destructor expression.  If SCOPE is NULL, the
    expression was of the form `OBJECT.~DESTRUCTOR' where DESTRUCTOR is
    the TYPE for the type given.  If SCOPE is non-NULL, the expression
index 9bd505d2c67f4620c139f19d4df6d7d4ff3cd283..a473f27af29cb74fec7a0188eb290d7ee6d10525 100644 (file)
@@ -1,3 +1,8 @@
+2004-01-19  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/13592
+       * g++.dg/template/call2.C: New test.
+
 2004-01-19  Eric Botcazou  <ebotcazou@libertysurf.fr>
 
        * gcc.dg/compat/fnptr-by-value-1_x.c, scalar-by-value-1_y.c
diff --git a/gcc/testsuite/g++.dg/template/call2.C b/gcc/testsuite/g++.dg/template/call2.C
new file mode 100644 (file)
index 0000000..86d5c2e
--- /dev/null
@@ -0,0 +1,14 @@
+// PR c++/13592
+
+struct S { 
+  void operator()(int); 
+}; 
+struct A { 
+  template <typename> void foo(); 
+  S s; 
+}; 
+template <typename> void A::foo() { 
+  s(0); 
+}