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: 18368, 18674, 18512


PR 18368 is a PR about the fact that we were no longer hinting that
the problem in something like "class X {} f()" might be a missing
semicolon after the class-specifier.  Fixed by making sure that the
function that emits the error had access to the type, so that it could
issue a good warning.  I had to change several test cases to accept
the new warning.

PR 18512 was a parser crash when lookup of an unqualified name after
"." or "->" found a TYPE_DECL (becaue the name was a template-id).
Easily fixed by handling that case.

PR 18674 relates to the fact that saying "enum T::x" in a template,
where "T" is a dependent name, results in a TYPENAME_TYPE internally.
However, the standard does not permit the "enum" to resolve to a
"struct".   So, we must keep track of the original designation.  That
involved passing around the tag kind in the parser; an unfortunately
large change, but very mechanical.  

Then, I realized that there was some serious badness in here.  In
particular, for every *use* of a variable in a template, we
substituted into its type at instantiation time.  (I found this
because we issued duplicate errors about the enum/struct mismatch.)
This, despite the fact that, of course, we already know the resulting
type, becuase we know how to retrieve the instantiation of the
variable.  Furthermore, every call to build_typename_type resulted in
a new TYPENAME_TYPE and accompanying TYPE_DECL being created -- even
though the whole point of that function was to lookup existing
typename types in a hash table and return an existing match, if
available.  So, I fixed both of those problems.  Since Zack's not
quite yet got our Qt builds working again, I couldn't measure the
compile-time performance impact there, but it sure ain't going to
hurt.

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

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

2004-11-27  Mark Mitchell  <mark@codesourcery.com>

	PR c++/18368
	* parser.c (cp_parser_check_for_definition_in_return_type): Take
	the defined type as a parameter, and inform the user about the
	possibility of a missing semicolon.
	(cp_parser_explicit_instantiation): Adjust call to
	cp_parser_check_for_definition_in_return_type.
	(cp_parser_init_declarator): Likewise.
	(cp_parser_member_declaration): Likewise.

	PR c++/18674
	* cp-tree.def (TYPENAME_TYPE): Remove discussion of implicit
	typename from comments.
	* cp-tree.h (TYPENAME_IS_ENUM_P): New macro.
	(TYPENAME_IS_CLASS_P): Likewise.
	(make_typename_type): Change prototype.
	* decl.c (struct_typename_info): New type.
	(typename_compare): Expect the second argument to be a
	typename_info, not a tree.
	(build_typename_type): Add tag_type parameter.  Do not create a
	new type until necessary.
	(make_typename_type): Add tag_type parameter.
	* error.c (TYPENAME_TYPE): Print tags other than "typename" if
	appropriate.
	* friend.c (make_friend_class): Adjust call to make_typename_type.
	* parser.c (cp_parser_make_typename_type): Likewise.
	(cp_parser_primary_expression): Adjust call to
	cp_parser_lookup_name.
	(cp_parser_unqualified_id): Adjust calls to cp_parser_class_name.
	(cp_parser_class_or_namespace_name): Likewise.
	(cp_parser_postfix_expression): Adjust calls to
	make_typename_type.
	(cp_parser_mem_initializer_id): Adjust calls to
	cp_parser_class_name.
	(cp_parser_type_parameter): Adjust calls to cp_parser_lookup_name.
	(cp_parser_template_name): Likewise.
	(cp_parser_template_argument): Likewise.
	(cp_parser_type_name): Adjust call to cp_parser_class_name.
	(cp_parser_elaborated_type_specifier): Adjust calls to
	make_typename_type and cp_parser_lookup_name.
	(cp_parser_namespace_name): Likewise.
	(cp_parser_class_name): Replace type_p parameter with tag_type.
	Adjust calls to make_typename_type and cp_parser_lookup_name.
	(cp_parser_class_head): Adjust calls to cp_parser_class_name.
	(cp_parser_base_specifier): Likewise.
	(cp_parser_lookup_name): Replace is_type parameter with tag_type.
	Adjust calls to make_typename_type and lookup_qualified_name.
	(cp_parser_lookup_name_simple): Adjust call to
	cp_parser_lookup_name.
	(cp_parser_constructor_declarator_p): Adjust call to
	cp_parser_class_name.
	* pt.c (convert_template_argument): Adjust all to
	make_typename_type.
	(tsubst_decl): Do not pre-substitute the type of the declaration.
	(tsubst): Hand off declarations more quickly.  Adjust call to
	make_typename_type. 

	PR c++/18512
	* parser.c (cp_parser_postfix_dot_deref_expression): Robustify.

2004-11-29  Mark Mitchell  <mark@codesourcery.com>

	PR c++/18674
	* g++.old-deja/g++.brendan/crash16.C: Adjust error messages.
	* g++.old-deja/g++.law/ctors5.C: Likewise.
	* g++.old-deja/g++.other/crash25.C: Likewise.

	PR c++/18674
	* g++.dg/template/error16.C: New test.
	
	PR c++/18512
	* g++.dg/template/crash29.C: New test.

Index: cp/cp-tree.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.def,v
retrieving revision 1.90
diff -c -5 -p -r1.90 cp-tree.def
*** cp/cp-tree.def	17 Sep 2004 21:54:56 -0000	1.90
--- cp/cp-tree.def	29 Nov 2004 19:17:26 -0000
*************** DEFTREECODE (BOUND_TEMPLATE_TEMPLATE_PAR
*** 180,192 ****
  	     tcc_type, 0)
  
  /* A type designated by `typename T::t'.  TYPE_CONTEXT is `T',
     TYPE_NAME is an IDENTIFIER_NODE for `t'.  If the type was named via
     template-id, TYPENAME_TYPE_FULLNAME will hold the TEMPLATE_ID_EXPR.
!    If TREE_TYPE is present, this type was generated by the implicit
!    typename extension, and the TREE_TYPE is a _TYPE from a baseclass
!    of `T'.  */
  DEFTREECODE (TYPENAME_TYPE, "typename_type", tcc_type, 0)
  
  /* For template template argument of the form `T::template C'.
     TYPE_CONTEXT is `T', the template parameter dependent object.
     TYPE_NAME is an IDENTIFIER_NODE for `C', the member class template.  */
--- 180,190 ----
  	     tcc_type, 0)
  
  /* A type designated by `typename T::t'.  TYPE_CONTEXT is `T',
     TYPE_NAME is an IDENTIFIER_NODE for `t'.  If the type was named via
     template-id, TYPENAME_TYPE_FULLNAME will hold the TEMPLATE_ID_EXPR.
!    TREE_TYPE is always NULL.  */
  DEFTREECODE (TYPENAME_TYPE, "typename_type", tcc_type, 0)
  
  /* For template template argument of the form `T::template C'.
     TYPE_CONTEXT is `T', the template parameter dependent object.
     TYPE_NAME is an IDENTIFIER_NODE for `C', the member class template.  */
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.1074
diff -c -5 -p -r1.1074 cp-tree.h
*** cp/cp-tree.h	25 Nov 2004 17:11:36 -0000	1.1074
--- cp/cp-tree.h	29 Nov 2004 19:17:26 -0000
*************** struct diagnostic_context;
*** 45,61 ****
--- 45,63 ----
        DECL_PRETTY_FUNCTION_P (in VAR_DECL)
        KOENIG_LOOKUP_P (in CALL_EXPR)
        STATEMENT_LIST_NO_SCOPE (in STATEMENT_LIST).
        EXPR_STMT_STMT_EXPR_RESULT (in EXPR_STMT)
        BIND_EXPR_TRY_BLOCK (in BIND_EXPR)
+       TYPENAME_IS_ENUM_P (in TYPENAME_TYPE)
     1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)
        TI_PENDING_TEMPLATE_FLAG.
        TEMPLATE_PARMS_FOR_INLINE.
        DELETE_EXPR_USE_VEC (in DELETE_EXPR).
        (TREE_CALLS_NEW) (in _EXPR or _REF) (commented-out).
        ICS_ELLIPSIS_FLAG (in _CONV)
        DECL_INITIALIZED_P (in VAR_DECL)
+       TYPENAME_IS_CLASS_P (in TYPENAME_TYPE)
     2: IDENTIFIER_OPNAME_P (in IDENTIFIER_NODE)
        ICS_THIS_FLAG (in _CONV)
        DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL)
        STATEMENT_LIST_TRY_BLOCK (in STATEMENT_LIST)
     3: (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out).
