* call.c (joust): Only prefer a non-builtin candidate to a builtin
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 25 Jul 2001 15:04:32 +0000 (15:04 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 25 Jul 2001 15:04:32 +0000 (15:04 +0000)
        one if they have the same signature.

        * cvt.c (build_up_reference): Take DECL parm.  Check TREE_STATIC on
        it rather than toplevel_bindings_p.  Give it a mangled name if static.
        (convert_to_reference): Adjust.
        * decl2.c (get_temp_name): Lose.
        * mangle.c (mangle_ref_init_variable): New fn.
        (mangle_guard_variable): Strip the ref-init header.
        * cp-tree.h: Adjust.
        * decl.c (cp_finish_decl): Add the DECL_STMT after processing the
        initializer.
        (grok_reference_init): Always use DECL_INITIAL.

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

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/mangle.c
gcc/testsuite/g++.dg/README [new file with mode: 0644]
gcc/testsuite/g++.dg/init/init-ref1.C [moved from gcc/testsuite/g++.dg/other/init-ref1.C with 100% similarity]
gcc/testsuite/g++.dg/init/init-ref2.C [moved from gcc/testsuite/g++.dg/other/init-ref2.C with 100% similarity]
gcc/testsuite/g++.dg/overload/builtin1.C [new file with mode: 0644]

index eb00008..050f437 100644 (file)
@@ -1,3 +1,19 @@
+2001-07-25  Jason Merrill  <jason_merrill@redhat.com>
+       
+       * call.c (joust): Only prefer a non-builtin candidate to a builtin
+       one if they have the same signature.
+
+       * cvt.c (build_up_reference): Take DECL parm.  Check TREE_STATIC on
+       it rather than toplevel_bindings_p.  Give it a mangled name if static.
+       (convert_to_reference): Adjust.
+       * decl2.c (get_temp_name): Lose.
+       * mangle.c (mangle_ref_init_variable): New fn.
+       (mangle_guard_variable): Strip the ref-init header.
+       * cp-tree.h: Adjust.
+       * decl.c (cp_finish_decl): Add the DECL_STMT after processing the
+       initializer.
+       (grok_reference_init): Always use DECL_INITIAL.
+
 2001-07-25  Nathan Sidwell  <nathan@codesourcery.com>
 
        PR c++/3416
index 4be0920..268cc27 100644 (file)
@@ -5353,22 +5353,6 @@ joust (cand1, cand2, warn)
         return winner;
     }
 
