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 18738


This patch fixes PR c++/18738.  We were rejecting uses of "typename"
where the qualfying scope was a namespace, rather than a type.

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

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

2004-12-14  Mark Mitchell  <mark@codesourcery.com>

	PR c++/18738
	* decl.c (make_typename_type): Do not handle namespace-scoped
	names here.
	(tag_name): Handle typename_type.
	(check_elaborated_type_specifier): Handle typenames.
	* parser.c (cp_parser_diagnose_invalid_type_name): Improve
	comment.
	(cp_parser_elaborated_type_specifier): Use
	cp_parser_diagnose_invalid_type_name.

2004-12-14  Mark Mitchell  <mark@codesourcery.com>

	PR c++/18738
	* g++.dg/template/typename8.C: New test.
	* g++.dg/parse/friend2.C: Tweak error message.

Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1340
diff -c -5 -p -r1.1340 decl.c
*** cp/decl.c	8 Dec 2004 10:25:06 -0000	1.1340
--- cp/decl.c	15 Dec 2004 00:37:30 -0000
*************** make_typename_type (tree context, tree n
*** 2667,2685 ****
      {
        error ("%qD used without template parameters", name);
        return error_mark_node;
      }
    gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
! 
!   if (TREE_CODE (context) == NAMESPACE_DECL)
!     {
!       /* We can get here from typename_sub0 in the explicit_template_type
! 	 expansion.  Just fail.  */
!       if (complain & tf_error)
! 	error ("no class template named %q#T in %q#T", name, context);
!       return error_mark_node;
!     }
  
    if (!dependent_type_p (context)
        || currently_open_class (context))
      {
        if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR)
--- 2667,2677 ----
      {
        error ("%qD used without template parameters", name);
        return error_mark_node;
      }
    gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
!   gcc_assert (TYPE_P (context));
  
    if (!dependent_type_p (context)
        || currently_open_class (context))
      {
        if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR)
*************** grok_op_properties (tree decl, int frien
*** 9046,9068 ****
      }
  
    return ok;
  }
  
  static const char *
  tag_name (enum tag_types code)
  {
    switch (code)
      {
      case record_type:
        return "struct";
      case class_type:
        return "class";
      case union_type:
!       return "union ";
      case enum_type:
        return "enum";
      default:
        gcc_unreachable ();
      }
  }
  
--- 9038,9064 ----
      }
  
    return ok;
  }
  
+ /* Return a string giving the keyword associate with CODE.  */
+ 
  static const char *
  tag_name (enum tag_types code)
  {
    switch (code)
      {
      case record_type:
        return "struct";
      case class_type:
        return "class";
      case union_type:
!       return "union";
      case enum_type:
        return "enum";
+     case typename_type:
+       return "typename";
      default:
        gcc_unreachable ();
      }
  }
  
*************** check_elaborated_type_specifier (enum ta
*** 9104,9129 ****
         type-parameter, the elaborated-type-specifier is ill-formed.
  
       In other words, the only legitimate declaration to use in the
       elaborated type specifier is the implicit typedef created when
       the type is declared.  */
!   else if (!DECL_IMPLICIT_TYPEDEF_P (decl))
      {
        error ("using typedef-name %qD after %qs", decl, tag_name (tag_code));
        cp_error_at ("%qD has a previous declaration here", decl);
        return error_mark_node;
      }
    else if (TREE_CODE (type) != RECORD_TYPE
  	   && TREE_CODE (type) != UNION_TYPE
! 	   && tag_code != enum_type)
      {
        error ("%qT referred to as %qs", type, tag_name (tag_code));
        cp_error_at ("%qT has a previous declaration here", type);
        return error_mark_node;
      }
    else if (TREE_CODE (type) != ENUMERAL_TYPE
! 	   && tag_code == enum_type)
      {
        error ("%qT referred to as enum", type);
        cp_error_at ("%qT has a previous declaration here", type);
        return error_mark_node;
      }
--- 9100,9128 ----
         type-parameter, the elaborated-type-specifier is ill-formed.
  
       In other words, the only legitimate declaration to use in the
       elaborated type specifier is the implicit typedef created when
       the type is declared.  */
!   else if (!DECL_IMPLICIT_TYPEDEF_P (decl)
! 	   && tag_code != typename_type)
      {
        error ("using typedef-name %qD after %qs", decl, tag_name (tag_code));
        cp_error_at ("%qD has a previous declaration here", decl);
        return error_mark_node;
      }
    else if (TREE_CODE (type) != RECORD_TYPE
  	   && TREE_CODE (type) != UNION_TYPE
! 	   && tag_code != enum_type
! 	   && tag_code != typename_type)
      {
        error ("%qT referred to as %qs", type, tag_name (tag_code));
        cp_error_at ("%qT has a previous declaration here", type);
        return error_mark_node;
      }
    else if (TREE_CODE (type) != ENUMERAL_TYPE
! 	   && tag_code == enum_type
! 	   && tag_code != typename_type)
      {
        error ("%qT referred to as enum", type);
        cp_error_at ("%qT has a previous declaration here", type);
        return error_mark_node;
      }
Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.293
diff -c -5 -p -r1.293 parser.c
*** cp/parser.c	10 Dec 2004 16:04:15 -0000	1.293
--- cp/parser.c	15 Dec 2004 00:37:33 -0000
*************** cp_parser_non_integral_constant_expressi
*** 1939,1951 ****
        parser->non_integral_constant_expression_p = true;
      }
    return false;
  }
  
