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 16965


This patch fixes PR c++/16965, which is a case of an inferior error
message with the new C++ parser: the parser failed to distinguish
between an ambiguous lookup and a totally undeclared name.

Tested on i686-pc-linux-gnu, applied on the mainline.

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

2004-08-17  Mark Mitchell  <mark@codesourcery.com>

	PR c++/16965
	* cp-tree.h (qualified_name_lookup_error): Add parameter.
	* name-lookup.c (do_class_using_decl): Restrict set of entities
	passed to cp_emit_debug_info_for_using more carefully.
	(lookup_qualified_name): Allow lookup_member to return sets of
	ambiguous entries.
	* parser.c (cp_parser_lookup_name): Add ambiguous_p parameter.
	(cp_parser_primary_expression): Handle ambiguous lookups.
	(cp_parser_template_name): Adjust use of cp_parser_lookup_name.
	(cp_parser_template_argument): Likewise.
	(cp_parser_elaborate_type_specifier): Likewise.
	(cp_parser_namespace_name): Likewise.
	(cp_parser_class_name): Likewise.
	(cp_parser_lookup_name_simple): Likewise.
	* pt.c (tsubst_qualified_id): Handle ambiguous results.
	(tsubst_expr): Likewise.
	* semantics.c (qualified_name_lookup_error): Add decl paramter.
	For ambiguous lookups, print candidates.

2004-08-17  Mark Mitchell  <mark@codesourcery.com>

	PR c++/16965
	* g++.dg/parse/error17.C: New test.
	
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.1030
diff -c -5 -p -r1.1030 cp-tree.h
*** cp/cp-tree.h	16 Aug 2004 14:29:24 -0000	1.1030
--- cp/cp-tree.h	17 Aug 2004 17:31:08 -0000
*************** extern void finish_default_args         
*** 4164,4174 ****
  extern void finish_template_decl                (tree);
  extern tree finish_template_type                (tree, tree, int);
  extern tree finish_base_specifier               (tree, tree, bool);
  extern void finish_member_declaration           (tree);
  extern void check_multiple_declarators          (void);
! extern void qualified_name_lookup_error		(tree, tree);
  extern tree finish_id_expression                (tree, tree, tree,
  						 cp_id_kind *, tree *,
  						 bool, bool, bool *, 
  						 const char **);
  extern tree finish_typeof			(tree);
--- 4164,4174 ----
  extern void finish_template_decl                (tree);
  extern tree finish_template_type                (tree, tree, int);
  extern tree finish_base_specifier               (tree, tree, bool);
  extern void finish_member_declaration           (tree);
  extern void check_multiple_declarators          (void);
! extern void qualified_name_lookup_error		(tree, tree, tree);
  extern tree finish_id_expression                (tree, tree, tree,
  						 cp_id_kind *, tree *,
  						 bool, bool, bool *, 
  						 const char **);
  extern tree finish_typeof			(tree);
Index: cp/name-lookup.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/name-lookup.c,v
retrieving revision 1.81
diff -c -5 -p -r1.81 name-lookup.c
*** cp/name-lookup.c	2 Aug 2004 18:49:06 -0000	1.81
--- cp/name-lookup.c	17 Aug 2004 17:31:08 -0000
*************** do_class_using_decl (tree decl)
*** 2951,2961 ****
    if (scope && !processing_template_decl)
      {
        tree r;
  
        r = lookup_qualified_name (scope, name, false, false);
!       if (r && TREE_CODE (r) != ERROR_MARK)
  	cp_emit_debug_info_for_using (r, scope);
      }
    return value;
  }
  
--- 2951,2961 ----
    if (scope && !processing_template_decl)
      {
        tree r;
  
        r = lookup_qualified_name (scope, name, false, false);
!       if (r && (DECL_P (r) || TREE_CODE (r) == OVERLOAD))
  	cp_emit_debug_info_for_using (r, scope);
      }
    return value;
  }
  
*************** unqualified_namespace_lookup (tree name,
*** 3811,3821 ****
     or a class TYPE).  If IS_TYPE_P is TRUE, then ignore non-type
     bindings.  
  
     Returns a DECL (or OVERLOAD, or BASELINK) representing the
     declaration found.  If no suitable declaration can be found,