-  /* a non-template user function is better than a builtin.  (Pedantically
-     the builtin which matched the user function should not be added to
-     the overload set, but we spot it here.
-     
-     [over.match.oper]
-     ... the builtin candidates include ...
-     - do not have the same parameter type list as any non-template
-       non-member candidate.  */
-                            
-  if (TREE_CODE (cand1->fn) != IDENTIFIER_NODE
-      && TREE_CODE (cand2->fn) == IDENTIFIER_NODE)
-    return 1;
-  else if (TREE_CODE (cand1->fn) == IDENTIFIER_NODE
-           && TREE_CODE (cand2->fn) != IDENTIFIER_NODE)
-    return -1;
-  
   /* or, if not that,
      the  context  is  an  initialization by user-defined conversion (see
      _dcl.init_  and  _over.match.user_)  and  the  standard   conversion
@@ -5384,21 +5368,42 @@ joust (cand1, cand2, warn)
         return winner;
     }
   
-  /* If the built-in candidates are the same, arbitrarily pick one.  */
-  if (cand1->fn == cand2->fn
-      && TREE_CODE (cand1->fn) == IDENTIFIER_NODE)
+  /* Check whether we can discard a builtin candidate, either because we
+     have two identical ones or matching builtin and non-builtin candidates.
+
+     (Pedantically in the latter case the builtin which matched the user
+     function should not be added to the overload set, but we spot it here.
+     
+     [over.match.oper]
+     ... the builtin candidates include ...
+     - do not have the same parameter type list as any non-template
+       non-member candidate.  */
+                            
+  if (TREE_CODE (cand1->fn) == IDENTIFIER_NODE
+      || TREE_CODE (cand2->fn) == IDENTIFIER_NODE)
     {
       for (i = 0; i < len; ++i)
        if (!same_type_p (TREE_TYPE (TREE_VEC_ELT (cand1->convs, i)),
                          TREE_TYPE (TREE_VEC_ELT (cand2->convs, i))))
          break;
       if (i == TREE_VEC_LENGTH (cand1->convs))
-       return 1;
+       {
+         if (cand1->fn == cand2->fn)
+           /* Two built-in candidates; arbitrarily pick one.  */
+           return 1;
+         else if (TREE_CODE (cand1->fn) == IDENTIFIER_NODE)
+           /* cand1 is built-in; prefer cand2.  */
+           return -1;
+         else
+           /* cand2 is built-in; prefer cand1.  */
+           return 1;
+       }
 
       /* Kludge around broken overloading rules whereby
         Integer a, b; test ? a : b; is ambiguous, since there's a builtin
         that takes references and another that takes values.  */
-      if (cand1->fn == ansi_opname (COND_EXPR))
+      if (cand1->fn == cand2->fn
+         && cand1->fn == ansi_opname (COND_EXPR))
        {
          tree c1 = TREE_VEC_ELT (cand1->convs, 1);
          tree c2 = TREE_VEC_ELT (cand2->convs, 1);
index 8a6b0ae..d5f10e4 100644 (file)
@@ -3784,7 +3784,6 @@ extern void cplus_decl_attributes         PARAMS ((tree *, tree, tree, int));
 extern tree constructor_name_full              PARAMS ((tree));
 extern tree constructor_name                   PARAMS ((tree));
 extern void defer_fn                           PARAMS ((tree));
-extern tree get_temp_name                      PARAMS ((tree));
 extern void finish_anon_union                  PARAMS ((tree));
 extern tree finish_table                       PARAMS ((tree, tree, tree, int));
 extern void finish_builtin_type                        PARAMS ((tree, const char *,
@@ -4384,6 +4383,7 @@ extern tree mangle_ctor_vtbl_for_type           PARAMS ((tree, tree));
 extern tree mangle_thunk                        PARAMS ((tree, tree, tree));
 extern tree mangle_conv_op_name_for_type        PARAMS ((tree));
 extern tree mangle_guard_variable               PARAMS ((tree));
+extern tree mangle_ref_init_variable            PARAMS ((tree));
 
 /* in dump.c */
 extern int cp_dump_tree                         PARAMS ((dump_info_p, tree));
index 385ad2e..3637cc0 100644 (file)
@@ -37,7 +37,7 @@ Boston, MA 02111-1307, USA.  */
 
 static tree cp_convert_to_pointer PARAMS ((tree, tree, int));
 static tree convert_to_pointer_force PARAMS ((tree, tree));
-static tree build_up_reference PARAMS ((tree, tree, int));
+static tree build_up_reference PARAMS ((tree, tree, int, tree));
 static void warn_ref_binding PARAMS ((tree, tree, tree));
 
 /* Change of width--truncation and extension of integers or reals--
@@ -358,11 +358,12 @@ convert_to_pointer_force (type, expr)
    value we have to begin with is in ARG.
 
    FLAGS controls how we manage access checking.
-   DIRECT_BIND in FLAGS controls how any temporaries are generated.  */
+   DIRECT_BIND in FLAGS controls how any temporaries are generated.
+     If DIRECT_BIND is set, DECL is the reference we're binding to.  */
 
 static tree
-build_up_reference (type, arg, flags)
-     tree type, arg;
+build_up_reference (type, arg, flags, decl)
+     tree type, arg, decl;
      int flags;
 {
   tree rval;
@@ -374,15 +375,28 @@ build_up_reference (type, arg, flags)
 
   if ((flags & DIRECT_BIND) && ! real_lvalue_p (arg))
     {
-      /* Create a new temporary variable.  */
+      /* Create a new temporary variable.  We can't just use a TARGET_EXPR
+        here because it needs to live as long as DECL.  */
       tree targ = arg;
-      if (toplevel_bindings_p ())
-       arg = get_temp_name (argtype);
+
+      arg = build_decl (VAR_DECL, NULL_TREE, argtype);
+      DECL_ARTIFICIAL (arg) = 1;
+      TREE_USED (arg) = 1;
+      TREE_STATIC (arg) = TREE_STATIC (decl);
+
+      if (TREE_STATIC (decl))
+       {
+         /* Namespace-scope or local static; give it a mangled name.  */
+         tree name = mangle_ref_init_variable (decl);
+         DECL_NAME (arg) = name;
+         SET_DECL_ASSEMBLER_NAME (arg, name);
+         arg = pushdecl_top_level (arg);
+       }
       else
        {
+         /* automatic; make sure we handle the cleanup properly.  */
          maybe_push_cleanup_level (argtype);
-         arg = pushdecl (build_decl (VAR_DECL, NULL_TREE, argtype));
-         DECL_ARTIFICIAL (arg) = 1;
+         arg = pushdecl (arg);
        }
 
       /* Process the initializer for the declaration.  */
@@ -393,7 +407,7 @@ build_up_reference (type, arg, flags)
   else if (!(flags & DIRECT_BIND) && ! lvalue_p (arg))
     return get_target_expr (arg);
 
-  /* If we had a way to wrap this up, and say, if we ever needed it's
+  /* If we had a way to wrap this up, and say, if we ever needed its
      address, transform all occurrences of the register, into a memory
      reference we could win better.  */
   rval = build_unary_op (ADDR_EXPR, arg, 1);
@@ -531,7 +545,7 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
                        ttr, reftype);
        }
 
-      return build_up_reference (reftype, expr, flags);
+      return build_up_reference (reftype, expr, flags, decl);
     }
   else if ((convtype & CONV_REINTERPRET) && lvalue_p (expr))
     {
@@ -562,7 +576,7 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
       if (rval == NULL_TREE || rval == error_mark_node)
        return rval;
       warn_ref_binding (reftype, intype, decl);
-      rval = build_up_reference (reftype, rval, flags);
+      rval = build_up_reference (reftype, rval, flags, decl);
     }
 
   if (rval)
index c140af4..4bbf2e0 100644 (file)
@@ -7386,14 +7386,7 @@ grok_reference_init (decl, type, init)
   if (TREE_STATIC (decl) && !TREE_CONSTANT (tmp))
     return tmp;
 
-  if (building_stmt_tree ())
-    {
-      /* Initialize the declaration.  */
-      tmp = build (INIT_EXPR, TREE_TYPE (decl), decl, tmp);
-      finish_expr_stmt (tmp);
-    }
-  else
-    DECL_INITIAL (decl) = tmp;
+  DECL_INITIAL (decl) = tmp;
 
   return NULL_TREE;
 }
@@ -8010,17 +8003,16 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
   if (type == error_mark_node)
     return;
 
-  /* Add this declaration to the statement-tree.  */
-  if (building_stmt_tree ()
-      && at_function_scope_p ()
-      && TREE_CODE (decl) != RESULT_DECL)
-    add_decl_stmt (decl);
-
   if (TYPE_HAS_MUTABLE_P (type))
     TREE_READONLY (decl) = 0;
 
   if (processing_template_decl)
     {
+      /* Add this declaration to the statement-tree.  */
+      if (at_function_scope_p ()
+         && TREE_CODE (decl) != RESULT_DECL)
+       add_decl_stmt (decl);
+
       if (init && DECL_INITIAL (decl))
        DECL_INITIAL (decl) = init;
       goto finish_end0;
@@ -8089,6 +8081,12 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
 
   GNU_xref_decl (current_function_decl, decl);
 
+  /* Add this declaration to the statement-tree.  */
+  if (building_stmt_tree ()
+      && at_function_scope_p ()
+      && TREE_CODE (decl) != RESULT_DECL)
+    add_decl_stmt (decl);
+
   if (TREE_CODE (decl) == VAR_DECL)
     layout_var_decl (decl);
 
index d0f8c43..ef419bd 100644 (file)
@@ -1946,41 +1946,6 @@ defer_fn (fn)
   VARRAY_PUSH_TREE (deferred_fns, fn);
 }
 
-/* Hand off a unique name which can be used for variable we don't really
-   want to know about anyway, for example, the anonymous variables which
-   are needed to make references work.  Declare this thing so we can use it.
-   The variable created will be of type TYPE, and will have internal
-   linkage.  */
-
-tree
-get_temp_name (type)
-     tree type;
-{
-  char buf[sizeof (AUTO_TEMP_FORMAT) + 20];
-  tree decl;
-  int toplev = toplevel_bindings_p ();
-
-  sprintf (buf, AUTO_TEMP_FORMAT, global_temp_name_counter++);
-  decl = build_decl (VAR_DECL, get_identifier (buf), type);
-  DECL_ARTIFICIAL (decl) = 1;
-  TREE_USED (decl) = 1;
-  TREE_STATIC (decl) = 1;
-  
-  decl = pushdecl_top_level (decl);
-
-  /* If this is a local variable, then lay out its rtl now.
-     Otherwise, callers of this function are responsible for dealing
-     with this variable's rtl.  */
-  if (! toplev)
-    {
-      expand_decl (decl);
-      my_friendly_assert (DECL_INITIAL (decl) == NULL_TREE,
-                         19990826);
-    }
-
-  return decl;
-}
-
 /* Hunts through the global anonymous union ANON_DECL, building
    appropriate VAR_DECLs.  Stores cleanups on the list of ELEMS, and
    returns a VAR_DECL whose size is the same as the size of the
index 2b1b009..6e94681 100644 (file)
@@ -2420,10 +2420,28 @@ mangle_guard_variable (variable)
 {
   start_mangling ();
   write_string ("_ZGV");
-  write_name (variable, /*ignore_local_scope=*/0);
+  if (strncmp (IDENTIFIER_POINTER (DECL_NAME (variable)), "_ZGR", 4) == 0)
+    /* The name of a guard variable for a reference temporary should refer
+       to the reference, not the temporary.  */
+    write_string (IDENTIFIER_POINTER (DECL_NAME (variable)) + 4);
+  else
+    write_name (variable, /*ignore_local_scope=*/0);
   return get_identifier (finish_mangling ());
 }
 
