]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/25364 (ICE with function pointer as template parameter)
authorMark Mitchell <mark@codesourcery.com>
Thu, 22 Dec 2005 20:08:39 +0000 (20:08 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Thu, 22 Dec 2005 20:08:39 +0000 (20:08 +0000)
PR c++/25364
* typeck.c (build_unary_op): Pass DECLs not names to
build_offset_refs.
* init.c (build_offset_ref): Do not do name lookup.  Do not call
mark_used.
* call.c (build_call): Simplify and tidy.
* semantics.c (finish_qualified_id_expr): Call mark_used.
PR c++/25364
* g++.dg/template/call4.C: New test.

From-SVN: r108973

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/init.c
gcc/cp/semantics.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/call4.C [new file with mode: 0644]

index 361202edb41b02125a54ccf96221b5e814b8c3da..705edbb57576b893931f0233518ffb679b4568be 100644 (file)
@@ -1,3 +1,13 @@
+2005-12-22  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/25364
+       * typeck.c (build_unary_op): Pass DECLs not names to
+       build_offset_refs.
+       * init.c (build_offset_ref): Do not do name lookup.  Do not call
+       mark_used.
+       * call.c (build_call): Simplify and tidy.
+       * semantics.c (finish_qualified_id_expr): Call mark_used.
+
 2005-12-22  Volker Reichelt  <reichelt@igpm.rwth-aachen.de>
 
        PR c++/23333
index 53040d5e13bbc56bfe6bbe8c9430236dd239f355..f34124085f8bc117749e1ff28be7c71939ecac37 100644 (file)
@@ -284,18 +284,28 @@ build_call (tree function, tree parms)
 
   function = build_addr_func (function);
 
-  if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function)))
-    {
-      sorry ("unable to call pointer to member function here");
-      return error_mark_node;
-    }
-
+  gcc_assert (TYPE_PTR_P (TREE_TYPE (function)));
   fntype = TREE_TYPE (TREE_TYPE (function));
+  gcc_assert (TREE_CODE (fntype) == FUNCTION_TYPE
+             || TREE_CODE (fntype) == METHOD_TYPE);
   result_type = TREE_TYPE (fntype);
 
   if (TREE_CODE (function) == ADDR_EXPR
       && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL)
-    decl = TREE_OPERAND (function, 0);
+    {
+      decl = TREE_OPERAND (function, 0);
+      if (!TREE_USED (decl))
+       {
+         /* We invoke build_call directly for several library
+            functions.  These may have been declared normally if
+            we're building libgcc, so we can't just check
+            DECL_ARTIFICIAL.  */
+         gcc_assert (DECL_ARTIFICIAL (decl)
+                     || !strncmp (IDENTIFIER_POINTER (DECL_NAME (decl)),
+                                  "__", 2));
+         mark_used (decl);
+       }
+    }
   else
     decl = NULL_TREE;
 
@@ -314,17 +324,6 @@ build_call (tree function, tree parms)
   if (decl && DECL_CONSTRUCTOR_P (decl))
     is_constructor = 1;
 
-  if (decl && ! TREE_USED (decl))
-    {
-      /* We invoke build_call directly for several library functions.
-        These may have been declared normally if we're building libgcc,
-        so we can't just check DECL_ARTIFICIAL.  */
-      gcc_assert (DECL_ARTIFICIAL (decl)
-                 || !strncmp (IDENTIFIER_POINTER (DECL_NAME (decl)),
-                              "__", 2));
-      mark_used (decl);
-    }
-
   /* Don't pass empty class objects by value.  This is useful
      for tags in STL, which are used to control overload resolution.
      We don't need to handle other cases of copying empty classes.  */
index f19842dddc1e1add5745bcf6ab6cf04ee37ca287..54b8a08ef7f90246f7d05af0b56153b49c4f282e 100644 (file)
@@ -1332,112 +1332,40 @@ get_type_value (tree name)
    @@ This function should be rewritten and placed in search.c.  */
 
 tree