*************** struct lang_decl GTY(())
*** 2252,2261 ****
--- 2254,2272 ----
     this is an IDENTIFIER_NODE, and the same as the DECL_NAME on the
     corresponding TYPE_DECL.  However, this may also be a
     TEMPLATE_ID_EXPR if we had something like `typename X::Y<T>'.  */
  #define TYPENAME_TYPE_FULLNAME(NODE) (TYPENAME_TYPE_CHECK (NODE))->type.values
  
+ /* True if a TYPENAME_TYPE was declared as an "enum".  */
+ #define TYPENAME_IS_ENUM_P(NODE) \
+   (TREE_LANG_FLAG_0 (TYPENAME_TYPE_CHECK (NODE)))
+ 
+ /* True if a TYPENAME_TYPE was declared as a "class", "struct", or
+    "union".  */
+ #define TYPENAME_IS_CLASS_P(NODE) \
+   (TREE_LANG_FLAG_1 (TYPENAME_TYPE_CHECK (NODE)))
+ 
  /* Nonzero in INTEGER_CST means that this int is negative by dint of
     using a twos-complement negated operand.  */
  #define TREE_NEGATED_INT(NODE) TREE_LANG_FLAG_0 (INTEGER_CST_CHECK (NODE))
  
  /* [class.virtual]
*************** extern tree pushdecl_top_level_and_finis
*** 3717,3727 ****
  extern tree push_using_decl                     (tree, tree);
  extern tree declare_local_label                 (tree);
  extern tree define_label			(location_t, tree);
  extern void check_goto				(tree);
  extern void define_case_label			(void);
! extern tree make_typename_type			(tree, tree, tsubst_flags_t);
  extern tree make_unbound_class_template		(tree, tree, tree, tsubst_flags_t);
  extern tree check_for_out_of_scope_variable     (tree);
  extern tree build_library_fn			(tree, tree);
  extern tree build_library_fn_ptr		(const char *, tree);
  extern tree build_cp_library_fn_ptr		(const char *, tree);
--- 3728,3738 ----
  extern tree push_using_decl                     (tree, tree);
  extern tree declare_local_label                 (tree);
  extern tree define_label			(location_t, tree);
  extern void check_goto				(tree);
  extern void define_case_label			(void);
! extern tree make_typename_type			(tree, tree, enum tag_types, tsubst_flags_t);
  extern tree make_unbound_class_template		(tree, tree, tree, tsubst_flags_t);
  extern tree check_for_out_of_scope_variable     (tree);
  extern tree build_library_fn			(tree, tree);
  extern tree build_library_fn_ptr		(const char *, tree);
  extern tree build_cp_library_fn_ptr		(const char *, tree);
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1334
diff -c -5 -p -r1.1334 decl.c
*** cp/decl.c	25 Nov 2004 17:11:36 -0000	1.1334
--- cp/decl.c	29 Nov 2004 19:17:26 -0000
*************** static tree build_cp_library_fn (tree, e
*** 119,129 ****
  static void store_parm_decls (tree);
  static void initialize_local_var (tree, tree);
  static void expand_static_init (tree, tree);
  static tree next_initializable_field (tree);
  static tree reshape_init (tree, tree *);
- static tree build_typename_type (tree, tree, tree);
  
  /* Erroneous argument lists can use this *IFF* they do not modify it.  */
  tree error_mark_list;
  
  /* The following symbols are subsumed in the cp_global_trees array, and
--- 119,128 ----
*************** typename_hash (const void* k)
*** 2536,2622 ****
  	  ^ htab_hash_pointer (DECL_NAME (TYPE_NAME (t))));
  
    return hash;
  }
  
  /* Compare two TYPENAME_TYPEs.  K1 and K2 are really of type `tree'.  */
  
  static int
  typename_compare (const void * k1, const void * k2)
  {
    tree t1;
!   tree t2;
!   tree d1;
!   tree d2;
  
    t1 = (tree) k1;
!   t2 = (tree) k2;
!   d1 = TYPE_NAME (t1);
!   d2 = TYPE_NAME (t2);
! 
!   return (DECL_NAME (d1) == DECL_NAME (d2)
! 	  && TYPE_CONTEXT (t1) == TYPE_CONTEXT (t2)
! 	  && ((TREE_TYPE (t1) != NULL_TREE)
! 	      == (TREE_TYPE (t2) != NULL_TREE))
! 	  && same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
! 	  && TYPENAME_TYPE_FULLNAME (t1) == TYPENAME_TYPE_FULLNAME (t2));
  }
  
  /* Build a TYPENAME_TYPE.  If the type is `typename T::t', CONTEXT is
!    the type of `T', NAME is the IDENTIFIER_NODE for `t'.  If BASE_TYPE
!    is non-NULL, this type is being created by the implicit typename
!    extension, and BASE_TYPE is a type named `t' in some base class of
!    `T' which depends on template parameters.
! 
     Returns the new TYPENAME_TYPE.  */
  
  static GTY ((param_is (union tree_node))) htab_t typename_htab;
  
  static tree
! build_typename_type (tree context, tree name, tree fullname)
  {
    tree t;
    tree d;
    void **e;
  
    if (typename_htab == NULL)
!     {
!       typename_htab = htab_create_ggc (61, &typename_hash,
! 				       &typename_compare, NULL);
!     }
! 
!   /* Build the TYPENAME_TYPE.  */
!   t = make_aggr_type (TYPENAME_TYPE);
!   TYPE_CONTEXT (t) = FROB_CONTEXT (context);
!   TYPENAME_TYPE_FULLNAME (t) = fullname;
  
!   /* Build the corresponding TYPE_DECL.  */
!   d = build_decl (TYPE_DECL, name, t);
!   TYPE_NAME (TREE_TYPE (d)) = d;
!   TYPE_STUB_DECL (TREE_TYPE (d)) = d;
!   DECL_CONTEXT (d) = FROB_CONTEXT (context);
!   DECL_ARTIFICIAL (d) = 1;
  
    /* See if we already have this type.  */
!   e = htab_find_slot (typename_htab, t, INSERT);
    if (*e)
      t = (tree) *e;
    else
!     *e = t;
  
    return t;
  }
  
! /* Resolve `typename CONTEXT::NAME'.  Returns an appropriate type,
!    unless an error occurs, in which case error_mark_node is returned.
!    If we locate a non-artificial TYPE_DECL and TF_KEEP_TYPE_DECL is
!    set, we return that, rather than the _TYPE it corresponds to, in
!    other cases we look through the type decl.  If TF_ERROR is set,
!    complain about errors, otherwise be quiet.  */
  
  tree
! make_typename_type (tree context, tree name, tsubst_flags_t complain)
  {
    tree fullname;
  
    if (name == error_mark_node
        || context == NULL_TREE
--- 2535,2639 ----
  	  ^ htab_hash_pointer (DECL_NAME (TYPE_NAME (t))));
  
    return hash;
  }
  
+ typedef struct typename_info {
+   tree scope;
+   tree name;
+   tree template_id;
+   bool enum_p;
+   bool class_p;
+ } typename_info;
+ 
  /* Compare two TYPENAME_TYPEs.  K1 and K2 are really of type `tree'.  */
  
  static int
  typename_compare (const void * k1, const void * k2)
  {
    tree t1;
!   const typename_info *t2;
  
    t1 = (tree) k1;
!   t2 = (const typename_info *) k2;
! 
!   return (DECL_NAME (TYPE_NAME (t1)) == t2->name
! 	  && TYPE_CONTEXT (t1) == t2->scope
! 	  && TYPENAME_TYPE_FULLNAME (t1) == t2->template_id
! 	  && TYPENAME_IS_ENUM_P (t1) == t2->enum_p
! 	  && TYPENAME_IS_CLASS_P (t1) == t2->class_p);
  }
  
  /* Build a TYPENAME_TYPE.  If the type is `typename T::t', CONTEXT is
!    the type of `T', NAME is the IDENTIFIER_NODE for `t'.
!  
     Returns the new TYPENAME_TYPE.  */
  
  static GTY ((param_is (union tree_node))) htab_t typename_htab;
  
  static tree
! build_typename_type (tree context, tree name, tree fullname,
! 		     enum tag_types tag_type)
  {
    tree t;
    tree d;
+   typename_info ti;
    void **e;
+   hashval_t hash;
  
    if (typename_htab == NULL)
!     typename_htab = htab_create_ggc (61, &typename_hash,
! 				     &typename_compare, NULL);
  
!   ti.scope = FROB_CONTEXT (context); 
!   ti.name = name;
!   ti.template_id = fullname;
!   ti.enum_p = tag_type == enum_type;
!   ti.class_p = (tag_type == class_type
! 		|| tag_type == record_type
! 		|| tag_type == union_type);
!   hash =  (htab_hash_pointer (ti.scope)
! 	   ^ htab_hash_pointer (ti.name));
  
    /* See if we already have this type.  */
!   e = htab_find_slot_with_hash (typename_htab, &ti, hash, INSERT);
    if (*e)
      t = (tree) *e;
    else
!     {
!       /* Build the TYPENAME_TYPE.  */
!       t = make_aggr_type (TYPENAME_TYPE);
!       TYPE_CONTEXT (t) = ti.scope;
!       TYPENAME_TYPE_FULLNAME (t) = ti.template_id;
!       TYPENAME_IS_ENUM_P (t) = ti.enum_p;
!       TYPENAME_IS_CLASS_P (t) = ti.class_p;
!       
!       /* Build the corresponding TYPE_DECL.  */
!       d = build_decl (TYPE_DECL, name, t);
!       TYPE_NAME (TREE_TYPE (d)) = d;
!       TYPE_STUB_DECL (TREE_TYPE (d)) = d;
!       DECL_CONTEXT (d) = FROB_CONTEXT (context);
!       DECL_ARTIFICIAL (d) = 1;
  
+       /* Store it in the hash table.  */
+       *e = t;
+     }
+       
    return t;
  }
  
! /* Resolve `typename CONTEXT::NAME'.  TAG_TYPE indicates the tag
!    provided to name the type.  Returns an appropriate type, unless an
!    error occurs, in which case error_mark_node is returned.  If we
!    locate a non-artificial TYPE_DECL and TF_KEEP_TYPE_DECL is set, we
!    return that, rather than the _TYPE it corresponds to, in other
!    cases we look through the type decl.  If TF_ERROR is set, complain
!    about errors, otherwise be quiet.  */
  
  tree