+/* Return an identifier for the name of a temporary variable used to
+   initialize a static reference.  This isn't part of the ABI, but we might
+   as well call them something readable.  */
+
+tree
+mangle_ref_init_variable (variable)
+     tree variable;
+{
+  start_mangling ();
+  write_string ("_ZGR");
+  write_name (variable, /*ignore_local_scope=*/0);
+  return get_identifier (finish_mangling ());
+}
 \f
 
 /* Foreign language type mangling section.  */
diff --git a/gcc/testsuite/g++.dg/README b/gcc/testsuite/g++.dg/README
new file mode 100644 (file)
index 0000000..318b819
--- /dev/null
@@ -0,0 +1,17 @@
+Subdirectories:
+
+abi     Tests for ABI compatibility -- mangling, object layout, etc.
+eh      Tests for exception handling.
+ext     Tests for GNU language extensions.
+inherit         Tests for inheritance -- virtual functions, multiple inheritance, etc.
+init    Tests for initialization semantics, constructors/destructors, etc.
+lookup  Tests for lookup semantics, namespaces, etc.
+overload Tests for overload resolution and conversions.
+rtti    Tests for run-time type identification (typeid, dynamic_cast, etc.)
+template Tests for templates.
+warn    Tests for compiler warnings.
+
+other   Tests that don't fit into one of the other categories.
+
+special         Tests that need custom expect code to run them; see special/ecos.exp
+        for an example.
diff --git a/gcc/testsuite/g++.dg/overload/builtin1.C b/gcc/testsuite/g++.dg/overload/builtin1.C
new file mode 100644 (file)
index 0000000..9f66e33
--- /dev/null
@@ -0,0 +1,16 @@
+// Test that we don't discard builtin candidates inappropriately.
+
+struct B { };
+
+struct A {
+  operator int ();
+  operator B ();
+};
+
+void operator+ (B, B);         // { dg-error "" "candidate" }
+
+int main ()
+{
+  A a;
+  a + a;                       // { dg-error "" "ambiguous" }
+}