OSDN Git Service

* pt.c (tsubst_decl): A FUNCTION_DECL has DECL_RESULT, not
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 21 Dec 2000 17:50:10 +0000 (17:50 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 21 Dec 2000 17:50:10 +0000 (17:50 +0000)
        DECL_TEMPLATE_RESULT.

        * search.c (lookup_field_r): Call lookup_fnfields_1, not
        lookup_fnfields_here.

        * parse.y (typename_sub2): Return the TYPE_DECL, not the type.

        * call.c (build_object_call): Also allow conversions that return
        reference to pointer to function.
        (add_conv_candidate): Handle totype being ref to ptr to fn.
        (build_field_call): Also allow members of type reference to function.
        Lose support for calling pointer to METHOD_TYPE fields.

        * error.c (dump_expr): Handle *_CAST_EXPR.

        * typeck2.c (build_scoped_ref): Always convert to the naming class.

        * tree.c (break_out_cleanups): Lose.
        * cp-tree.h: Remove prototype.
        * typeck.c (build_component_ref): Don't break_out_cleanups.
        (build_compound_expr): Likewise.
        * semantics.c (finish_expr_stmt): Likewise.

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

17 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/error.c
gcc/cp/parse.y
gcc/cp/pt.c
gcc/cp/search.c
gcc/cp/semantics.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/cp/typeck2.c
gcc/testsuite/g++.old-deja/g++.benjamin/scope01.C
gcc/testsuite/g++.old-deja/g++.brendan/misc15.C
gcc/testsuite/g++.old-deja/g++.other/call1.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.other/lookup18.C
gcc/testsuite/g++.old-deja/g++.other/lookup20.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/parms3.C [new file with mode: 0644]

index fc473fb..0dd5b81 100644 (file)
@@ -1,3 +1,29 @@
+2000-12-20  Jason Merrill  <jason@redhat.com>
+
+       * pt.c (tsubst_decl): A FUNCTION_DECL has DECL_RESULT, not
+       DECL_TEMPLATE_RESULT.
+
+       * search.c (lookup_field_r): Call lookup_fnfields_1, not
+       lookup_fnfields_here.
+
+       * parse.y (typename_sub2): Return the TYPE_DECL, not the type.
+
+       * call.c (build_object_call): Also allow conversions that return
+       reference to pointer to function.
+       (add_conv_candidate): Handle totype being ref to ptr to fn.
+       (build_field_call): Also allow members of type reference to function.
+       Lose support for calling pointer to METHOD_TYPE fields.
+
+       * error.c (dump_expr): Handle *_CAST_EXPR.
+
+       * typeck2.c (build_scoped_ref): Always convert to the naming class.
+
+       * tree.c (break_out_cleanups): Lose.
+       * cp-tree.h: Remove prototype.
+       * typeck.c (build_component_ref): Don't break_out_cleanups.
+       (build_compound_expr): Likewise.
+       * semantics.c (finish_expr_stmt): Likewise.
+
 2000-12-20  Richard Henderson  <rth@redhat.com>
 
        * cp-tree.h: Update declarations.
index 77e29eb..e7de1ba 100644 (file)
@@ -156,15 +156,11 @@ build_field_call (basetype_path, instance_ptr, name, parms)
       if (IS_AGGR_TYPE (TREE_TYPE (instance)))
        return build_opfncall (CALL_EXPR, LOOKUP_NORMAL,
                               instance, parms, NULL_TREE);
-      else if (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE)
-       {
-         if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == FUNCTION_TYPE)
-           return build_function_call (instance, parms);
-         else if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance)))
-                  == METHOD_TYPE)
-           return build_function_call
-             (instance, tree_cons (NULL_TREE, instance_ptr, parms));
-       }
+      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;
@@ -1422,13 +1418,19 @@ add_conv_candidate (candidates, fn, obj, arglist)
      tree fn, obj, arglist;
 {
   tree totype = TREE_TYPE (TREE_TYPE (fn));
-  tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (totype));
-  int i, len = list_length (arglist) + 1;
-  tree convs = make_tree_vec (len);
-  tree parmnode = parmlist;
-  tree argnode = arglist;
-  int viable = 1;
-  int flags = LOOKUP_NORMAL;
+  int i, len, viable, flags;
+  tree parmlist, convs, parmnode, argnode;
+
+  for (parmlist = totype; TREE_CODE (parmlist) != FUNCTION_TYPE; )
+    parmlist = TREE_TYPE (parmlist);
+  parmlist = TYPE_ARG_TYPES (parmlist);
+
+  len = list_length (arglist) + 1;
+  convs = make_tree_vec (len);
+  parmnode = parmlist;
+  argnode = arglist;
+  viable = 1;
+  flags = LOOKUP_NORMAL;
 
   /* Don't bother looking up the same type twice.  */
   if (candidates && candidates->fn == totype)
