re PR c++/11788 (missing implicit instantiation of static member function)
authorNathan Sidwell <nathan@codesourcery.com>
Thu, 11 Sep 2003 15:18:52 +0000 (15:18 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Thu, 11 Sep 2003 15:18:52 +0000 (15:18 +0000)
cp:
PR c++/11788
* typeck.c (build_address): If it is a function, mark it used.
(build_unary_op): Do not lose object's side-effects when taking
address of static member function.
* class.c (resolve_address_of_overloaded_function): Use
tsubst_flags_t parameter. Only expect overload sets. Adjust.
(instantiate_type): Adjust flags passing. Do not lose object's
side-effects when taking address of static member function.
testsuite:
PR c++/11788
* g++.dg/overload/addr1.C: New test.

From-SVN: r71304

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/overload/addr1.C [new file with mode: 0644]

index 5c123b97bcb78e3f3070097b5a834c07d67cad22..2f3461a254c99106d0a87bfe7c4c3850c31e573b 100644 (file)
@@ -1,3 +1,14 @@
+2003-09-10  Nathan Sidwell  <nathan@codesourcery.com>
+
+       PR c++/11788
+       * typeck.c (build_address): If it is a function, mark it used.
+       (build_unary_op): Do not lose object's side-effects when taking
+       address of static member function.
+       * class.c (resolve_address_of_overloaded_function): Use
+       tsubst_flags_t parameter. Only expect overload sets. Adjust.
+       (instantiate_type): Adjust flags passing. Do not lose object's
+       side-effects when taking address of static member function.
+
 2003-09-11  Richard Henderson  <rth@redhat.com>
 
        * semantics.c (expand_or_defer_fn): Update for new
index d17ff5ad0b72d8d6e49e25d150fa3500c45654a2..485e9ad3f6886c9867149fc0c86a44094805a39e 100644 (file)
@@ -129,8 +129,8 @@ static int method_name_cmp (const void *, const void *);
 static int resort_method_name_cmp (const void *, const void *);
 static void add_implicitly_declared_members (tree, int, int, int);
 static tree fixed_type_or_null (tree, int *, int *);
-static tree resolve_address_of_overloaded_function (tree, tree, int,
-                                                         int, int, tree);
+static tree resolve_address_of_overloaded_function (tree, tree, tsubst_flags_t,
+                                                   bool, tree);
 static tree build_vtbl_ref_1 (tree, tree);
 static tree build_vtbl_initializer (tree, tree, tree, tree, int *);
 static int count_fields (tree);
@@ -5675,18 +5675,17 @@ pop_lang_context (void)
 
 /* Given an OVERLOAD and a TARGET_TYPE, return the function that
    matches the TARGET_TYPE.  If there is no satisfactory match, return
-   error_mark_node, and issue an error message if COMPLAIN is
-   nonzero.  Permit pointers to member function if PTRMEM is nonzero.
-   If TEMPLATE_ONLY, the name of the overloaded function
-   was a template-id, and EXPLICIT_TARGS are the explicitly provided
+   error_mark_node, and issue a error & warning messages under control
+   of FLAGS.  Permit pointers to member function if FLAGS permits.  If
+   TEMPLATE_ONLY, the name of the overloaded function was a
+   template-id, and EXPLICIT_TARGS are the explicitly provided
    template arguments.  */
 
 static tree
 resolve_address_of_overloaded_function (tree target_type, 
                                        tree overload,
-                                       int complain,
-                                       int ptrmem,
-                                       int template_only,
+                                       tsubst_flags_t flags,
+                                       bool template_only,
                                        tree explicit_targs)
 {
   /* Here's what the standard says:
@@ -5730,9 +5729,8 @@ resolve_address_of_overloaded_function (tree target_type,
                        && (TREE_CODE (TREE_TYPE (target_type)) 
                            == METHOD_TYPE)), 0);
 
-  if (TREE_CODE (overload) == COMPONENT_REF)
-    overload = TREE_OPERAND (overload, 1);
-
+  my_friendly_assert (is_overloaded_fn (overload), 20030910);
+  
   /* Check that the TARGET_TYPE is reasonable.  */
   if (TYPE_PTRFN_P (target_type))
     /* This is OK.  */;
@@ -5748,7 +5746,7 @@ resolve_address_of_overloaded_function (tree target_type,
     }
   else 
     {
-      if (complain)
+      if (flags & tf_error)
        error ("\
 cannot resolve overloaded function `%D' based on conversion to type `%T'", 
                  DECL_NAME (OVL_FUNCTION (overload)), target_type);
@@ -5842,8 +5840,7 @@ cannot resolve overloaded function `%D' based on conversion to type `%T'",
            continue;
 
          /* Instantiate the template.  */
-         instantiation = instantiate_template (fn, targs,
-                                               complain ? tf_error : tf_none);
+         instantiation = instantiate_template (fn, targs, flags);
          if (instantiation == error_mark_node)
            /* Instantiation failed.  */
            continue;
@@ -5873,7 +5870,7 @@ cannot resolve overloaded function `%D' based on conversion to type `%T'",
   if (matches == NULL_TREE)
     {
       /* There were *no* matches.  */
-      if (complain)
+      if (flags & tf_error)
        {
          error ("no matches converting function `%D' to type `%#T'", 
                    DECL_NAME (OVL_FUNCTION (overload)),
@@ -5894,7 +5891,7 @@ cannot resolve overloaded function `%D' based on conversion to type `%T'",
     {
       /* There were too many matches.  */
 
-      if (complain)
+      if (flags & tf_error)
        {
          tree match;
 
@@ -5917,11 +5914,11 @@ cannot resolve overloaded function `%D' based on conversion to type `%T'",
   fn = TREE_PURPOSE (matches);
 
   if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
-      && !ptrmem && !flag_ms_extensions)
+      && !(flags & tf_ptrmem_ok) && !flag_ms_extensions)
     {
       static int explained;
       
-      if (!complain)
+      if (!(flags & tf_error))
         return error_mark_node;
 
       pedwarn ("assuming pointer to member `%D'", fn);
@@ -5948,7 +5945,7 @@ cannot resolve overloaded function `%D' based on conversion to type `%T'",
 
 /* This function will instantiate the type of the expression given in
    RHS to match the type of LHSTYPE.  If errors exist, then return
-   error_mark_node. FLAGS is a bit mask.  If ITF_COMPLAIN is set, then
+   error_mark_node. FLAGS is a bit mask.  If TF_ERROR is set, then
    we complain on errors.  If we are not complaining, never modify rhs,
    as overload resolution wants to try many possible instantiations, in
    the hope that at least one will work.
@@ -5959,14 +5956,13 @@ cannot resolve overloaded function `%D' based on conversion to type `%T'",
 tree
 instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
 {
-  int complain = (flags & tf_error);
-  int allow_ptrmem = flags & tf_ptrmem_ok;
+  tsubst_flags_t flags_in = flags;
   
   flags &= ~tf_ptrmem_ok;
   
   if (TREE_CODE (lhstype) == UNKNOWN_TYPE)
     {
-      if (complain)
+      if (flags & tf_error)
        error ("not enough type information");
       return error_mark_node;
     }
@@ -5983,7 +5979,7 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
        ;
       else
        {
-         if (complain)
+         if (flags & tf_error)
            error ("argument of type `%T' does not match `%T'",
                   TREE_TYPE (rhs), lhstype);
          return error_mark_node;
@@ -6034,13 +6030,21 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
       return instantiate_type (lhstype, rhs, flags);
 
     case COMPONENT_REF:
-      return instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
+      {
+       tree addr = instantiate_type (lhstype, TREE_OPERAND (rhs, 1), flags);
+
+       if (addr != error_mark_node
+           && TREE_SIDE_EFFECTS (TREE_OPERAND (rhs, 0)))
+         /* Do not lose object's side effects. */
+         addr = build (COMPOUND_EXPR, TREE_TYPE (addr),
+                       TREE_OPERAND (rhs, 0), addr);
+       return addr;
+      }
 
     case OFFSET_REF:
       rhs = TREE_OPERAND (rhs, 1);
       if (BASELINK_P (rhs))
-       return instantiate_type (lhstype, BASELINK_FUNCTIONS (rhs),
-                                flags | allow_ptrmem);
+       return instantiate_type (lhstype, BASELINK_FUNCTIONS (rhs), flags_in);
 
       /* This can happen if we are forming a pointer-to-member for a
         member template.  */
@@ -6054,22 +6058,16 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
        tree args = TREE_OPERAND (rhs, 1);
 
        return
-         resolve_address_of_overloaded_function (lhstype,
-                                                 fns,
-                                                 complain,
-                                                 allow_ptrmem,
-                                                 /*template_only=*/1,
+         resolve_address_of_overloaded_function (lhstype, fns, flags_in,
+                                                 /*template_only=*/true,
                                                  args);
       }
 
     case OVERLOAD:
     case FUNCTION_DECL:
       return 
-       resolve_address_of_overloaded_function (lhstype, 
-                                               rhs,
-                                               complain,
-                                               allow_ptrmem,
-                                               /*template_only=*/0,
+       resolve_address_of_overloaded_function (lhstype, rhs, flags_in,
+                                               /*template_only=*/false,
                                                /*explicit_targs=*/NULL_TREE);
 
     case TREE_LIST:
@@ -6131,7 +6129,7 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
     case PREDECREMENT_EXPR:
     case POSTINCREMENT_EXPR:
     case POSTDECREMENT_EXPR:
-      if (complain)
+      if (flags & tf_error)
        error ("invalid operation on uninstantiated type");
       return error_mark_node;
 
@@ -6147,14 +6145,14 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
     case TRUTH_ANDIF_EXPR:
     case TRUTH_ORIF_EXPR:
     case TRUTH_NOT_EXPR:
-      if (complain)
+      if (flags & tf_error)
        error ("not enough type information");
       return error_mark_node;
 
     case COND_EXPR:
       if (type_unknown_p (TREE_OPERAND (rhs, 0)))
        {
-         if (complain)
+         if (flags & tf_error)
            error ("not enough type information");
          return error_mark_node;
        }
index 8b391b8448d8513b1e340f3b303fb1808152a2ba..32ec44b46792161b447d88f66ef2777351f5433d 100644 (file)
@@ -3581,9 +3581,7 @@ build_address (tree t)
   if (error_operand_p (t) || !cxx_mark_addressable (t))
     return error_mark_node;
 
-  addr = build1 (ADDR_EXPR, 
-                build_pointer_type (TREE_TYPE (t)),
-                t);
+  addr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);
   if (staticp (t))
     TREE_CONSTANT (addr) = 1;
 
@@ -4003,12 +4001,24 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
       {
        tree addr;
 
-       if (TREE_CODE (arg) == COMPONENT_REF
-           && TREE_CODE (TREE_OPERAND (arg, 1)) == BASELINK)
-         arg = BASELINK_FUNCTIONS (TREE_OPERAND (arg, 1));
-
        if (TREE_CODE (arg) != COMPONENT_REF)
          addr = build_address (arg);
+       else if (TREE_CODE (TREE_OPERAND (arg, 1)) == BASELINK)
+         {
+           tree fn = BASELINK_FUNCTIONS (TREE_OPERAND (arg, 1));
+
+           /* We can only get here with a single static member
+              function.  */
+           my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL
+                               && DECL_STATIC_FUNCTION_P (fn),
+                               20030906);
+           mark_used (fn);
+           addr = build_address (fn);
+           if (TREE_SIDE_EFFECTS (TREE_OPERAND (arg, 0)))
+             /* Do not lose object's side effects.  */
+             addr = build (COMPOUND_EXPR, TREE_TYPE (addr),
+                           TREE_OPERAND (arg, 0), addr);
+         }
        else if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)))
          {
            error ("attempt to take address of bit-field structure member `%D'",
index f1d670b0b2b35406ec9fd1f5fc5bc0092a2092ca..4d0d6fe916d51122b7e8088df5f311f61ab6bd62 100644 (file)
@@ -1,3 +1,8 @@
+2003-09-11  Nathan Sidwell  <nathan@codesourcery.com>
+
+       PR c++/11788
+       * g++.dg/overload/addr1.C: New test.
+
 2003-09-10  Ian Lance Taylor  <ian@wasabisystems.com>
 
        * gcc.dg/20030909-1.c: New test.
diff --git a/gcc/testsuite/g++.dg/overload/addr1.C b/gcc/testsuite/g++.dg/overload/addr1.C
new file mode 100644 (file)
index 0000000..25856a2
--- /dev/null
@@ -0,0 +1,50 @@
+// { dg-do run }
+
+// Copyright (C) 2003 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 6 Sep 2003 <nathan@codesourcery.com>
+// Origin: Volker Reichelt <reichelt@igpm.rwth-aachen.de>
+
+// PR c++/11788 we failed to instantiate a decl, and we lost some side
+// effects
+
+static int flag = 0;
+
+template <typename> struct A
+{
+  A &active ()  { flag++;}
+  
+  static void foo() {}
+
+  static void bar () {}
+  static void bar (int) {}
+
+  int m;
+};
+
+void (*baz ()) ()
+{
+    A<int> a;
+    return &a.active ().foo;
+}
+
+void (*boz ()) ()
+{
+    A<int> a;
+    return &a.active ().bar;
+}
+
+int *buz ()
+{
+  A<int> a;
+  
+  return &a.active ().m;
+}
+
+int main ()
+{
+  baz ();
+  boz ();
+  buz ();
+  
+  return flag != 3;
+}