!    ERROR_MARK_NODE is returned.  Iif COMPLAIN is true and SCOPE is
     neither a class-type nor a namespace a diagnostic is issued.  */
  
  tree
  lookup_qualified_name (tree scope, tree name, bool is_type_p, bool complain)
  {
--- 3811,3821 ----
     or a class TYPE).  If IS_TYPE_P is TRUE, then ignore non-type
     bindings.  
  
     Returns a DECL (or OVERLOAD, or BASELINK) representing the
     declaration found.  If no suitable declaration can be found,
!    ERROR_MARK_NODE is returned.  If COMPLAIN is true and SCOPE is
     neither a class-type nor a namespace a diagnostic is issued.  */
  
  tree
  lookup_qualified_name (tree scope, tree name, bool is_type_p, bool complain)
  {
*************** lookup_qualified_name (tree scope, tree 
*** 3832,3842 ****
  	return select_decl (&binding, flags);
      }
    else if (is_aggr_type (scope, complain))
      {
        tree t;
!       t = lookup_member (scope, name, 0, is_type_p);
        if (t)
  	return t;
      }
  
    return error_mark_node;
--- 3832,3842 ----
  	return select_decl (&binding, flags);
      }
    else if (is_aggr_type (scope, complain))
      {
        tree t;
!       t = lookup_member (scope, name, 2, is_type_p);
        if (t)
  	return t;
      }
  
    return error_mark_node;
Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.236
diff -c -5 -p -r1.236 parser.c
*** cp/parser.c	12 Aug 2004 09:34:14 -0000	1.236
--- cp/parser.c	17 Aug 2004 17:31:08 -0000
*************** static void cp_parser_label_declaration
*** 1829,1839 ****
    (cp_parser *);
  
  /* Utility Routines */
  
  static tree cp_parser_lookup_name
!   (cp_parser *, tree, bool, bool, bool, bool);
  static tree cp_parser_lookup_name_simple
    (cp_parser *, tree);
  static tree cp_parser_maybe_treat_template_as_class
    (tree, bool);
  static bool cp_parser_check_declarator_template_parameters
--- 1829,1839 ----
    (cp_parser *);
  
  /* Utility Routines */
  
  static tree cp_parser_lookup_name
!   (cp_parser *, tree, bool, bool, bool, bool, bool *);
  static tree cp_parser_lookup_name_simple
    (cp_parser *, tree);
  static tree cp_parser_maybe_treat_template_as_class
    (tree, bool);
  static bool cp_parser_check_declarator_template_parameters