@@ -2659,8 +2661,12 @@ build_object_call (obj, args)
       tree totype = TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns)));
 
       if ((TREE_CODE (totype) == POINTER_TYPE
-          || TREE_CODE (totype) == REFERENCE_TYPE)
-         && TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE)
+          && TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE)
+         || (TREE_CODE (totype) == REFERENCE_TYPE
+             && TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE)
+         || (TREE_CODE (totype) == REFERENCE_TYPE
+             && TREE_CODE (TREE_TYPE (totype)) == POINTER_TYPE
+             && TREE_CODE (TREE_TYPE (TREE_TYPE (totype))) == FUNCTION_TYPE))
        for (; fns; fns = OVL_NEXT (fns))
          {
            tree fn = OVL_CURRENT (fns);
index f6d0b82..7c3dce4 100644 (file)
@@ -4401,7 +4401,6 @@ extern int lvalue_p                               PARAMS ((tree));
 extern int lvalue_or_else                      PARAMS ((tree, const char *));
 extern tree build_cplus_new                    PARAMS ((tree, tree));
 extern tree get_target_expr                    PARAMS ((tree));
-extern tree break_out_cleanups                 PARAMS ((tree));
 extern tree break_out_calls                    PARAMS ((tree));
 extern tree build_cplus_method_type            PARAMS ((tree, tree, tree));
 extern tree build_cplus_staticfn_type          PARAMS ((tree, tree, tree));
index b208e65..ce11ae1 100644 (file)
@@ -2051,6 +2051,24 @@ dump_expr (t, flags)
        }
       break;
 
+    case STATIC_CAST_EXPR:
+      output_add_string (scratch_buffer, "static_cast<");
+      goto cast;
+    case REINTERPRET_CAST_EXPR:
+      output_add_string (scratch_buffer, "reinterpret_cast<");
+      goto cast;
+    case CONST_CAST_EXPR:
+      output_add_string (scratch_buffer, "const_cast<");
+      goto cast;
+    case DYNAMIC_CAST_EXPR:
+      output_add_string (scratch_buffer, "dynamic_cast<");
+    cast:
+      dump_type (TREE_TYPE (t), flags);
+      output_add_string (scratch_buffer, ">(");
+      dump_expr (TREE_OPERAND (t, 0), flags);
+      print_right_paren (scratch_buffer);
+      break;
+
     case LOOKUP_EXPR:
       print_tree_identifier (scratch_buffer, TREE_OPERAND (t, 0));
       break;
index 15cf725..4e76394 100644 (file)
@@ -3056,6 +3056,8 @@ typename_sub1:
                {
                  if (TREE_CODE ($1) == IDENTIFIER_NODE)
                    cp_error ("`%T' is not a class or namespace", $1);
+                 else if (TREE_CODE ($1) == TYPE_DECL)
+                   $$ = TREE_TYPE ($1);
                }
        | typename_sub1 typename_sub2
                {
@@ -3078,24 +3080,26 @@ typename_sub1:
                    = make_typename_type ($1, $3, /*complain=*/1); }
        ;
 
+/* This needs to return a TYPE_DECL for simple names so that we don't
+   forget what name was used.  */
 typename_sub2:
          TYPENAME SCOPE
                {
-                 if (TREE_CODE ($1) != IDENTIFIER_NODE)
-                   $1 = lastiddecl;
+                 if (TREE_CODE ($1) != TYPE_DECL)
+                   $$ = lastiddecl;
 
                  /* Retrieve the type for the identifier, which might involve
                     some computation. */
-                 got_scope = $$ = complete_type (IDENTIFIER_TYPE_VALUE ($1));
+                 got_scope = complete_type (TREE_TYPE ($$));
 
                  if ($$ == error_mark_node)
                    cp_error ("`%T' is not a class or namespace", $1);
                }
        | SELFNAME SCOPE
                {
-                 if (TREE_CODE ($1) != IDENTIFIER_NODE)
+                 if (TREE_CODE ($1) != TYPE_DECL)
                    $$ = lastiddecl;
-                 got_scope = $$ = complete_type (TREE_TYPE ($$));
+                 got_scope = complete_type (TREE_TYPE ($$));
                }
        | template_type SCOPE
                { got_scope = $$ = complete_type (TREE_TYPE ($$)); }
