This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH: PR 25364


This patch fixes PR 25364, an ICE-on-valid regression.  The ICE comes
from an assert in a low-level routine (build_call) which is checking
that the function being called has already been passed to mark_used.
The point is that mark_used should be called as soon as name lookup
has been resolved and the front end has determined that the thing in
question has in fact been used.

The key part of this patch is, therefore, calling mark_used in
finish_qualified_id_expr, and that's the bit that I've applied to the
4.0 and 4.1 branches.  However, for mainline, I took the opportunity
to remove a bunch of unncessary cruft in build_offset_ref.  (This is
another dividend from the "new" parser, which eliminated a lot of the
weird recovery paths we used to need.)  I also eliminated a spurious
use of name lookup; build_unary_op was asking build_offset_ref to do
name lookup even though build_unary_op already knew what the result of
the lookup would be.

Tested on x86_64-unknown-linux-gnu, applied on the mainline, and the
much more limited change to the 4.0, and 4.1 branches.

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

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  Mark Mitchell  <mark@codesourcery.com>

	PR c++/25364
	* g++.dg/template/call4.C: New test.

Index: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c	(revision 108836)
+++ gcc/cp/typeck.c	(working copy)
@@ -4117,10 +4117,11 @@ build_unary_op (enum tree_code code, tre
 	     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, tre
 			 "  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: gcc/cp/init.c
===================================================================
--- gcc/cp/init.c	(revision 108840)
+++ gcc/cp/init.c	(working copy)
@@ -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, 
       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, 
       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, 
 	  else
 	    perform_or_defer_access_check (basebinfo, t);
 
-	  mark_used (t);
 	  if (DECL_STATIC_FUNCTION_P (t))
 	    return t;
 	  member = t;
Index: gcc/cp/call.c
===================================================================
--- gcc/cp/call.c	(revision 108836)
+++ gcc/cp/call.c	(working copy)
@@ -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: gcc/cp/semantics.c
===================================================================
--- gcc/cp/semantics.c	(revision 108836)
+++ gcc/cp/semantics.c	(working copy)
@@ -1508,9 +1508,18 @@ finish_qualified_id_expr (tree qualifyin
 			  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: gcc/testsuite/g++.dg/template/call4.C
===================================================================
--- gcc/testsuite/g++.dg/template/call4.C	(revision 0)
+++ gcc/testsuite/g++.dg/template/call4.C	(revision 0)
@@ -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>();
+}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]