*************** cp_parser_primary_expression (cp_parser 
*** 2903,2913 ****
  	    || TREE_CODE (id_expression) == TYPE_DECL)
  	  decl = id_expression;
  	/* Look up the name.  */
  	else
  	  {
! 	    decl = cp_parser_lookup_name_simple (parser, id_expression);
  	    /* If name lookup gives us a SCOPE_REF, then the
  	       qualifying scope was dependent.  Just propagate the
  	       name.  */
  	    if (TREE_CODE (decl) == SCOPE_REF)
  	      {
--- 2903,2924 ----
  	    || TREE_CODE (id_expression) == TYPE_DECL)
  	  decl = id_expression;
  	/* Look up the name.  */
  	else
  	  {
! 	    bool ambiguous_p;
! 
! 	    decl = cp_parser_lookup_name (parser, id_expression,
! 					  /*is_type=*/false,
! 					  /*is_template=*/false,
! 					  /*is_namespace=*/false,
! 					  /*check_dependency=*/true,
! 					  &ambiguous_p);
! 	    /* If the lookup was ambiguous, an error will already have
! 	       been issued.  */
! 	    if (ambiguous_p)
! 	      return error_mark_node;
  	    /* If name lookup gives us a SCOPE_REF, then the
  	       qualifying scope was dependent.  Just propagate the
  	       name.  */
  	    if (TREE_CODE (decl) == SCOPE_REF)
  	      {
*************** cp_parser_type_parameter (cp_parser* par
*** 8329,8339 ****
  	      default_argument
  		= cp_parser_lookup_name (parser, default_argument,
  					/*is_type=*/false,
  					/*is_template=*/is_template,
  					/*is_namespace=*/false,
! 					/*check_dependency=*/true);
  	    /* See if the default argument is valid.  */
  	    default_argument
  	      = check_template_template_default_arg (default_argument);
  	  }
  	else
--- 8340,8351 ----
  	      default_argument
  		= cp_parser_lookup_name (parser, default_argument,
  					/*is_type=*/false,
  					/*is_template=*/is_template,
  					/*is_namespace=*/false,
! 					/*check_dependency=*/true,
! 					/*ambiguous_p=*/NULL);
  	    /* See if the default argument is valid.  */
  	    default_argument
  	      = check_template_template_default_arg (default_argument);
  	  }
  	else
*************** cp_parser_template_name (cp_parser* pars
*** 8708,8718 ****
    /* Look up the name.  */
    decl = cp_parser_lookup_name (parser, identifier,
  				/*is_type=*/false,
  				/*is_template=*/false,
  				/*is_namespace=*/false,
! 				check_dependency_p);
    decl = maybe_get_template_decl_from_type_decl (decl);
  
    /* If DECL is a template, then the name was a template-name.  */
    if (TREE_CODE (decl) == TEMPLATE_DECL)
      ;
--- 8720,8731 ----
    /* Look up the name.  */
    decl = cp_parser_lookup_name (parser, identifier,
  				/*is_type=*/false,
  				/*is_template=*/false,
  				/*is_namespace=*/false,
! 				check_dependency_p,
! 				/*ambiguous_p=*/NULL);
    decl = maybe_get_template_decl_from_type_decl (decl);
  
    /* If DECL is a template, then the name was a template-name.  */
    if (TREE_CODE (decl) == TEMPLATE_DECL)
      ;
*************** cp_parser_template_argument (cp_parser* 
*** 8898,8908 ****
        if (TREE_CODE (argument) != TYPE_DECL)
  	argument = cp_parser_lookup_name (parser, argument,
  					  /*is_type=*/false,
  					  /*is_template=*/template_p,
  					  /*is_namespace=*/false,
! 					  /*check_dependency=*/true);
        if (TREE_CODE (argument) != TEMPLATE_DECL
  	  && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
  	cp_parser_error (parser, "expected template-name");
      }
    if (cp_parser_parse_definitely (parser))
--- 8911,8922 ----
        if (TREE_CODE (argument) != TYPE_DECL)
  	argument = cp_parser_lookup_name (parser, argument,
  					  /*is_type=*/false,
  					  /*is_template=*/template_p,
  					  /*is_namespace=*/false,
! 					  /*check_dependency=*/true,
! 					  /*ambiguous_p=*/NULL);
        if (TREE_CODE (argument) != TEMPLATE_DECL
  	  && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
  	cp_parser_error (parser, "expected template-name");
      }
    if (cp_parser_parse_definitely (parser))
*************** cp_parser_elaborated_type_specifier (cp_
*** 9751,9761 ****
  	     cp_parser_lookup_name.  */
  	  decl = cp_parser_lookup_name (parser, identifier,
  					/*is_type=*/true,
  					/*is_template=*/false,
  					/*is_namespace=*/false,
! 					/*check_dependency=*/true);
  
  	  /* If we are parsing friend declaration, DECL may be a
  	     TEMPLATE_DECL tree node here.  However, we need to check
  	     whether this TEMPLATE_DECL results in valid code.  Consider
  	     the following example:
--- 9765,9776 ----
  	     cp_parser_lookup_name.  */
  	  decl = cp_parser_lookup_name (parser, identifier,
  					/*is_type=*/true,
  					/*is_template=*/false,
  					/*is_namespace=*/false,
! 					/*check_dependency=*/true,
! 					/*ambiguous_p=*/NULL);
  
  	  /* If we are parsing friend declaration, DECL may be a
  	     TEMPLATE_DECL tree node here.  However, we need to check
  	     whether this TEMPLATE_DECL results in valid code.  Consider
  	     the following example:
*************** cp_parser_namespace_name (cp_parser* par
*** 10027,10037 ****
       operator.)  */
    namespace_decl = cp_parser_lookup_name (parser, identifier,
  					  /*is_type=*/false,
  					  /*is_template=*/false,
  					  /*is_namespace=*/true,
! 					  /*check_dependency=*/true);
    /* If it's not a namespace, issue an error.  */
    if (namespace_decl == error_mark_node
        || TREE_CODE (namespace_decl) != NAMESPACE_DECL)
      {
        cp_parser_error (parser, "expected namespace-name");
--- 10042,10053 ----
       operator.)  */
    namespace_decl = cp_parser_lookup_name (parser, identifier,
  					  /*is_type=*/false,
  					  /*is_template=*/false,
  					  /*is_namespace=*/true,
! 					  /*check_dependency=*/true,
! 					  /*ambiguous_p=*/NULL);
    /* If it's not a namespace, issue an error.  */
    if (namespace_decl == error_mark_node
        || TREE_CODE (namespace_decl) != NAMESPACE_DECL)
      {
        cp_parser_error (parser, "expected namespace-name");
*************** cp_parser_class_name (cp_parser *parser,
*** 12237,12247 ****
  	  /* Look up the name.  */
  	  decl = cp_parser_lookup_name (parser, identifier,
  					type_p,
  					/*is_template=*/false,
  					/*is_namespace=*/false,
! 					check_dependency_p);
  	}
      }
    else
      {
        /* Try a template-id.  */
--- 12253,12264 ----
  	  /* Look up the name.  */
  	  decl = cp_parser_lookup_name (parser, identifier,
  					type_p,
  					/*is_template=*/false,
  					/*is_namespace=*/false,
! 					check_dependency_p,
! 					/*ambiguous_p=*/NULL);
  	}
      }
    else
      {
        /* Try a template-id.  */
*************** cp_parser_label_declaration (cp_parser* 
*** 14119,14138 ****
  
     If IS_NAMESPACE is TRUE, bindings that do not refer to namespaces
     are ignored.
  
     If CHECK_DEPENDENCY is TRUE, names are not looked up in dependent
!    types.  */
  
  static tree
  cp_parser_lookup_name (cp_parser *parser, tree name,
  		       bool is_type, bool is_template, bool is_namespace,
! 		       bool check_dependency)
  {
    tree decl;
    tree object_type = parser->context->object_type;
  
    /* Now that we have looked up the name, the OBJECT_TYPE (if any) is
       no longer valid.  Note that if we are parsing tentatively, and
       the parse fails, OBJECT_TYPE will be automatically restored.  */
    parser->context->object_type = NULL_TREE;
  
--- 14136,14163 ----
  
     If IS_NAMESPACE is TRUE, bindings that do not refer to namespaces
     are ignored.
  
     If CHECK_DEPENDENCY is TRUE, names are not looked up in dependent
!    types.  
! 
!    If AMBIGUOUS_P is non-NULL, it is set to true if name-lookup
!    results in an ambiguity, and false otherwise.  */
  
  static tree
  cp_parser_lookup_name (cp_parser *parser, tree name,
  		       bool is_type, bool is_template, bool is_namespace,
! 		       bool check_dependency,
! 		       bool *ambiguous_p)
  {
    tree decl;
    tree object_type = parser->context->object_type;
  
+   /* Assume that the lookup will be unambiguous.  */
+   if (ambiguous_p)
+     *ambiguous_p = false;
+ 
    /* Now that we have looked up the name, the OBJECT_TYPE (if any) is
       no longer valid.  Note that if we are parsing tentatively, and
       the parse fails, OBJECT_TYPE will be automatically restored.  */
    parser->context->object_type = NULL_TREE;
  
*************** cp_parser_lookup_name (cp_parser *parser
*** 14276,14285 ****
--- 14301,14312 ----
      return error_mark_node;
  
    /* If it's a TREE_LIST, the result of the lookup was ambiguous.  */
    if (TREE_CODE (decl) == TREE_LIST)
      {
+       if (ambiguous_p)
+ 	*ambiguous_p = true;
        /* The error message we have to print is too complicated for
  	 cp_parser_error, so we incorporate its actions directly.  */
        if (!cp_parser_simulate_error (parser))
  	{
  	  error ("reference to `%D' is ambiguous", name);
*************** cp_parser_lookup_name_simple (cp_parser*
*** 14317,14327 ****
  {
    return cp_parser_lookup_name (parser, name,
  				/*is_type=*/false,
  				/*is_template=*/false,
  				/*is_namespace=*/false,
! 				/*check_dependency=*/true);
  }
  
  /* If DECL is a TEMPLATE_DECL that can be treated like a TYPE_DECL in
     the current context, return the TYPE_DECL.  If TAG_NAME_P is
     true, the DECL indicates the class being defined in a class-head,
--- 14344,14355 ----
  {
    return cp_parser_lookup_name (parser, name,
  				/*is_type=*/false,
  				/*is_template=*/false,
  				/*is_namespace=*/false,
! 				/*check_dependency=*/true,
! 				/*ambiguous_p=*/NULL);
  }
  
  /* If DECL is a TEMPLATE_DECL that can be treated like a TYPE_DECL in
     the current context, return the TYPE_DECL.  If TAG_NAME_P is
     true, the DECL indicates the class being defined in a class-head,
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.905
diff -c -5 -p -r1.905 pt.c
*** cp/pt.c	16 Aug 2004 14:29:25 -0000	1.905
--- cp/pt.c	17 Aug 2004 17:31:08 -0000
*************** tsubst_qualified_id (tree qualified_id, 
*** 7394,7415 ****
  	  return error_mark_node;
  	}
      }
    
    if (DECL_P (expr))
!     check_accessibility_of_qualified_id (expr, /*object_type=*/NULL_TREE,
! 					 scope);
!   
!   /* Remember that there was a reference to this entity.  */
!   if (DECL_P (expr))
!     mark_used (expr);
  
    if (is_template)
      expr = lookup_template_function (expr, template_args);
  
    if (expr == error_mark_node && complain & tf_error)
!     qualified_name_lookup_error (scope, TREE_OPERAND (qualified_id, 1));
    else if (TYPE_P (scope))
      {
        expr = (adjust_result_of_qualified_name_lookup 
  	      (expr, scope, current_class_type));
        expr = finish_qualified_id_expr (scope, expr, done, address_p);
--- 7394,7425 ----
  	  return error_mark_node;
  	}
      }
    
    if (DECL_P (expr))
!     {
!       check_accessibility_of_qualified_id (expr, /*object_type=*/NULL_TREE,
! 					   scope);
!       /* Remember that there was a reference to this entity.  */
!       mark_used (expr);
!     }
! 
!   if (expr == error_mark_node || TREE_CODE (expr) == TREE_LIST)
!     {
!       if (complain & tf_error)
! 	qualified_name_lookup_error (scope, 
! 				     TREE_OPERAND (qualified_id, 1),
! 				     expr);
!       return error_mark_node;
!     }
  
    if (is_template)
      expr = lookup_template_function (expr, template_args);
  
    if (expr == error_mark_node && complain & tf_error)
!     qualified_name_lookup_error (scope, TREE_OPERAND (qualified_id, 1),
! 				 expr);
    else if (TYPE_P (scope))
      {
        expr = (adjust_result_of_qualified_name_lookup 
  	      (expr, scope, current_class_type));
        expr = finish_qualified_id_expr (scope, expr, done, address_p);
*************** tsubst_expr (tree t, tree args, tsubst_f
*** 7853,7864 ****
  	    
  	    scope = tsubst_expr (scope, args, complain, in_decl);
  	    decl = lookup_qualified_name (scope, name,
  					  /*is_type_p=*/false,
  					  /*complain=*/false);
! 	    if (decl == error_mark_node)
! 	      qualified_name_lookup_error (scope, name);
  	    else
  	      do_local_using_decl (decl, scope, name);
  	  }
  	else
  	  {
--- 7863,7874 ----
  	    
  	    scope = tsubst_expr (scope, args, complain, in_decl);
  	    decl = lookup_qualified_name (scope, name,
  					  /*is_type_p=*/false,
  					  /*complain=*/false);
! 	    if (decl == error_mark_node || TREE_CODE (decl) == TREE_LIST)
! 	      qualified_name_lookup_error (scope, name, decl);
  	    else
  	      do_local_using_decl (decl, scope, name);
  	  }
  	else
  	  {
*************** tsubst_copy_and_build (tree t, 
*** 8508,8518 ****
  	      BASELINK_FUNCTIONS (member) 
  		= build_nt (TEMPLATE_ID_EXPR, BASELINK_FUNCTIONS (member),
  			    args);
  	    else
  	      {
! 		qualified_name_lookup_error (TREE_TYPE (object), tmpl);
  		return error_mark_node;
  	      }
  	  }
  	else if (TREE_CODE (member) == SCOPE_REF
  		 && !CLASS_TYPE_P (TREE_OPERAND (member, 0))
--- 8518,8529 ----
  	      BASELINK_FUNCTIONS (member) 
  		= build_nt (TEMPLATE_ID_EXPR, BASELINK_FUNCTIONS (member),
  			    args);
  	    else
  	      {
! 		qualified_name_lookup_error (TREE_TYPE (object), tmpl,
! 					     member);
  		return error_mark_node;
  	      }
  	  }
  	else if (TREE_CODE (member) == SCOPE_REF
  		 && !CLASS_TYPE_P (TREE_OPERAND (member, 0))
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.423
diff -c -5 -p -r1.423 semantics.c
*** cp/semantics.c	16 Aug 2004 02:08:02 -0000	1.423
--- cp/semantics.c	17 Aug 2004 17:31:08 -0000
*************** check_multiple_declarators (void)
*** 2288,2306 ****
        || processing_explicit_instantiation
        || processing_specialization)
      error ("multiple declarators in template declaration");
  }
  
! /* Issue a diagnostic that NAME cannot be found in SCOPE.  */
  
  void
! qualified_name_lookup_error (tree scope, tree name)
  {
    if (TYPE_P (scope))
      {
        if (!COMPLETE_TYPE_P (scope))
  	error ("incomplete type `%T' used in nested name specifier", scope);
        else
  	error ("`%D' is not a member of `%T'", name, scope);
      }
    else if (scope != global_namespace)
      error ("`%D' is not a member of `%D'", name, scope);
--- 2288,2312 ----
        || processing_explicit_instantiation
        || processing_specialization)
      error ("multiple declarators in template declaration");
  }
  
! /* Issue a diagnostic that NAME cannot be found in SCOPE.  DECL is
!    what we found when we tried to do the lookup.  */
  
  void
! qualified_name_lookup_error (tree scope, tree name, tree decl)
  {
    if (TYPE_P (scope))
      {
        if (!COMPLETE_TYPE_P (scope))
  	error ("incomplete type `%T' used in nested name specifier", scope);
+       else if (TREE_CODE (decl) == TREE_LIST)
+ 	{
+ 	  error ("reference to `%T::%D' is ambiguous", scope, name);
+ 	  print_candidates (decl);
+ 	}
        else
  	error ("`%D' is not a member of `%T'", name, scope);
      }
    else if (scope != global_namespace)
      error ("`%D' is not a member of `%D'", name, scope);
*************** finish_id_expression (tree id_expression
*** 2372,2382 ****
  			   && dependent_type_p (TREE_TYPE (id_expression))))))
  	    {
  	      /* If the qualifying type is non-dependent (and the name
  		 does not name a conversion operator to a dependent
  		 type), issue an error.  */
! 	      qualified_name_lookup_error (scope, id_expression);
  	      return error_mark_node;
  	    }
  	  else if (!scope)
  	    {
  	      /* It may be resolved via Koenig lookup.  */
--- 2378,2388 ----
  			   && dependent_type_p (TREE_TYPE (id_expression))))))
  	    {
  	      /* If the qualifying type is non-dependent (and the name
  		 does not name a conversion operator to a dependent
  		 type), issue an error.  */
! 	      qualified_name_lookup_error (scope, id_expression, decl);
  	      return error_mark_node;
  	    }
  	  else if (!scope)
  	    {
  	      /* It may be resolved via Koenig lookup.  */
Index: testsuite/g++.dg/parse/error17.C
===================================================================
RCS file: testsuite/g++.dg/parse/error17.C
diff -N testsuite/g++.dg/parse/error17.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/parse/error17.C	17 Aug 2004 17:31:09 -0000
***************
*** 0 ****
--- 1,8 ----
+ // PR c++/16965
+ 
+ template <typename T> struct B { 
+   static int Bar(T); // { dg-error "" }
+ }; 
+ struct D : B<int>, B<char> {}; 
+  
+ int i2 = D::Bar(2); // { dg-error "" }


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