index 3a0096e..50e7ddf 100644 (file)
@@ -5715,7 +5715,7 @@ tsubst_decl (t, args, type, in_decl)
 
        DECL_ARGUMENTS (r) = tsubst (DECL_ARGUMENTS (t), args,
                                     /*complain=*/1, t);
-       DECL_TEMPLATE_RESULT (r) = NULL_TREE;
+       DECL_RESULT (r) = NULL_TREE;
 
        TREE_STATIC (r) = 0;
        TREE_PUBLIC (r) = TREE_PUBLIC (t);
index 601f08b..2f4a3e9 100644 (file)
@@ -1251,7 +1251,9 @@ is_subobject_of_p (parent, binfo, most_derived)
 
 /* Very similar to lookup_fnfields_1 but it ensures that at least one
    function was declared inside the class given by TYPE.  It really should
-   only return functions that match the given TYPE.  */
+   only return functions that match the given TYPE.  Therefore, it should
+   only be called for situations that ignore using-declarations, such as
+   determining overrides.  */
 
 static int
 lookup_fnfields_here (type, name)
@@ -1359,7 +1361,7 @@ lookup_field_r (binfo, data)
      with the same name, the type is hidden by the function.  */
   if (!lfi->want_type)
     {
-      int idx = lookup_fnfields_here (type, lfi->name);
+      int idx = lookup_fnfields_1 (type, lfi->name);
       if (idx >= 0)
        nval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx);
     }
index 856f4ae..28bf1cc 100644 (file)
@@ -214,9 +214,6 @@ finish_expr_stmt (expr)
       if (stmts_are_full_exprs_p ())
        expr = convert_to_void (expr, "statement");
       
-      if (!processing_template_decl)
-       expr = break_out_cleanups (expr);
-      
       r = add_stmt (build_stmt (EXPR_STMT, expr));
     }
 
index f86318b..a1089ce 100644 (file)
@@ -317,37 +317,6 @@ get_target_expr (init)
   return build_target_expr_with_type (init, TREE_TYPE (init));
 }
 
-/* Recursively search EXP for CALL_EXPRs that need cleanups and replace
-   these CALL_EXPRs with tree nodes that will perform the cleanups.  */
-
-tree
-break_out_cleanups (exp)
-     tree exp;
-{
-  tree tmp = exp;
-
-  if (TREE_CODE (tmp) == CALL_EXPR
-      && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (tmp)))
-    return build_cplus_new (TREE_TYPE (tmp), tmp);
-
-  while (TREE_CODE (tmp) == NOP_EXPR
-        || TREE_CODE (tmp) == CONVERT_EXPR
-        || TREE_CODE (tmp) == NON_LVALUE_EXPR)
-    {
-      if (TREE_CODE (TREE_OPERAND (tmp, 0)) == CALL_EXPR
-         && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (TREE_OPERAND (tmp, 0))))
-       {
-         TREE_OPERAND (tmp, 0)
-           = build_cplus_new (TREE_TYPE (TREE_OPERAND (tmp, 0)),
-                              TREE_OPERAND (tmp, 0));
-         break;
-       }
-      else
-       tmp = TREE_OPERAND (tmp, 0);
-    }
-  return exp;
-}
-
 /* Recursively perform a preorder search EXP for CALL_EXPRs, making
    copies where they are found.  Returns a deep copy all nodes transitively
    containing CALL_EXPRs.  */
index 6d12cbd..8de99f6 100644 (file)
@@ -2278,8 +2278,7 @@ build_component_ref (datum, component, basetype_path, protect)
       field_type = cp_build_qualified_type (field_type, type_quals);
     }
 
-  ref = fold (build (COMPONENT_REF, field_type,
-                    break_out_cleanups (datum), field));
+  ref = fold (build (COMPONENT_REF, field_type, datum, field));
 
   /* Mark the expression const or volatile, as appropriate.  Even
      though we've dealt with the type above, we still have to mark the
@@ -5039,8 +5038,7 @@ build_compound_expr (list)
   if (! TREE_SIDE_EFFECTS (first) && ! pedantic)
     return rest;
 
-  return build (COMPOUND_EXPR, TREE_TYPE (rest),
-               break_out_cleanups (first), rest);
+  return build (COMPOUND_EXPR, TREE_TYPE (rest), first, rest);
 }
 
 tree
index d8143f8..c40b81c 100644 (file)
@@ -957,9 +957,10 @@ process_init_constructor (type, init, elts)
    the A part of the C object named by X.  In this case,
    DATUM would be x, and BASETYPE would be A.
 
-   Note that this is nonconformant; the standard specifies that first
-   we look up ii in A, then convert x to an L& and pull out the ii part.
-   But narrowing seems to be standard practice, so let's do it anyway.  */
+   I used to think that this was nonconformant, that the standard specified
+   that first we look up ii in A, then convert x to an L& and pull out the
+   ii part.  But in fact, it does say that we convert x to an A&; A here
+   is known as the "naming class".  (jason 2000-12-19) */
 
 tree
 build_scoped_ref (datum, basetype)