! /* Emit a diagnostic for an invalid type name. Consider also if it is
!    qualified or not and the result of a lookup, to provide a better
!    message.  */
  
  static void
  cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
  {
    tree decl, old_scope;
--- 1939,1950 ----
        parser->non_integral_constant_expression_p = true;
      }
    return false;
  }
  
! /* Emit a diagnostic for an invalid type name.  SCOPE is the
!    qualifying scope (or NULL, if none) for ID.  */
  
  static void
  cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
  {
    tree decl, old_scope;
*************** cp_parser_elaborated_type_specifier (cp_
*** 9655,9675 ****
  	  parser->scope = NULL_TREE;
  	  return error_mark_node;
  	}
  
        /* For a `typename', we needn't call xref_tag.  */
!       if (tag_type == typename_type)
  	return cp_parser_make_typename_type (parser, parser->scope,
  					     identifier);
        /* Look up a qualified name in the usual way.  */
        if (parser->scope)
  	{
  	  tree decl;
  
- 	  /* In an elaborated-type-specifier, names are assumed to name
- 	     types, so we set IS_TYPE to TRUE when calling
- 	     cp_parser_lookup_name.  */
  	  decl = cp_parser_lookup_name (parser, identifier,
  					tag_type,
  					/*is_template=*/false,
  					/*is_namespace=*/false,
  					/*check_dependency=*/true,
--- 9654,9672 ----
  	  parser->scope = NULL_TREE;
  	  return error_mark_node;
  	}
  
        /* For a `typename', we needn't call xref_tag.  */
!       if (tag_type == typename_type 
! 	  && TREE_CODE (parser->scope) != NAMESPACE_DECL)
  	return cp_parser_make_typename_type (parser, parser->scope,
  					     identifier);
        /* Look up a qualified name in the usual way.  */
        if (parser->scope)
  	{
  	  tree decl;
  
  	  decl = cp_parser_lookup_name (parser, identifier,
  					tag_type,
  					/*is_template=*/false,
  					/*is_namespace=*/false,
  					/*check_dependency=*/true,
*************** cp_parser_elaborated_type_specifier (cp_
*** 9700,9710 ****
  		  (decl, /*tag_name_p=*/is_friend
  			 && parser->num_template_parameter_lists));
  
  	  if (TREE_CODE (decl) != TYPE_DECL)
  	    {
! 	      error ("expected type-name");
  	      return error_mark_node;
  	    }
  
  	  if (TREE_CODE (TREE_TYPE (decl)) != TYPENAME_TYPE)
  	    check_elaborated_type_specifier
--- 9697,9709 ----
  		  (decl, /*tag_name_p=*/is_friend
  			 && parser->num_template_parameter_lists));
  
  	  if (TREE_CODE (decl) != TYPE_DECL)
  	    {
! 	      cp_parser_diagnose_invalid_type_name (parser, 
! 						    parser->scope,
! 						    identifier);
  	      return error_mark_node;
  	    }
  
  	  if (TREE_CODE (TREE_TYPE (decl)) != TYPENAME_TYPE)
  	    check_elaborated_type_specifier
Index: testsuite/g++.dg/parse/friend2.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/parse/friend2.C,v
retrieving revision 1.1
diff -c -5 -p -r1.1 friend2.C
*** testsuite/g++.dg/parse/friend2.C	29 Jan 2003 14:25:06 -0000	1.1
--- testsuite/g++.dg/parse/friend2.C	15 Dec 2004 00:37:33 -0000
*************** namespace NS {
*** 8,16 ****
    template <class T1, class T2, class T3 = int, class T4 = int>
    struct C {};
  }
  
  template <class T> class X {
!   friend class NS::C;	// { dg-error "expected|friend" }
  };
  
  X<int> c;
--- 8,16 ----
    template <class T1, class T2, class T3 = int, class T4 = int>
    struct C {};
  }
  
  template <class T> class X {
!   friend class NS::C;	// { dg-error "template|friend" }
  };
  
  X<int> c;
Index: testsuite/g++.dg/template/typename8.C
===================================================================
RCS file: testsuite/g++.dg/template/typename8.C
diff -N testsuite/g++.dg/template/typename8.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/typename8.C	15 Dec 2004 00:37:37 -0000
***************
*** 0 ****
--- 1,10 ----
+ // PR c++/18738
+ 
+ namespace foo {
+   typedef int my_type;
+ }
+ 
+ template<typename T>
+ struct A {
+   typename foo::my_type bar();
+ };


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