! make_typename_type (tree context, tree name, enum tag_types tag_type,
! 		    tsubst_flags_t complain)
  {
    tree fullname;
  
    if (name == error_mark_node
        || context == NULL_TREE
*************** make_typename_type (tree context, tree n
*** 2726,2736 ****
        if (complain & tf_error)
  	error ("no type named %q#T in %q#T", name, context);
        return error_mark_node;
      }
  
!   return build_typename_type (context, name, fullname);
  }
  
  /* Resolve `CONTEXT::template NAME'.  Returns a TEMPLATE_DECL if the name
     can be resolved or an UNBOUND_CLASS_TEMPLATE, unless an error occurs, 
     in which case error_mark_node is returned.
--- 2743,2753 ----
        if (complain & tf_error)
  	error ("no type named %q#T in %q#T", name, context);
        return error_mark_node;
      }
  
!   return build_typename_type (context, name, fullname, tag_type);
  }
  
  /* Resolve `CONTEXT::template NAME'.  Returns a TEMPLATE_DECL if the name
     can be resolved or an UNBOUND_CLASS_TEMPLATE, unless an error occurs, 
     in which case error_mark_node is returned.
Index: cp/error.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/error.c,v
retrieving revision 1.272
diff -c -5 -p -r1.272 error.c
*** cp/error.c	24 Nov 2004 04:09:27 -0000	1.272
--- cp/error.c	29 Nov 2004 19:17:28 -0000
*************** dump_type (tree t, int flags)
*** 346,356 ****
        dump_type_suffix (t, flags);
        break;
      }
      case TYPENAME_TYPE:
        pp_cxx_cv_qualifier_seq (cxx_pp, t);
!       pp_cxx_identifier (cxx_pp, "typename");
        dump_typename (t, flags);
        break;
  
      case UNBOUND_CLASS_TEMPLATE:
        dump_type (TYPE_CONTEXT (t), flags);
--- 346,359 ----
        dump_type_suffix (t, flags);
        break;
      }
      case TYPENAME_TYPE:
        pp_cxx_cv_qualifier_seq (cxx_pp, t);
!       pp_cxx_identifier (cxx_pp, 
! 			 TYPENAME_IS_ENUM_P (t) ? "enum" 
! 			 : TYPENAME_IS_CLASS_P (t) ? "class"
! 			 : "typename");
        dump_typename (t, flags);
        break;
  
      case UNBOUND_CLASS_TEMPLATE:
        dump_type (TYPE_CONTEXT (t), flags);
Index: cp/friend.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/friend.c,v
retrieving revision 1.102
diff -c -5 -p -r1.102 friend.c
*** cp/friend.c	20 Oct 2004 16:20:40 -0000	1.102
--- cp/friend.c	29 Nov 2004 19:17:28 -0000
*************** make_friend_class (tree type, tree frien
*** 298,308 ****
  						 name,
  						 current_template_parms,
  						 tf_error);
  	      else
  		friend_type
! 		  = make_typename_type (ctype, name, tf_error);
  	    }
  	  else
  	    {
  	      decl = lookup_member (ctype, name, 0, true);
  	      if (!decl)
--- 298,308 ----
  						 name,
  						 current_template_parms,
  						 tf_error);
  	      else
  		friend_type
! 		  = make_typename_type (ctype, name, class_type, tf_error);
  	    }
  	  else
  	    {
  	      decl = lookup_member (ctype, name, 0, true);
  	      if (!decl)
Index: cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.283
diff -c -5 -p -r1.283 parser.c
*** cp/parser.c	25 Nov 2004 17:05:33 -0000	1.283
--- cp/parser.c	29 Nov 2004 19:17:29 -0000
*************** static bool cp_parser_ctor_initializer_o
*** 1512,1522 ****
    (cp_parser *);
  
  /* Classes [gram.class] */
  
  static tree cp_parser_class_name
!   (cp_parser *, bool, bool, bool, bool, bool, bool);
  static tree cp_parser_class_specifier
    (cp_parser *);
  static tree cp_parser_class_head
    (cp_parser *, bool *, tree *);
  static enum tag_types cp_parser_class_key
--- 1512,1522 ----
    (cp_parser *);
  
  /* Classes [gram.class] */
  
  static tree cp_parser_class_name
!   (cp_parser *, bool, bool, enum tag_types, bool, bool, bool);
  static tree cp_parser_class_specifier
    (cp_parser *);
  static tree cp_parser_class_head
    (cp_parser *, bool *, tree *);
  static enum tag_types cp_parser_class_key
*************** static void cp_parser_label_declaration
*** 1621,1631 ****
    (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
--- 1621,1631 ----
    (cp_parser *);
  
  /* Utility Routines */
  
  static tree cp_parser_lookup_name
!   (cp_parser *, tree, enum tag_types, 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
*************** static void cp_parser_name_lookup_error
*** 1711,1721 ****
  static bool cp_parser_simulate_error
    (cp_parser *);
  static void cp_parser_check_type_definition
    (cp_parser *);
  static void cp_parser_check_for_definition_in_return_type
!   (cp_declarator *, int);
  static void cp_parser_check_for_invalid_template_id
    (cp_parser *, tree);
  static bool cp_parser_non_integral_constant_expression
    (cp_parser *, const char *);
  static void cp_parser_diagnose_invalid_type_name
--- 1711,1721 ----
  static bool cp_parser_simulate_error
    (cp_parser *);
  static void cp_parser_check_type_definition
    (cp_parser *);
  static void cp_parser_check_for_definition_in_return_type
!   (cp_declarator *, tree);
  static void cp_parser_check_for_invalid_template_id
    (cp_parser *, tree);
  static bool cp_parser_non_integral_constant_expression
    (cp_parser *, const char *);
  static void cp_parser_diagnose_invalid_type_name
*************** cp_parser_check_type_definition (cp_pars
*** 1859,1889 ****
      /* Use `%s' to print the string in case there are any escape
         characters in the message.  */
      error ("%s", parser->type_definition_forbidden_message);
  }
  
! /* This function is called when a declaration is parsed.  If
!    DECLARATOR is a function declarator and DECLARES_CLASS_OR_ENUM
!    indicates that a type was defined in the decl-specifiers for DECL,
!    then an error is issued.  */
  
  static void
  cp_parser_check_for_definition_in_return_type (cp_declarator *declarator,
! 					       int declares_class_or_enum)
  {
    /* [dcl.fct] forbids type definitions in return types.
       Unfortunately, it's not easy to know whether or not we are
       processing a return type until after the fact.  */
    while (declarator
  	 && (declarator->kind == cdk_pointer
  	     || declarator->kind == cdk_reference
  	     || declarator->kind == cdk_ptrmem))
      declarator = declarator->declarator;
    if (declarator
!       && declarator->kind == cdk_function
!       && declares_class_or_enum & 2)
!     error ("new types may not be defined in a return type");
  }
  
  /* A type-specifier (TYPE) has been parsed which cannot be followed by
     "<" in any valid C++ program.  If the next token is indeed "<",
     issue a message warning the user about what appears to be an
--- 1859,1892 ----
      /* Use `%s' to print the string in case there are any escape
         characters in the message.  */
      error ("%s", parser->type_definition_forbidden_message);
  }
  
! /* This function is called when the DECLARATOR is processed.  The TYPE
!    was a type definied in the decl-specifiers.  If it is invalid to
!    define a type in the decl-specifiers for DECLARATOR, an error is
!    issued.  */
  
  static void
  cp_parser_check_for_definition_in_return_type (cp_declarator *declarator,
! 					       tree type)
  {
    /* [dcl.fct] forbids type definitions in return types.
       Unfortunately, it's not easy to know whether or not we are
       processing a return type until after the fact.  */
    while (declarator
  	 && (declarator->kind == cdk_pointer
  	     || declarator->kind == cdk_reference
  	     || declarator->kind == cdk_ptrmem))
      declarator = declarator->declarator;
    if (declarator
!       && declarator->kind == cdk_function)
!     {
!       error ("new types may not be defined in a return type");
!       inform ("(perhaps a semicolon is missing after the definition of %qT)",
! 	      type);
!     }
  }
  
  /* A type-specifier (TYPE) has been parsed which cannot be followed by
     "<" in any valid C++ program.  If the next token is indeed "<",
     issue a message warning the user about what appears to be an
*************** static tree
*** 2293,2308 ****
  cp_parser_make_typename_type (cp_parser *parser, tree scope, tree id)
  {
    tree result;
    if (TREE_CODE (id) == IDENTIFIER_NODE)
      {
!       result = make_typename_type (scope, id, /*complain=*/0);
        if (result == error_mark_node)
  	cp_parser_diagnose_invalid_type_name (parser, scope, id);
        return result;
      }
!   return make_typename_type (scope, id, tf_error);
  }
  
  
  /* Create a new C++ parser.  */
  
--- 2296,2312 ----
  cp_parser_make_typename_type (cp_parser *parser, tree scope, tree id)
  {
    tree result;
    if (TREE_CODE (id) == IDENTIFIER_NODE)
      {
!       result = make_typename_type (scope, id, typename_type,
! 				   /*complain=*/0);
        if (result == error_mark_node)
  	cp_parser_diagnose_invalid_type_name (parser, scope, id);
        return result;
      }
!   return make_typename_type (scope, id, typename_type, tf_error);
  }
  
  
  /* Create a new C++ parser.  */
  