-build_offset_ref (tree type, tree name, bool address_p)
+build_offset_ref (tree type, tree member, bool address_p)
 {
   tree decl;
-  tree member;
   tree basebinfo = NULL_TREE;
-  tree orig_name = name;
 
   /* class templates can come in as TEMPLATE_DECLs here.  */
-  if (TREE_CODE (name) == TEMPLATE_DECL)
-    return name;
+  if (TREE_CODE (member) == TEMPLATE_DECL)
+    return member;
 
-  if (dependent_type_p (type) || type_dependent_expression_p (name))
-    return build_qualified_name (NULL_TREE, type, name
+  if (dependent_type_p (type) || type_dependent_expression_p (member))
+    return build_qualified_name (NULL_TREE, type, member
                                 /*template_p=*/false);
 
-  if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
-    {
-      /* If the NAME is a TEMPLATE_ID_EXPR, we are looking at
-        something like `a.template f<int>' or the like.  For the most
-        part, we treat this just like a.f.  We do remember, however,
-        the template-id that was used.  */
-      name = TREE_OPERAND (orig_name, 0);
-
-      if (DECL_P (name))
-       name = DECL_NAME (name);
-      else
-       {
-         if (TREE_CODE (name) == COMPONENT_REF)
-           name = TREE_OPERAND (name, 1);
-         if (TREE_CODE (name) == OVERLOAD)
-           name = DECL_NAME (OVL_CURRENT (name));
-       }
-
-      gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
-    }
-
-  if (type == NULL_TREE)
-    return error_mark_node;
-
-  /* Handle namespace names fully here.  */
-  if (TREE_CODE (type) == NAMESPACE_DECL)
-    {
-      tree t = lookup_namespace_name (type, name);
-      if (t == error_mark_node)
-       return t;
-      if (TREE_CODE (orig_name) == TEMPLATE_ID_EXPR)
-       /* Reconstruct the TEMPLATE_ID_EXPR.  */
-       t = build2 (TEMPLATE_ID_EXPR, TREE_TYPE (t),
-                   t, TREE_OPERAND (orig_name, 1));
-      if (! type_unknown_p (t))
-       {
-         mark_used (t);
-         t = convert_from_reference (t);
-       }
-      return t;
-    }
-
+  gcc_assert (TYPE_P (type));
   if (! is_aggr_type (type, 1))
     return error_mark_node;
 
-  if (TREE_CODE (name) == BIT_NOT_EXPR)
-    {
-      if (! check_dtor_name (type, name))
-       error ("qualified type %qT does not match destructor name %<~%T%>",
-                 type, TREE_OPERAND (name, 0));
-      name = dtor_identifier;
-    }
+  gcc_assert (DECL_P (member) || BASELINK_P (member));
+  /* Callers should call mark_used before this point.  */
+  gcc_assert (!DECL_P (member) || TREE_USED (member));
 
   if (!COMPLETE_TYPE_P (complete_type (type))
       && !TYPE_BEING_DEFINED (type))
     {
-      error ("incomplete type %qT does not have member %qD", type, name);
-      return error_mark_node;
-    }
-
-  /* Set up BASEBINFO for member lookup.  */
-  decl = maybe_dummy_object (type, &basebinfo);
-
-  if (BASELINK_P (name) || DECL_P (name))
-    member = name;
-  else
-    {
-      member = lookup_member (basebinfo, name, 1, 0);
-
-      if (member == error_mark_node)
-       return error_mark_node;
-    }
-
-  if (!member)
-    {
-      error ("%qD is not a member of type %qT", name, type);
+      error ("incomplete type %qT does not have member %qD", type, member);
       return error_mark_node;
     }
 
+  /* Entities other than non-static members need no further
+     processing.  */ 
   if (TREE_CODE (member) == TYPE_DECL)
-    {
-      TREE_USED (member) = 1;
-      return member;
-    }
-  /* static class members and class-specific enum
-     values can be returned without further ado.  */
+    return member;
   if (TREE_CODE (member) == VAR_DECL || TREE_CODE (member) == CONST_DECL)
-    {
-      mark_used (member);
-      return convert_from_reference (member);
-    }
+    return convert_from_reference (member);
 
   if (TREE_CODE (member) == FIELD_DECL && DECL_C_BIT_FIELD (member))
     {
@@ -1445,6 +1373,9 @@ build_offset_ref (tree type, tree name, bool address_p)
       return error_mark_node;
     }
 
+  /* Set up BASEBINFO for member lookup.  */
+  decl = maybe_dummy_object (type, &basebinfo);
+
   /* A lot of this logic is now handled in lookup_member.  */
   if (BASELINK_P (member))
     {
@@ -1452,29 +1383,6 @@ build_offset_ref (tree type, tree name, bool address_p)
       tree fnfields = member;
       tree t = BASELINK_FUNCTIONS (fnfields);
 
-      if (TREE_CODE (orig_name) == TEMPLATE_ID_EXPR)
-       {
-         /* The FNFIELDS are going to contain functions that aren't
-            necessarily templates, and templates that don't
-            necessarily match the explicit template parameters.  We
-            save all the functions, and the explicit parameters, and
-            then figure out exactly what to instantiate with what
-            arguments in instantiate_type.  */
-
-         if (TREE_CODE (t) != OVERLOAD)
-           /* The code in instantiate_type which will process this
-              expects to encounter OVERLOADs, not raw functions.  */
-           t = ovl_cons (t, NULL_TREE);
-
-         t = build2 (TEMPLATE_ID_EXPR, TREE_TYPE (t), t,
-                     TREE_OPERAND (orig_name, 1));
-         t = build2 (OFFSET_REF, unknown_type_node, decl, t);
-
-         PTRMEM_OK_P (t) = 1;
-
-         return t;
-       }
-
       if (TREE_CODE (t) != TEMPLATE_ID_EXPR && !really_overloaded_fn (t))
        {
          /* Get rid of a potential OVERLOAD around it.  */
@@ -1494,7 +1402,6 @@ build_offset_ref (tree type, tree name, bool address_p)
          else
            perform_or_defer_access_check (basebinfo, t);
 
-         mark_used (t);
          if (DECL_STATIC_FUNCTION_P (t))
            return t;
          member = t;
index 0b6532590934c154f5ba23122cb6b7abf2092b83..a200bf4eae0afa2e3a0843460475e596ce9d86aa 100644 (file)
@@ -1508,9 +1508,18 @@ finish_qualified_id_expr (tree qualifying_class,
                          bool template_p,
                          bool template_arg_p)
 {
+  gcc_assert (TYPE_P (qualifying_class));
+
   if (error_operand_p (expr))
     return error_mark_node;
 
+  if (DECL_P (expr))
+    mark_used (expr);
+  else if (BASELINK_P (expr)
+          && TREE_CODE (BASELINK_FUNCTIONS (expr)) != TEMPLATE_ID_EXPR
+          && !really_overloaded_fn (BASELINK_FUNCTIONS (expr)))
+    mark_used (OVL_CURRENT (BASELINK_FUNCTIONS (expr)));
+
   if (template_p)
     check_template_keyword (expr);
 
index 0cae93807107e1bbf884ea410db976951e7f664b..827b3e59b0f916c3275ed487d23f8540c1789e6d 100644 (file)
@@ -4117,10 +4117,11 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
             is used here to remove this const from the diagnostics
             and the created OFFSET_REF.  */
          tree base = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg, 0)));
-         tree name = DECL_NAME (get_first_fn (TREE_OPERAND (arg, 1)));
+         tree fn = get_first_fn (TREE_OPERAND (arg, 1));
 
          if (! flag_ms_extensions)
            {
+             tree name = DECL_NAME (fn);
              if (current_class_type
                  && TREE_OPERAND (arg, 0) == current_class_ref)
                /* An expression like &memfn.  */
@@ -4134,7 +4135,7 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
                         "  Say %<&%T::%D%>",
                         base, name);
            }
-         arg = build_offset_ref (base, name, /*address_p=*/true);
+         arg = build_offset_ref (base, fn, /*address_p=*/true);
        }
 
     offset_ref:
index ebeb40a640125c9bbd810524a3d5504405689981..dcf9b71c928eceef76bd8f2ac0594648e1f49b15 100644 (file)
@@ -1,3 +1,8 @@
+2005-12-22  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/25364
+       * g++.dg/template/call4.C: New test.
+
 2005-12-22  Dale Johannesen  <dalej@apple.com>
 
        * gcc.target/i386/sse-17.c:  New.
diff --git a/gcc/testsuite/g++.dg/template/call4.C b/gcc/testsuite/g++.dg/template/call4.C
new file mode 100644 (file)
index 0000000..1f7eb4c
--- /dev/null
@@ -0,0 +1,21 @@
+// PR c++/25364
+
+class OFX_PropertySuiteV1
+{
+  static int propGetDouble ();
+};
+template<int dimension,
+        class T,
+        int (*PROPGET)()
+  >
+struct OFX_AnimatedNumberParam
+{
+  virtual int paramSetValueAtTime()
+  {
+    return PROPGET();
+  }
+};
+void  f()
+{
+  new OFX_AnimatedNumberParam<2,double,OFX_PropertySuiteV1::propGetDouble>();
+}