@@ -967,16 +968,10 @@ build_scoped_ref (datum, basetype)
      tree basetype;
 {
   tree ref;
-  tree type = TREE_TYPE (datum);
 
   if (datum == error_mark_node)
     return error_mark_node;
 
-  /* Don't do this if it would cause an error or if we're being pedantic.  */
-  if (! ACCESSIBLY_UNIQUELY_DERIVED_P (basetype, type)
-      || pedantic)
-    return datum;
-
   ref = build_unary_op (ADDR_EXPR, datum, 0);
   ref = convert_pointer_to (basetype, ref);
 
index 582723a..a834f4f 100644 (file)
@@ -19,8 +19,8 @@ class C : public A, public B {};
 void foo() {
   // straight call
   C x;
-  x.A::ii = 5;                 // ERROR - L is ambiguous base
-  x.A::foo(x.A::ii);           // ERROR - L is ambiguous base
+  x.A::ii = 5;
+  x.A::foo(x.A::ii);
   
   // 5.1 Primary expressions
   // p 8 
index 30c4feb..a294e4f 100644 (file)
@@ -9,5 +9,5 @@ struct B : public A {
 struct C : public A {
 };
 struct D : public C, public B {
-        void fun() { C::aa = 10; } // ERROR - conversion to A is ambiguous
+        void fun() { C::aa = 10; }
 };
diff --git a/gcc/testsuite/g++.old-deja/g++.other/call1.C b/gcc/testsuite/g++.old-deja/g++.other/call1.C
new file mode 100644 (file)
index 0000000..7341488
--- /dev/null
@@ -0,0 +1,51 @@
+// Test that various calls to non-functions work.
+
+void f () { }
+
+typedef void (*fptr)();
+typedef void (&fref)();
+fptr p = f;
+fref r = f;
+const fptr &pr = p;
+
+struct A {
+  fptr p;
+
+  A (fptr n): p(n) { }
+  operator fptr () { return p; }
+};
+
+struct B {
+  fref r;
+
+  B (fptr n): r(*n) { }
+  operator const fref () { return r; }
+};
+
+struct C {
+  const fptr &pr;
+
+  C (fptr n): pr(n) { }
+  operator const fptr& () { return pr; }
+};
+
+int main ()
+{
+  f();
+
+  p();
+  r();
+  pr();
+
+  A a (f);
+  a();
+  a.p();
+
+  B b (f);
+  b();
+  b.r();
+
+  C c (f);
+  c();
+  c.pr();
+}
index bec78f8..09549f7 100644 (file)
@@ -1,5 +1,5 @@
-// Test that referring to an ambiguous base in name lookup does not
-// interfere with accessing the field, which is not ambiguous.
+// Test that referring to an ambiguous base in name lookup prevents
+// access to the field, even though the field is not ambiguous.
 
 // Build don't link:
 
@@ -14,10 +14,10 @@ struct E: public C, public D {
 };
 
 void E::f() {
-  B::i = 0;
+  B::i = 0;                    // ERROR - B is ambiguous
 }
 
 void f () {
   E e;
-  e.B::i = 0;
+  e.B::i = 0;                  // ERROR - B is ambiguous
 }
diff --git a/gcc/testsuite/g++.old-deja/g++.other/lookup20.C b/gcc/testsuite/g++.old-deja/g++.other/lookup20.C
new file mode 100644 (file)
index 0000000..930c9ab
--- /dev/null
@@ -0,0 +1,10 @@
+// Bug: typename_sub2 returned the type, so we tried to look up "A" in B.
+// Build don't link:
+
+struct A { struct A1 { }; };
+
+struct B {
+  typedef A Q;
+};
+
+struct C: public B::Q::A1 { };
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/parms3.C b/gcc/testsuite/g++.old-deja/g++.pt/parms3.C
new file mode 100644 (file)
index 0000000..031f3d6
--- /dev/null
@@ -0,0 +1,8 @@
+// Test that we can represent static_casts in template arg lists.
+// Build don't link:
+
+template <int I> struct A { };
+
+template <class T> struct B {
+  A<static_cast<T>(3.14)> a;
+};