*************** cp_parser_primary_expression (cp_parser 
*** 2829,2839 ****
  	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
--- 2833,2843 ----
  	else
  	  {
  	    bool ambiguous_p;
  
  	    decl = cp_parser_lookup_name (parser, id_expression,
! 					  none_type,
  					  /*is_template=*/false,
  					  /*is_namespace=*/false,
  					  /*check_dependency=*/true,
  					  &ambiguous_p);
  	    /* If the lookup was ambiguous, an error will already have
*************** cp_parser_unqualified_id (cp_parser* par
*** 3162,3172 ****
  	  {
  	    cp_parser_parse_tentatively (parser);
  	    type_decl = cp_parser_class_name (parser,
  					      /*typename_keyword_p=*/false,
  					      /*template_keyword_p=*/false,
! 					      /*type_p=*/false,
  					      /*check_dependency=*/false,
  					      /*class_head_p=*/false,
  					      declarator_p);
  	    if (cp_parser_parse_definitely (parser))
  	      return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
--- 3166,3176 ----
  	  {
  	    cp_parser_parse_tentatively (parser);
  	    type_decl = cp_parser_class_name (parser,
  					      /*typename_keyword_p=*/false,
  					      /*template_keyword_p=*/false,
! 					      none_type,
  					      /*check_dependency=*/false,
  					      /*class_head_p=*/false,
  					      declarator_p);
  	    if (cp_parser_parse_definitely (parser))
  	      return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
*************** cp_parser_unqualified_id (cp_parser* par
*** 3180,3190 ****
  	    parser->qualifying_scope = NULL_TREE;
  	    type_decl
  	      = cp_parser_class_name (parser,
  				      /*typename_keyword_p=*/false,
  				      /*template_keyword_p=*/false,
! 				      /*type_p=*/false,
  				      /*check_dependency=*/false,
  				      /*class_head_p=*/false,
  				      declarator_p);
  	    if (cp_parser_parse_definitely (parser))
  	      return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
--- 3184,3194 ----
  	    parser->qualifying_scope = NULL_TREE;
  	    type_decl
  	      = cp_parser_class_name (parser,
  				      /*typename_keyword_p=*/false,
  				      /*template_keyword_p=*/false,
! 				      none_type,
  				      /*check_dependency=*/false,
  				      /*class_head_p=*/false,
  				      declarator_p);
  	    if (cp_parser_parse_definitely (parser))
  	      return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
*************** cp_parser_unqualified_id (cp_parser* par
*** 3198,3208 ****
  	    parser->qualifying_scope = NULL_TREE;
  	    type_decl
  	      = cp_parser_class_name (parser,
  				      /*typename_keyword_p=*/false,
  				      /*template_keyword_p=*/false,
! 				      /*type_p=*/false,
  				      /*check_dependency=*/false,
  				      /*class_head_p=*/false,
  				      declarator_p);
  	    if (cp_parser_parse_definitely (parser))
  	      return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
--- 3202,3212 ----
  	    parser->qualifying_scope = NULL_TREE;
  	    type_decl
  	      = cp_parser_class_name (parser,
  				      /*typename_keyword_p=*/false,
  				      /*template_keyword_p=*/false,
! 				      none_type,
  				      /*check_dependency=*/false,
  				      /*class_head_p=*/false,
  				      declarator_p);
  	    if (cp_parser_parse_definitely (parser))
  	      return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
*************** cp_parser_unqualified_id (cp_parser* par
*** 3213,3223 ****
  	parser->qualifying_scope = NULL_TREE;
  	type_decl
  	  = cp_parser_class_name (parser,
  				  /*typename_keyword_p=*/false,
  				  /*template_keyword_p=*/false,
! 				  /*type_p=*/false,
  				  /*check_dependency=*/false,
  				  /*class_head_p=*/false,
  				  declarator_p);
  	/* If an error occurred, assume that the name of the
  	   destructor is the same as the name of the qualifying
--- 3217,3227 ----
  	parser->qualifying_scope = NULL_TREE;
  	type_decl
  	  = cp_parser_class_name (parser,
  				  /*typename_keyword_p=*/false,
  				  /*template_keyword_p=*/false,
! 				  none_type,
  				  /*check_dependency=*/false,
  				  /*class_head_p=*/false,
  				  declarator_p);
  	/* If an error occurred, assume that the name of the
  	   destructor is the same as the name of the qualifying
*************** cp_parser_class_or_namespace_name (cp_pa
*** 3577,3587 ****
    if (!only_class_p)
      cp_parser_parse_tentatively (parser);
    scope = cp_parser_class_name (parser,
  				typename_keyword_p,
  				template_keyword_p,
! 				type_p,
  				check_dependency_p,
  				/*class_head_p=*/false,
  				is_declaration);
    /* If that didn't work, try for a namespace-name.  */
    if (!only_class_p && !cp_parser_parse_definitely (parser))
--- 3581,3591 ----
    if (!only_class_p)
      cp_parser_parse_tentatively (parser);
    scope = cp_parser_class_name (parser,
  				typename_keyword_p,
  				template_keyword_p,
! 				type_p ? class_type : none_type,
  				check_dependency_p,
  				/*class_head_p=*/false,
  				is_declaration);
    /* If that didn't work, try for a namespace-name.  */
    if (!only_class_p && !cp_parser_parse_definitely (parser))
*************** cp_parser_postfix_expression (cp_parser 
*** 3813,3822 ****
--- 3817,3827 ----
  	  type = TREE_TYPE (id);
  	/* Create a TYPENAME_TYPE to represent the type to which the
  	   functional cast is being performed.  */
  	else
  	  type = make_typename_type (parser->scope, id,
+ 				     typename_type,
  				     /*complain=*/1);
  
  	postfix_expression = cp_parser_functional_cast (parser, type);
        }
        break;
*************** cp_parser_postfix_dot_deref_expression (
*** 4273,4294 ****
        /* But we do need to remember that there was an explicit scope for
  	 virtual function calls.  */
        if (parser->scope)
  	*idk = CP_ID_KIND_QUALIFIED;
  
!       if (name != error_mark_node && !BASELINK_P (name) && parser->scope)
  	{
! 	  name = build_nt (SCOPE_REF, parser->scope, name);
! 	  parser->scope = NULL_TREE;
! 	  parser->qualifying_scope = NULL_TREE;
! 	  parser->object_scope = NULL_TREE;
  	}
-       if (scope && name && BASELINK_P (name))
- 	adjust_result_of_qualified_name_lookup
- 	  (name, BINFO_TYPE (BASELINK_BINFO (name)), scope);
-       postfix_expression
- 	= finish_class_member_access_expr (postfix_expression, name);
      }
  
    /* We no longer need to look up names in the scope of the object on
       the left-hand side of the `.' or `->' operator.  */
    parser->context->object_type = NULL_TREE;
--- 4278,4309 ----
        /* But we do need to remember that there was an explicit scope for
  	 virtual function calls.  */
        if (parser->scope)
  	*idk = CP_ID_KIND_QUALIFIED;
  
!       /* If the name is a template-id that names a type, we will get a
! 	 TYPE_DECL here.  That is invalid code.  */
!       if (TREE_CODE (name) == TYPE_DECL)
  	{
! 	  error ("invalid use of %qD", name);
! 	  postfix_expression = error_mark_node;
! 	}
!       else
! 	{
! 	  if (name != error_mark_node && !BASELINK_P (name) && parser->scope)
! 	    {
! 	      name = build_nt (SCOPE_REF, parser->scope, name);
! 	      parser->scope = NULL_TREE;
! 	      parser->qualifying_scope = NULL_TREE;
! 	      parser->object_scope = NULL_TREE;
! 	    }
! 	  if (scope && name && BASELINK_P (name))
! 	    adjust_result_of_qualified_name_lookup
! 	      (name, BINFO_TYPE (BASELINK_BINFO (name)), scope);
! 	  postfix_expression
! 	    = finish_class_member_access_expr (postfix_expression, name);
  	}
      }
  
    /* We no longer need to look up names in the scope of the object on
       the left-hand side of the `.' or `->' operator.  */
    parser->context->object_type = NULL_TREE;
*************** cp_parser_mem_initializer_id (cp_parser*
*** 7657,7677 ****
       are definitely looking for a class-name.  */
    if (global_scope_p || nested_name_specifier_p)
      return cp_parser_class_name (parser,
  				 /*typename_keyword_p=*/true,
  				 /*template_keyword_p=*/template_p,
! 				 /*type_p=*/false,
  				 /*check_dependency_p=*/true,
  				 /*class_head_p=*/false,
  				 /*is_declaration=*/true);
    /* Otherwise, we could also be looking for an ordinary identifier.  */
    cp_parser_parse_tentatively (parser);
    /* Try a class-name.  */
    id = cp_parser_class_name (parser,
  			     /*typename_keyword_p=*/true,
  			     /*template_keyword_p=*/false,
! 			     /*type_p=*/false,
  			     /*check_dependency_p=*/true,
  			     /*class_head_p=*/false,
  			     /*is_declaration=*/true);
    /* If we found one, we're done.  */
    if (cp_parser_parse_definitely (parser))
--- 7672,7692 ----
       are definitely looking for a class-name.  */
    if (global_scope_p || nested_name_specifier_p)
      return cp_parser_class_name (parser,
  				 /*typename_keyword_p=*/true,
  				 /*template_keyword_p=*/template_p,
! 				 none_type,
  				 /*check_dependency_p=*/true,
  				 /*class_head_p=*/false,
  				 /*is_declaration=*/true);
    /* Otherwise, we could also be looking for an ordinary identifier.  */
    cp_parser_parse_tentatively (parser);
    /* Try a class-name.  */
    id = cp_parser_class_name (parser,
  			     /*typename_keyword_p=*/true,
  			     /*template_keyword_p=*/false,
! 			     none_type,
  			     /*check_dependency_p=*/true,
  			     /*class_head_p=*/false,
  			     /*is_declaration=*/true);
    /* If we found one, we're done.  */
    if (cp_parser_parse_definitely (parser))
*************** cp_parser_type_parameter (cp_parser* par
*** 8221,8235 ****
  		 ;
  	    else
  	      /* Look up the name.  */
  	      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
--- 8236,8250 ----
  		 ;
  	    else
  	      /* Look up the name.  */
  	      default_argument
  		= cp_parser_lookup_name (parser, default_argument,
! 					 none_type,
! 					 /*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
*** 8576,8586 ****
  	return identifier;
      }
  
    /* 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);
--- 8591,8601 ----
  	return identifier;
      }
  
    /* Look up the name.  */
    decl = cp_parser_lookup_name (parser, identifier,
! 				none_type,
  				/*is_template=*/false,
  				/*is_namespace=*/false,
  				check_dependency_p,
  				/*ambiguous_p=*/NULL);
    decl = maybe_get_template_decl_from_type_decl (decl);
*************** cp_parser_template_argument (cp_parser* 
*** 8767,8777 ****
  	 was for a class template specialization, then we will have a
  	 TYPE_DECL at this point.  There is no need to do name lookup
  	 at this point in that case.  */
        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
--- 8782,8792 ----
  	 was for a class template specialization, then we will have a
  	 TYPE_DECL at this point.  There is no need to do name lookup
  	 at this point in that case.  */
        if (TREE_CODE (argument) != TYPE_DECL)
  	argument = cp_parser_lookup_name (parser, argument,
! 					  none_type,
  					  /*is_template=*/template_p,
  					  /*is_namespace=*/false,
  					  /*check_dependency=*/true,
  					  /*ambiguous_p=*/NULL);
        if (TREE_CODE (argument) != TEMPLATE_DECL
*************** cp_parser_explicit_instantiation (cp_par
*** 8969,8980 ****
        declarator
  	= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
  				/*ctor_dtor_or_conv_p=*/NULL,
  				/*parenthesized_p=*/NULL,
  				/*member_p=*/false);
!       cp_parser_check_for_definition_in_return_type (declarator,
! 						     declares_class_or_enum);
        if (declarator != cp_error_declarator)
  	{
  	  decl = grokdeclarator (declarator, &decl_specifiers,
  				 NORMAL, 0, NULL);
  	  /* Turn access control back on for names used during
--- 8984,8996 ----
        declarator
  	= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
  				/*ctor_dtor_or_conv_p=*/NULL,
  				/*parenthesized_p=*/NULL,
  				/*member_p=*/false);
!       if (declares_class_or_enum & 2)
! 	cp_parser_check_for_definition_in_return_type (declarator,
! 						       decl_specifiers.type);
        if (declarator != cp_error_declarator)
  	{
  	  decl = grokdeclarator (declarator, &decl_specifiers,
  				 NORMAL, 0, NULL);
  	  /* Turn access control back on for names used during
*************** cp_parser_type_name (cp_parser* parser)
*** 9458,9468 ****
    cp_parser_parse_tentatively (parser);
    /* Try a class-name.  */
    type_decl = cp_parser_class_name (parser,
  				    /*typename_keyword_p=*/false,
  				    /*template_keyword_p=*/false,
! 				    /*type_p=*/false,
  				    /*check_dependency_p=*/true,
  				    /*class_head_p=*/false,
  				    /*is_declaration=*/false);
    /* If it's not a class-name, keep looking.  */
    if (!cp_parser_parse_definitely (parser))
--- 9474,9484 ----
    cp_parser_parse_tentatively (parser);
    /* Try a class-name.  */
    type_decl = cp_parser_class_name (parser,
  				    /*typename_keyword_p=*/false,
  				    /*template_keyword_p=*/false,
! 				    none_type,
  				    /*check_dependency_p=*/true,
  				    /*class_head_p=*/false,
  				    /*is_declaration=*/false);
    /* If it's not a class-name, keep looking.  */
    if (!cp_parser_parse_definitely (parser))
*************** cp_parser_elaborated_type_specifier (cp_
*** 9610,9619 ****
--- 9626,9636 ----
  	 in effect, then we must assume that, upon instantiation, the
  	 template will correspond to a class.  */
        else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
  	       && tag_type == typename_type)
  	type = make_typename_type (parser->scope, decl,
+ 				   typename_type,
  				   /*complain=*/1);
        else
  	type = TREE_TYPE (decl);
      }
  
*************** cp_parser_elaborated_type_specifier (cp_
*** 9639,9649 ****
  
  	  /* 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,
! 					/*is_type=*/true,
  					/*is_template=*/false,
  					/*is_namespace=*/false,
  					/*check_dependency=*/true,
  					/*ambiguous_p=*/NULL);
  
--- 9656,9666 ----
  
  	  /* 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,
  					/*ambiguous_p=*/NULL);
  
*************** cp_parser_namespace_name (cp_parser* par
*** 9927,9937 ****
  
       (Note that cp_parser_class_or_namespace_name only calls this
       function if the token after the name is the scope resolution
       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.  */
--- 9944,9954 ----
  
       (Note that cp_parser_class_or_namespace_name only calls this
       function if the token after the name is the scope resolution
       operator.)  */
    namespace_decl = cp_parser_lookup_name (parser, identifier,
! 					  none_type,
  					  /*is_template=*/false,
  					  /*is_namespace=*/true,
  					  /*check_dependency=*/true,
  					  /*ambiguous_p=*/NULL);
    /* If it's not a namespace, issue an error.  */
*************** cp_parser_init_declarator (cp_parser* pa
*** 10414,10425 ****
    /* If the DECLARATOR was erroneous, there's no need to go
       further.  */
    if (declarator == cp_error_declarator)
      return error_mark_node;
  
!   cp_parser_check_for_definition_in_return_type (declarator,
! 						 declares_class_or_enum);
  
    /* Figure out what scope the entity declared by the DECLARATOR is
       located in.  `grokdeclarator' sometimes changes the scope, so
       we compute it now.  */
    scope = get_scope_of_declarator (declarator);
--- 10431,10443 ----
    /* If the DECLARATOR was erroneous, there's no need to go
       further.  */
    if (declarator == cp_error_declarator)
      return error_mark_node;
  
!   if (declares_class_or_enum & 2)
!     cp_parser_check_for_definition_in_return_type (declarator,
! 						   decl_specifiers->type);
  
    /* Figure out what scope the entity declared by the DECLARATOR is
       located in.  `grokdeclarator' sometimes changes the scope, so
       we compute it now.  */
    scope = get_scope_of_declarator (declarator);
*************** cp_parser_initializer_list (cp_parser* p
*** 12098,12120 ****
  
     TYPENAME_KEYWORD_P is true iff the `typename' keyword has been used
     to indicate that names looked up in dependent types should be
     assumed to be types.  TEMPLATE_KEYWORD_P is true iff the `template'
     keyword has been used to indicate that the name that appears next
!    is a template.  TYPE_P is true iff the next name should be treated
!    as class-name, even if it is declared to be some other kind of name
!    as well.  If CHECK_DEPENDENCY_P is FALSE, names are looked up in
!    dependent scopes.  If CLASS_HEAD_P is TRUE, this class is the class
!    being defined in a class-head.
  
     Returns the TYPE_DECL representing the class.  */
  
  static tree
  cp_parser_class_name (cp_parser *parser,
  		      bool typename_keyword_p,
  		      bool template_keyword_p,
! 		      bool type_p,
  		      bool check_dependency_p,
  		      bool class_head_p,
  		      bool is_declaration)
  {
    tree decl;
--- 12116,12137 ----
  
     TYPENAME_KEYWORD_P is true iff the `typename' keyword has been used
     to indicate that names looked up in dependent types should be
     assumed to be types.  TEMPLATE_KEYWORD_P is true iff the `template'
     keyword has been used to indicate that the name that appears next
!    is a template.  TAG_TYPE indicates the explicit tag given before
!    the type name, if any.  If CHECK_DEPENDENCY_P is FALSE, names are
!    looked up in dependent scopes.  If CLASS_HEAD_P is TRUE, this class
!    is the class being defined in a class-head.
  
     Returns the TYPE_DECL representing the class.  */
  
  static tree
  cp_parser_class_name (cp_parser *parser,
  		      bool typename_keyword_p,
  		      bool template_keyword_p,
! 		      enum tag_types tag_type,
  		      bool check_dependency_p,
  		      bool class_head_p,
  		      bool is_declaration)
  {
    tree decl;
*************** cp_parser_class_name (cp_parser *parser,
*** 12166,12179 ****
  
  	     During the lookup for a name preceding the :: scope
  	     resolution operator, object, function, and enumerator
  	     names are ignored.  */
  	  if (cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))
! 	    type_p = true;
  	  /* 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);
  	}
--- 12183,12196 ----
  
  	     During the lookup for a name preceding the :: scope
  	     resolution operator, object, function, and enumerator
  	     names are ignored.  */
  	  if (cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))
! 	    tag_type = typename_type;
  	  /* Look up the name.  */
  	  decl = cp_parser_lookup_name (parser, identifier,
! 					tag_type,
  					/*is_template=*/false,
  					/*is_namespace=*/false,
  					check_dependency_p,
  					/*ambiguous_p=*/NULL);
  	}
*************** cp_parser_class_name (cp_parser *parser,
*** 12191,12201 ****
    decl = cp_parser_maybe_treat_template_as_class (decl, class_head_p);
  
    /* If this is a typename, create a TYPENAME_TYPE.  */
    if (typename_p && decl != error_mark_node)
      {
!       decl = make_typename_type (scope, decl, /*complain=*/1);
        if (decl != error_mark_node)
  	decl = TYPE_NAME (decl);
      }
  
    /* Check to see that it is really the name of a class.  */
--- 12208,12218 ----
    decl = cp_parser_maybe_treat_template_as_class (decl, class_head_p);
  
    /* If this is a typename, create a TYPENAME_TYPE.  */
    if (typename_p && decl != error_mark_node)
      {
!       decl = make_typename_type (scope, decl, typename_type, /*complain=*/1);
        if (decl != error_mark_node)
  	decl = TYPE_NAME (decl);
      }
  
    /* Check to see that it is really the name of a class.  */
*************** cp_parser_class_name (cp_parser *parser,
*** 12210,12220 ****
  
         are problematic.  Is `T::template X<int>' a class-name?  The
         standard does not seem to be definitive, but there is no other
         valid interpretation of the following `::'.  Therefore, those
         names are considered class-names.  */
!     decl = TYPE_NAME (make_typename_type (scope, decl, tf_error));
    else if (decl == error_mark_node
  	   || TREE_CODE (decl) != TYPE_DECL
  	   || !IS_AGGR_TYPE (TREE_TYPE (decl)))
      {
        cp_parser_error (parser, "expected class-name");
--- 12227,12237 ----
  
         are problematic.  Is `T::template X<int>' a class-name?  The
         standard does not seem to be definitive, but there is no other
         valid interpretation of the following `::'.  Therefore, those
         names are considered class-names.  */
!     decl = TYPE_NAME (make_typename_type (scope, decl, tag_type, tf_error));
    else if (decl == error_mark_node
  	   || TREE_CODE (decl) != TYPE_DECL
  	   || !IS_AGGR_TYPE (TREE_TYPE (decl)))
      {
        cp_parser_error (parser, "expected class-name");
*************** cp_parser_class_head (cp_parser* parser,
*** 12498,12508 ****
  	 template-name first we would stop after the template-name.  */
        cp_parser_parse_tentatively (parser);
        type = cp_parser_class_name (parser,
  				   /*typename_keyword_p=*/false,
  				   /*template_keyword_p=*/false,
! 				   /*type_p=*/true,
  				   /*check_dependency_p=*/false,
  				   /*class_head_p=*/true,
  				   /*is_declaration=*/false);
        /* If that didn't work, ignore the nested-name-specifier.  */
        if (!cp_parser_parse_definitely (parser))
--- 12515,12525 ----
  	 template-name first we would stop after the template-name.  */
        cp_parser_parse_tentatively (parser);
        type = cp_parser_class_name (parser,
  				   /*typename_keyword_p=*/false,
  				   /*template_keyword_p=*/false,
! 				   class_type,
  				   /*check_dependency_p=*/false,
  				   /*class_head_p=*/true,
  				   /*is_declaration=*/false);
        /* If that didn't work, ignore the nested-name-specifier.  */
        if (!cp_parser_parse_definitely (parser))
*************** cp_parser_member_declaration (cp_parser*
*** 13056,13067 ****
  					      CPP_SEMICOLON))
  		    cp_lexer_consume_token (parser->lexer);
  		  return;
  		}
  
! 	      cp_parser_check_for_definition_in_return_type
! 		(declarator, declares_class_or_enum);
  
  	      /* Look for an asm-specification.  */
  	      asm_specification = cp_parser_asm_specification_opt (parser);
  	      /* Look for attributes that apply to the declaration.  */
  	      attributes = cp_parser_attributes_opt (parser);
--- 13073,13085 ----
  					      CPP_SEMICOLON))
  		    cp_lexer_consume_token (parser->lexer);
  		  return;
  		}
  
! 	      if (declares_class_or_enum & 2)
! 		cp_parser_check_for_definition_in_return_type
! 		  (declarator, decl_specifiers.type);
  
  	      /* Look for an asm-specification.  */
  	      asm_specification = cp_parser_asm_specification_opt (parser);
  	      /* Look for attributes that apply to the declaration.  */
  	      attributes = cp_parser_attributes_opt (parser);
*************** cp_parser_base_specifier (cp_parser* par
*** 13412,13433 ****
       is to pretend that we have seen the `typename' keyword at this
       point.  */
    cp_parser_nested_name_specifier_opt (parser,
  				       /*typename_keyword_p=*/true,
  				       /*check_dependency_p=*/true,
! 				       /*type_p=*/true,
  				       /*is_declaration=*/true);
    /* If the base class is given by a qualified name, assume that names
       we see are type names or templates, as appropriate.  */
    class_scope_p = (parser->scope && TYPE_P (parser->scope));
    template_p = class_scope_p && cp_parser_optional_template_keyword (parser);
  
    /* Finally, look for the class-name.  */
    type = cp_parser_class_name (parser,
  			       class_scope_p,
  			       template_p,
! 			       /*type_p=*/true,
  			       /*check_dependency_p=*/true,
  			       /*class_head_p=*/false,
  			       /*is_declaration=*/true);
  
    if (type == error_mark_node)
--- 13430,13451 ----
       is to pretend that we have seen the `typename' keyword at this
       point.  */
    cp_parser_nested_name_specifier_opt (parser,
  				       /*typename_keyword_p=*/true,
  				       /*check_dependency_p=*/true,
! 				       typename_type,
  				       /*is_declaration=*/true);
    /* If the base class is given by a qualified name, assume that names
       we see are type names or templates, as appropriate.  */
    class_scope_p = (parser->scope && TYPE_P (parser->scope));
    template_p = class_scope_p && cp_parser_optional_template_keyword (parser);
  
    /* Finally, look for the class-name.  */
    type = cp_parser_class_name (parser,
  			       class_scope_p,
  			       template_p,
! 			       typename_type,
  			       /*check_dependency_p=*/true,
  			       /*class_head_p=*/false,
  			       /*is_declaration=*/true);
  
    if (type == error_mark_node)
*************** cp_parser_label_declaration (cp_parser* 
*** 14047,14058 ****
     In cases not explicitly covered above, this function returns a
     DECL, OVERLOAD, or baselink representing the result of the lookup.
     If there was no entity with the indicated NAME, the ERROR_MARK_NODE
     is returned.
  
!    If IS_TYPE is TRUE, bindings that do not refer to types are
!    ignored.
  
     If IS_TEMPLATE is TRUE, bindings that do not refer to templates are
     ignored.
  
     If IS_NAMESPACE is TRUE, bindings that do not refer to namespaces
--- 14065,14077 ----
     In cases not explicitly covered above, this function returns a
     DECL, OVERLOAD, or baselink representing the result of the lookup.
     If there was no entity with the indicated NAME, the ERROR_MARK_NODE
     is returned.
  
!    If TAG_TYPE is not NONE_TYPE, it inidcates an explicit type keyword
!    (e.g., "struct") that was used.  In that case bindings that do not
!    refer to types are ignored.
  
     If IS_TEMPLATE is TRUE, bindings that do not refer to templates are
     ignored.
  
     If IS_NAMESPACE is TRUE, bindings that do not refer to namespaces
*************** cp_parser_label_declaration (cp_parser* 
*** 14064,14074 ****
     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;
--- 14083,14094 ----
     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,
! 		       enum tag_types tag_type,
! 		       bool is_template, bool is_namespace,
  		       bool check_dependency,
  		       bool *ambiguous_p)
  {
    tree decl;
    tree object_type = parser->context->object_type;
*************** cp_parser_lookup_name (cp_parser *parser
*** 14142,14158 ****
  			  && currently_open_class (parser->scope))
  		     && dependent_type_p (parser->scope));
        if ((check_dependency || !CLASS_TYPE_P (parser->scope))
  	   && dependent_p)
  	{
! 	  if (is_type)
! 	    /* The resolution to Core Issue 180 says that `struct A::B'
! 	       should be considered a type-name, even if `A' is
! 	       dependent.  */
! 	    decl = TYPE_NAME (make_typename_type (parser->scope,
! 						  name,
! 						  /*complain=*/1));
  	  else if (is_template)
  	    decl = make_unbound_class_template (parser->scope,
  						name, NULL_TREE,
  						/*complain=*/1);
  	  else
--- 14162,14186 ----
  			  && currently_open_class (parser->scope))
  		     && dependent_type_p (parser->scope));
        if ((check_dependency || !CLASS_TYPE_P (parser->scope))
  	   && dependent_p)
  	{
! 	  if (tag_type)
! 	    {
! 	      tree type;
! 
! 	      /* The resolution to Core Issue 180 says that `struct
! 		 A::B' should be considered a type-name, even if `A'
! 		 is dependent.  */
! 	      type = make_typename_type (parser->scope, name, tag_type,
! 					 /*complain=*/1);
! 	      if (tag_type == enum_type)
! 		TYPENAME_IS_ENUM_P (type) = 1;
! 	      else if (tag_type != typename_type)
! 		TYPENAME_IS_CLASS_P (type) = 1;
! 	      decl = TYPE_NAME (type);
! 	    }
  	  else if (is_template)
  	    decl = make_unbound_class_template (parser->scope,
  						name, NULL_TREE,
  						/*complain=*/1);
  	  else
*************** cp_parser_lookup_name (cp_parser *parser
*** 14171,14181 ****
  	    pop_p = push_scope (parser->scope);
  	  /* If the PARSER->SCOPE is a a template specialization, it
  	     may be instantiated during name lookup.  In that case,
  	     errors may be issued.  Even if we rollback the current
  	     tentative parse, those errors are valid.  */
! 	  decl = lookup_qualified_name (parser->scope, name, is_type,
  					/*complain=*/true);
  	  if (pop_p)
  	    pop_scope (parser->scope);
  	}
        parser->qualifying_scope = parser->scope;
--- 14199,14210 ----
  	    pop_p = push_scope (parser->scope);
  	  /* If the PARSER->SCOPE is a a template specialization, it
  	     may be instantiated during name lookup.  In that case,
  	     errors may be issued.  Even if we rollback the current
  	     tentative parse, those errors are valid.  */
! 	  decl = lookup_qualified_name (parser->scope, name, 
! 					tag_type != none_type, 
  					/*complain=*/true);
  	  if (pop_p)
  	    pop_scope (parser->scope);
  	}
        parser->qualifying_scope = parser->scope;
*************** cp_parser_lookup_name (cp_parser *parser
*** 14191,14213 ****
  	   be instantiated during name lookup.  In that case, errors
  	   may be issued.  Even if we rollback the current tentative
  	   parse, those errors are valid.  */
  	object_decl = lookup_member (object_type,
  				     name,
! 				     /*protect=*/0, is_type);
        /* Look it up in the enclosing context, too.  */
!       decl = lookup_name_real (name, is_type, /*nonclass=*/0,
  			       /*block_p=*/true, is_namespace,
  			       /*flags=*/0);
        parser->object_scope = object_type;
        parser->qualifying_scope = NULL_TREE;
        if (object_decl)
  	decl = object_decl;
      }
    else
      {
!       decl = lookup_name_real (name, is_type, /*nonclass=*/0,
  			       /*block_p=*/true, is_namespace,
  			       /*flags=*/0);
        parser->qualifying_scope = NULL_TREE;
        parser->object_scope = NULL_TREE;
      }
--- 14220,14245 ----
  	   be instantiated during name lookup.  In that case, errors
  	   may be issued.  Even if we rollback the current tentative
  	   parse, those errors are valid.  */
  	object_decl = lookup_member (object_type,
  				     name,
! 				     /*protect=*/0, 
! 				     tag_type != none_type);
        /* Look it up in the enclosing context, too.  */
!       decl = lookup_name_real (name, tag_type != none_type, 
! 			       /*nonclass=*/0,
  			       /*block_p=*/true, is_namespace,
  			       /*flags=*/0);
        parser->object_scope = object_type;
        parser->qualifying_scope = NULL_TREE;
        if (object_decl)
  	decl = object_decl;
      }
    else
      {
!       decl = lookup_name_real (name, tag_type != none_type, 
! 			       /*nonclass=*/0,
  			       /*block_p=*/true, is_namespace,
  			       /*flags=*/0);
        parser->qualifying_scope = NULL_TREE;
        parser->object_scope = NULL_TREE;
      }
*************** cp_parser_lookup_name (cp_parser *parser
*** 14259,14269 ****
  
  static tree
  cp_parser_lookup_name_simple (cp_parser* parser, tree name)
  {
    return cp_parser_lookup_name (parser, name,
! 				/*is_type=*/false,
  				/*is_template=*/false,
  				/*is_namespace=*/false,
  				/*check_dependency=*/true,
  				/*ambiguous_p=*/NULL);
  }
--- 14291,14301 ----
  
  static tree
  cp_parser_lookup_name_simple (cp_parser* parser, tree name)
  {
    return cp_parser_lookup_name (parser, name,
! 				none_type,
  				/*is_template=*/false,
  				/*is_namespace=*/false,
  				/*check_dependency=*/true,
  				/*ambiguous_p=*/NULL);
  }
*************** cp_parser_constructor_declarator_p (cp_p
*** 14517,14527 ****
  
  	 we must recognize that the nested `S' names a template.  */
        type_decl = cp_parser_class_name (parser,
  					/*typename_keyword_p=*/false,
  					/*template_keyword_p=*/false,
! 					/*type_p=*/false,
  					/*check_dependency_p=*/false,
  					/*class_head_p=*/false,
  					/*is_declaration=*/false);
        /* If there was no class-name, then this is not a constructor.  */
        constructor_p = !cp_parser_error_occurred (parser);
--- 14549,14559 ----
  
  	 we must recognize that the nested `S' names a template.  */
        type_decl = cp_parser_class_name (parser,
  					/*typename_keyword_p=*/false,
  					/*template_keyword_p=*/false,
! 					none_type,
  					/*check_dependency_p=*/false,
  					/*class_head_p=*/false,
  					/*is_declaration=*/false);
        /* If there was no class-name, then this is not a constructor.  */
        constructor_p = !cp_parser_error_occurred (parser);
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.949
diff -c -5 -p -r1.949 pt.c
*** cp/pt.c	25 Nov 2004 17:11:37 -0000	1.949
--- cp/pt.c	29 Nov 2004 19:17:44 -0000
*************** static tree tsubst_template_parms (tree,
*** 138,148 ****
  static void regenerate_decl_from_template (tree, tree);
  static tree most_specialized (tree, tree, tree);
  static tree most_specialized_class (tree, tree);
  static int template_class_depth_real (tree, int);
  static tree tsubst_aggr_type (tree, tree, tsubst_flags_t, tree, int);
- static tree tsubst_decl (tree, tree, tree, tsubst_flags_t);
  static tree tsubst_arg_types (tree, tree, tsubst_flags_t, tree);
  static tree tsubst_function_type (tree, tree, tsubst_flags_t, tree);
  static void check_specialization_scope (void);
  static tree process_partial_specialization (tree);
  static void set_current_access_from_decl (tree);
--- 138,147 ----
*************** convert_template_argument (tree parm, 
*** 3827,3836 ****
--- 3826,3836 ----
        pedwarn ("to refer to a type member of a template parameter, "
                 "use %<typename %E%>", arg);
        
        arg = make_typename_type (TREE_OPERAND (arg, 0),
  				TREE_OPERAND (arg, 1),
+ 				typename_type,
  				complain & tf_error);
        is_type = 1;
      }
    if (is_type != requires_type)
      {
*************** tsubst_default_arguments (tree fn)
*** 6134,6150 ****
        TREE_PURPOSE (arg) = tsubst_default_argument (fn, 
  						    TREE_VALUE (arg),
  						    TREE_PURPOSE (arg));
  }
  
! /* Substitute the ARGS into the T, which is a _DECL.  TYPE is the
!    (already computed) substitution of ARGS into TREE_TYPE (T), if
!    appropriate.  Return the result of the substitution.  Issue error
!    and warning messages under control of COMPLAIN.  */
  
  static tree
! tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
  {
    location_t saved_loc;
    tree r = NULL_TREE;
    tree in_decl = t;
  
--- 6134,6149 ----
        TREE_PURPOSE (arg) = tsubst_default_argument (fn, 
  						    TREE_VALUE (arg),
  						    TREE_PURPOSE (arg));
  }
  
! /* Substitute the ARGS into the T, which is a _DECL.  Return the
!    result of the substitution.  Issue error and warning messages under
!    control of COMPLAIN.  */
  
  static tree
! tsubst_decl (tree t, tree args, tsubst_flags_t complain)
  {
    location_t saved_loc;
    tree r = NULL_TREE;
    tree in_decl = t;
  
*************** tsubst_decl (tree t, tree args, tree typ
*** 6261,6270 ****
--- 6260,6270 ----
        {
  	tree ctx;
  	tree argvec = NULL_TREE;
  	tree *friends;
  	tree gen_tmpl;
+ 	tree type;
  	int member;
  	int args_depth;
  	int parms_depth;
  
  	/* Nobody should be tsubst'ing into non-template functions.  */
*************** tsubst_decl (tree t, tree args, tree typ
*** 6370,6380 ****
  	else
  	  {
  	    member = 0;
  	    ctx = DECL_CONTEXT (t);
  	  }
! 	type = tsubst (type, args, complain, in_decl);
  	if (type == error_mark_node)
  	  return error_mark_node;
  
  	/* We do NOT check for matching decls pushed separately at this
             point, as they may not represent instantiations of this
--- 6370,6380 ----
  	else
  	  {
  	    member = 0;
  	    ctx = DECL_CONTEXT (t);
  	  }
! 	type = tsubst (TREE_TYPE (t), args, complain, in_decl);
  	if (type == error_mark_node)
  	  return error_mark_node;
  
  	/* We do NOT check for matching decls pushed separately at this
             point, as they may not represent instantiations of this
*************** tsubst_decl (tree t, tree args, tree typ
*** 6479,6492 ****
--- 6479,6495 ----
        }
        break;
  
      case PARM_DECL:
        {
+ 	tree type;
+ 
  	r = copy_node (t);
  	if (DECL_TEMPLATE_PARM_P (t))
  	  SET_DECL_TEMPLATE_PARM_P (r);
  
+ 	type = tsubst (TREE_TYPE (t), args, complain, in_decl);
  	TREE_TYPE (r) = type;
  	c_apply_type_quals_to_decl (cp_type_quals (type), r);
  
  	if (DECL_INITIAL (r))
  	  {
*************** tsubst_decl (tree t, tree args, tree typ
*** 6507,6517 ****
--- 6510,6525 ----
        }
        break;
  
      case FIELD_DECL:
        {
+ 	tree type;
+ 
  	r = copy_decl (t);
+ 	type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ 	if (type == error_mark_node)
+ 	  return error_mark_node;
  	TREE_TYPE (r) = type;
  	c_apply_type_quals_to_decl (cp_type_quals (type), r);
  
  	/* We don't have to set DECL_CONTEXT here; it is set by
  	   finish_member_declaration.  */
*************** tsubst_decl (tree t, tree args, tree typ
*** 6535,6566 ****
  	TREE_CHAIN (r) = NULL_TREE;
        }
        break;
  
      case TYPE_DECL:
-       if (TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM
- 	  || t == TYPE_MAIN_DECL (TREE_TYPE (t)))
- 	{
- 	  /* If this is the canonical decl, we don't have to mess with
-              instantiations, and often we can't (for typename, template
- 	     type parms and such).  Note that TYPE_NAME is not correct for
- 	     the above test if we've copied the type for a typedef.  */
- 	  r = TYPE_NAME (type);
- 	  break;
- 	}
- 
-       /* Fall through.  */
- 
      case VAR_DECL:
        {
  	tree argvec = NULL_TREE;
  	tree gen_tmpl = NULL_TREE;
  	tree spec;
  	tree tmpl = NULL_TREE;
  	tree ctx;
  	int local_p;
  
  	/* Assume this is a non-local variable.  */
  	local_p = 0;
  
  	if (TYPE_P (CP_DECL_CONTEXT (t)))
  	  ctx = tsubst_aggr_type (DECL_CONTEXT (t), args, 
--- 6543,6578 ----
  	TREE_CHAIN (r) = NULL_TREE;
        }
        break;
  
      case TYPE_DECL:
      case VAR_DECL:
        {
  	tree argvec = NULL_TREE;
  	tree gen_tmpl = NULL_TREE;
  	tree spec;
  	tree tmpl = NULL_TREE;
  	tree ctx;
+ 	tree type = NULL_TREE;
  	int local_p;
  
+ 	if (TREE_CODE (t) == TYPE_DECL)
+ 	  {
+ 	    type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ 	    if (TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM
+ 		|| t == TYPE_MAIN_DECL (TREE_TYPE (t)))
+ 	      {
+ 		/* If this is the canonical decl, we don't have to
+ 		   mess with instantiations, and often we can't (for
+ 		   typename, template type parms and such).  Note that
+ 		   TYPE_NAME is not correct for the above test if
+ 		   we've copied the type for a typedef.  */
+ 		r = TYPE_NAME (type);
+ 		break;
+ 	      }
+ 	  }
+ 	
  	/* Assume this is a non-local variable.  */
  	local_p = 0;
  
  	if (TYPE_P (CP_DECL_CONTEXT (t)))
  	  ctx = tsubst_aggr_type (DECL_CONTEXT (t), args, 
*************** tsubst_decl (tree t, tree args, tree typ
*** 6594,6603 ****
--- 6606,6618 ----
  	  }
  
  	r = copy_decl (t);
  	if (TREE_CODE (r) == VAR_DECL)
  	  {
+ 	    type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ 	    if (type == error_mark_node)
+ 	      return error_mark_node;
  	    type = complete_type (type);
  	    DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r)
  	      = DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (t);
  	    type = check_var_type (DECL_NAME (r), type);
  	  }
*************** tsubst (tree t, tree args, tsubst_flags_
*** 6879,6908 ****
        || t == char_type_node
        || t == unknown_type_node
        || TREE_CODE (t) == NAMESPACE_DECL)
      return t;
  
    if (TREE_CODE (t) == IDENTIFIER_NODE)
      type = IDENTIFIER_TYPE_VALUE (t);
    else
      type = TREE_TYPE (t);
  
    gcc_assert (type != unknown_type_node);
  
!   if (type && TREE_CODE (t) != FUNCTION_DECL
        && TREE_CODE (t) != TYPENAME_TYPE
-       && TREE_CODE (t) != TEMPLATE_DECL
        && TREE_CODE (t) != IDENTIFIER_NODE
        && TREE_CODE (t) != FUNCTION_TYPE
        && TREE_CODE (t) != METHOD_TYPE)
      type = tsubst (type, args, complain, in_decl);
    if (type == error_mark_node)
      return error_mark_node;
  
-   if (DECL_P (t))
-     return tsubst_decl (t, args, type, complain);
- 
    switch (TREE_CODE (t))
      {
      case RECORD_TYPE:
      case UNION_TYPE:
      case ENUMERAL_TYPE:
--- 6894,6922 ----
        || t == char_type_node
        || t == unknown_type_node
        || TREE_CODE (t) == NAMESPACE_DECL)
      return t;
  
+   if (DECL_P (t))
+     return tsubst_decl (t, args, complain);
+ 
    if (TREE_CODE (t) == IDENTIFIER_NODE)
      type = IDENTIFIER_TYPE_VALUE (t);
    else
      type = TREE_TYPE (t);
  
    gcc_assert (type != unknown_type_node);
  
!   if (type
        && TREE_CODE (t) != TYPENAME_TYPE
        && TREE_CODE (t) != IDENTIFIER_NODE
        && TREE_CODE (t) != FUNCTION_TYPE
        && TREE_CODE (t) != METHOD_TYPE)
      type = tsubst (type, args, complain, in_decl);
    if (type == error_mark_node)
      return error_mark_node;
  
    switch (TREE_CODE (t))
      {
      case RECORD_TYPE:
      case UNION_TYPE:
      case ENUMERAL_TYPE:
*************** tsubst (tree t, tree args, tsubst_flags_
*** 7358,7377 ****
  		  cxx_incomplete_type_error (NULL_TREE, ctx);
  		return error_mark_node;
  	      }
  	  }
  
! 	f = make_typename_type (ctx, f,
  				(complain & tf_error) | tf_keep_type_decl);
  	if (f == error_mark_node)
  	  return f;
   	if (TREE_CODE (f) == TYPE_DECL)
   	  {
  	    complain |= tf_ignore_bad_quals;
   	    f = TREE_TYPE (f);
   	  }
   	
   	return cp_build_qualified_type_real
   	  (f, cp_type_quals (f) | cp_type_quals (t), complain);
        }
  	       
      case UNBOUND_CLASS_TEMPLATE:
--- 7372,7401 ----
  		  cxx_incomplete_type_error (NULL_TREE, ctx);
  		return error_mark_node;
  	      }
  	  }
  
! 	f = make_typename_type (ctx, f, typename_type,
  				(complain & tf_error) | tf_keep_type_decl);
  	if (f == error_mark_node)
  	  return f;
   	if (TREE_CODE (f) == TYPE_DECL)
   	  {
  	    complain |= tf_ignore_bad_quals;
   	    f = TREE_TYPE (f);
   	  }
   	
+ 	if (TREE_CODE (f) != TYPENAME_TYPE)
+ 	  {
+ 	    if (TYPENAME_IS_ENUM_P (t) && TREE_CODE (f) != ENUMERAL_TYPE)
+ 	      error ("%qT resolves to %qT, which is not an enumeration type", 
+ 		     t, f);
+ 	    else if (TYPENAME_IS_CLASS_P (t) && !CLASS_TYPE_P (f))
+ 	      error ("%qT resolves to %qT, which is is not a class type", 
+ 		     t, f);
+ 	  }
+ 
   	return cp_build_qualified_type_real
   	  (f, cp_type_quals (f) | cp_type_quals (t), complain);
        }
  	       
      case UNBOUND_CLASS_TEMPLATE:
Index: testsuite/g++.dg/template/crash29.C
===================================================================
RCS file: testsuite/g++.dg/template/crash29.C
diff -N testsuite/g++.dg/template/crash29.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/crash29.C	29 Nov 2004 19:17:45 -0000
***************
*** 0 ****
--- 1,8 ----
+ // PR c++/18512
+ 
+ template <int> struct A {};
+ 
+ struct B : A<0>
+ {
+   void foo() { this->A<0>; } // { dg-error "" }
+ };
Index: testsuite/g++.old-deja/g++.brendan/crash16.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.old-deja/g++.brendan/crash16.C,v
retrieving revision 1.5
diff -c -5 -p -r1.5 crash16.C
*** testsuite/g++.old-deja/g++.brendan/crash16.C	23 Sep 2004 21:27:18 -0000	1.5
--- testsuite/g++.old-deja/g++.brendan/crash16.C	29 Nov 2004 19:17:45 -0000
*************** class Graph {
*** 4,12 ****
  public:
        unsigned         char N;
        Graph(void) {}; // { dg-error "previously defined here" }
  }
  
! Graph::Graph(void)    // { dg-error "return type|redefinition" }
  {    N = 10;
  }
  
--- 4,12 ----
  public:
        unsigned         char N;
        Graph(void) {}; // { dg-error "previously defined here" }
  }
  
! Graph::Graph(void)    // { dg-error "return type|redefinition|semicolon" }
  {    N = 10;
  }
  
Index: testsuite/g++.old-deja/g++.law/ctors5.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.old-deja/g++.law/ctors5.C,v
retrieving revision 1.5
diff -c -5 -p -r1.5 ctors5.C
*** testsuite/g++.old-deja/g++.law/ctors5.C	23 Sep 2004 21:27:20 -0000	1.5
--- testsuite/g++.old-deja/g++.law/ctors5.C	29 Nov 2004 19:17:49 -0000
*************** class Y
*** 18,28 ****
    private:
      X xx;
    public:
      Y();
  }
! X::X( int xi ) // { dg-error "return type|X::X" }
  {
      x = xi;
  }
  
  const X X::x0( 0 );
--- 18,28 ----
    private:
      X xx;
    public:
      Y();
  }
! X::X( int xi ) // { dg-error "return type|X::X|semicolon" }
  {
      x = xi;
  }
  
  const X X::x0( 0 );
Index: testsuite/g++.old-deja/g++.other/crash25.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.old-deja/g++.other/crash25.C,v
retrieving revision 1.6
diff -c -5 -p -r1.6 crash25.C
*** testsuite/g++.old-deja/g++.other/crash25.C	23 Sep 2004 21:27:21 -0000	1.6
--- testsuite/g++.old-deja/g++.other/crash25.C	29 Nov 2004 19:17:49 -0000
*************** class X {
*** 5,15 ****
  public:
    X();
    virtual ~X();
  }
  
! X::x()	// { dg-error "return type|member function" }
  {
  }
  
  X::~x()	// { dg-error "expected class-name" }
  {				
--- 5,15 ----
  public:
    X();
    virtual ~X();
  }
  
! X::x()	// { dg-error "return type|member function|semicolon" }
  {
  }
  
  X::~x()	// { dg-error "expected class-name" }
  {				
Index: testsuite/g++.dg/template/error16.C
===================================================================
RCS file: testsuite/g++.dg/template/error16.C
diff -N testsuite/g++.dg/template/error16.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/template/error16.C	29 Nov 2004 20:05:53 -0000
***************
*** 0 ****
--- 1,16 ----
+ // PR c++/18674
+ 
+ template <typename I>
+ static void g() {
+   enum I::t a; // { dg-error "" }
+   (void) a;
+ }
+ 
+ struct B {
+   typedef int t;
+ };
+ 
+ void h()
+ {
+   g<B>();
+ }


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