Commit fc6a28d7 by Mark Mitchell Committed by Mark Mitchell

re PR c++/18368 (C++ error message regression)

	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.

	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.

From-SVN: r91483
parent b7034e06
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 Daniel Jacobowitz <dan@codesourcery.com> 2004-11-29 Daniel Jacobowitz <dan@codesourcery.com>
PR c/7544 PR c/7544
......
...@@ -182,9 +182,7 @@ DEFTREECODE (BOUND_TEMPLATE_TEMPLATE_PARM, "bound_template_template_parm", ...@@ -182,9 +182,7 @@ DEFTREECODE (BOUND_TEMPLATE_TEMPLATE_PARM, "bound_template_template_parm",
/* A type designated by `typename T::t'. TYPE_CONTEXT is `T', /* 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 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. template-id, TYPENAME_TYPE_FULLNAME will hold the TEMPLATE_ID_EXPR.
If TREE_TYPE is present, this type was generated by the implicit TREE_TYPE is always NULL. */
typename extension, and the TREE_TYPE is a _TYPE from a baseclass
of `T'. */
DEFTREECODE (TYPENAME_TYPE, "typename_type", tcc_type, 0) DEFTREECODE (TYPENAME_TYPE, "typename_type", tcc_type, 0)
/* For template template argument of the form `T::template C'. /* For template template argument of the form `T::template C'.
......
...@@ -47,6 +47,7 @@ struct diagnostic_context; ...@@ -47,6 +47,7 @@ struct diagnostic_context;
STATEMENT_LIST_NO_SCOPE (in STATEMENT_LIST). STATEMENT_LIST_NO_SCOPE (in STATEMENT_LIST).
EXPR_STMT_STMT_EXPR_RESULT (in EXPR_STMT) EXPR_STMT_STMT_EXPR_RESULT (in EXPR_STMT)
BIND_EXPR_TRY_BLOCK (in BIND_EXPR) BIND_EXPR_TRY_BLOCK (in BIND_EXPR)
TYPENAME_IS_ENUM_P (in TYPENAME_TYPE)
1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE) 1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)
TI_PENDING_TEMPLATE_FLAG. TI_PENDING_TEMPLATE_FLAG.
TEMPLATE_PARMS_FOR_INLINE. TEMPLATE_PARMS_FOR_INLINE.
...@@ -54,6 +55,7 @@ struct diagnostic_context; ...@@ -54,6 +55,7 @@ struct diagnostic_context;
(TREE_CALLS_NEW) (in _EXPR or _REF) (commented-out). (TREE_CALLS_NEW) (in _EXPR or _REF) (commented-out).
ICS_ELLIPSIS_FLAG (in _CONV) ICS_ELLIPSIS_FLAG (in _CONV)
DECL_INITIALIZED_P (in VAR_DECL) DECL_INITIALIZED_P (in VAR_DECL)
TYPENAME_IS_CLASS_P (in TYPENAME_TYPE)
2: IDENTIFIER_OPNAME_P (in IDENTIFIER_NODE) 2: IDENTIFIER_OPNAME_P (in IDENTIFIER_NODE)
ICS_THIS_FLAG (in _CONV) ICS_THIS_FLAG (in _CONV)
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL) DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL)
...@@ -2254,6 +2256,15 @@ struct lang_decl GTY(()) ...@@ -2254,6 +2256,15 @@ struct lang_decl GTY(())
TEMPLATE_ID_EXPR if we had something like `typename X::Y<T>'. */ TEMPLATE_ID_EXPR if we had something like `typename X::Y<T>'. */
#define TYPENAME_TYPE_FULLNAME(NODE) (TYPENAME_TYPE_CHECK (NODE))->type.values #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 /* Nonzero in INTEGER_CST means that this int is negative by dint of
using a twos-complement negated operand. */ using a twos-complement negated operand. */
#define TREE_NEGATED_INT(NODE) TREE_LANG_FLAG_0 (INTEGER_CST_CHECK (NODE)) #define TREE_NEGATED_INT(NODE) TREE_LANG_FLAG_0 (INTEGER_CST_CHECK (NODE))
...@@ -3718,7 +3729,7 @@ extern tree declare_local_label (tree); ...@@ -3718,7 +3729,7 @@ extern tree declare_local_label (tree);
extern tree define_label (location_t, tree); extern tree define_label (location_t, tree);
extern void check_goto (tree); extern void check_goto (tree);
extern void define_case_label (void); extern void define_case_label (void);
extern tree make_typename_type (tree, tree, tsubst_flags_t); 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 make_unbound_class_template (tree, tree, tree, tsubst_flags_t);
extern tree check_for_out_of_scope_variable (tree); extern tree check_for_out_of_scope_variable (tree);
extern tree build_library_fn (tree, tree); extern tree build_library_fn (tree, tree);
......
...@@ -121,7 +121,6 @@ static void initialize_local_var (tree, tree); ...@@ -121,7 +121,6 @@ static void initialize_local_var (tree, tree);
static void expand_static_init (tree, tree); static void expand_static_init (tree, tree);
static tree next_initializable_field (tree); static tree next_initializable_field (tree);
static tree reshape_init (tree, 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. */ /* Erroneous argument lists can use this *IFF* they do not modify it. */
tree error_mark_list; tree error_mark_list;
...@@ -2538,83 +2537,101 @@ typename_hash (const void* k) ...@@ -2538,83 +2537,101 @@ typename_hash (const void* k)
return hash; 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'. */ /* Compare two TYPENAME_TYPEs. K1 and K2 are really of type `tree'. */
static int static int
typename_compare (const void * k1, const void * k2) typename_compare (const void * k1, const void * k2)
{ {
tree t1; tree t1;
tree t2; const typename_info *t2;
tree d1;
tree d2;
t1 = (tree) k1; t1 = (tree) k1;
t2 = (tree) k2; t2 = (const typename_info *) k2;
d1 = TYPE_NAME (t1);
d2 = TYPE_NAME (t2);
return (DECL_NAME (d1) == DECL_NAME (d2) return (DECL_NAME (TYPE_NAME (t1)) == t2->name
&& TYPE_CONTEXT (t1) == TYPE_CONTEXT (t2) && TYPE_CONTEXT (t1) == t2->scope
&& ((TREE_TYPE (t1) != NULL_TREE) && TYPENAME_TYPE_FULLNAME (t1) == t2->template_id
== (TREE_TYPE (t2) != NULL_TREE)) && TYPENAME_IS_ENUM_P (t1) == t2->enum_p
&& same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)) && TYPENAME_IS_CLASS_P (t1) == t2->class_p);
&& TYPENAME_TYPE_FULLNAME (t1) == TYPENAME_TYPE_FULLNAME (t2));
} }
/* Build a TYPENAME_TYPE. If the type is `typename T::t', CONTEXT is /* 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 the type of `T', NAME is the IDENTIFIER_NODE for `t'.
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. */ Returns the new TYPENAME_TYPE. */
static GTY ((param_is (union tree_node))) htab_t typename_htab; static GTY ((param_is (union tree_node))) htab_t typename_htab;
static tree static tree
build_typename_type (tree context, tree name, tree fullname) build_typename_type (tree context, tree name, tree fullname,
enum tag_types tag_type)
{ {
tree t; tree t;
tree d; tree d;
typename_info ti;
void **e; void **e;
hashval_t hash;
if (typename_htab == NULL) if (typename_htab == NULL)
{ typename_htab = htab_create_ggc (61, &typename_hash,
typename_htab = htab_create_ggc (61, &typename_hash, &typename_compare, NULL);
&typename_compare, NULL);
} ti.scope = FROB_CONTEXT (context);
ti.name = name;
/* Build the TYPENAME_TYPE. */ ti.template_id = fullname;
t = make_aggr_type (TYPENAME_TYPE); ti.enum_p = tag_type == enum_type;
TYPE_CONTEXT (t) = FROB_CONTEXT (context); ti.class_p = (tag_type == class_type
TYPENAME_TYPE_FULLNAME (t) = fullname; || tag_type == record_type
|| tag_type == union_type);
/* Build the corresponding TYPE_DECL. */ hash = (htab_hash_pointer (ti.scope)
d = build_decl (TYPE_DECL, name, t); ^ htab_hash_pointer (ti.name));
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. */ /* See if we already have this type. */
e = htab_find_slot (typename_htab, t, INSERT); e = htab_find_slot_with_hash (typename_htab, &ti, hash, INSERT);
if (*e) if (*e)
t = (tree) *e; t = (tree) *e;
else else
*e = t; {
/* 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; return t;
} }
/* Resolve `typename CONTEXT::NAME'. Returns an appropriate type, /* Resolve `typename CONTEXT::NAME'. TAG_TYPE indicates the tag
unless an error occurs, in which case error_mark_node is returned. provided to name the type. Returns an appropriate type, unless an
If we locate a non-artificial TYPE_DECL and TF_KEEP_TYPE_DECL is error occurs, in which case error_mark_node is returned. If we
set, we return that, rather than the _TYPE it corresponds to, in locate a non-artificial TYPE_DECL and TF_KEEP_TYPE_DECL is set, we
other cases we look through the type decl. If TF_ERROR is set, return that, rather than the _TYPE it corresponds to, in other
complain about errors, otherwise be quiet. */ cases we look through the type decl. If TF_ERROR is set, complain
about errors, otherwise be quiet. */
tree tree
make_typename_type (tree context, tree name, tsubst_flags_t complain) make_typename_type (tree context, tree name, enum tag_types tag_type,
tsubst_flags_t complain)
{ {
tree fullname; tree fullname;
...@@ -2728,7 +2745,7 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain) ...@@ -2728,7 +2745,7 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain)
return error_mark_node; return error_mark_node;
} }
return build_typename_type (context, name, fullname); return build_typename_type (context, name, fullname, tag_type);
} }
/* Resolve `CONTEXT::template NAME'. Returns a TEMPLATE_DECL if the name /* Resolve `CONTEXT::template NAME'. Returns a TEMPLATE_DECL if the name
......
...@@ -348,7 +348,10 @@ dump_type (tree t, int flags) ...@@ -348,7 +348,10 @@ dump_type (tree t, int flags)
} }
case TYPENAME_TYPE: case TYPENAME_TYPE:
pp_cxx_cv_qualifier_seq (cxx_pp, t); pp_cxx_cv_qualifier_seq (cxx_pp, t);
pp_cxx_identifier (cxx_pp, "typename"); pp_cxx_identifier (cxx_pp,
TYPENAME_IS_ENUM_P (t) ? "enum"
: TYPENAME_IS_CLASS_P (t) ? "class"
: "typename");
dump_typename (t, flags); dump_typename (t, flags);
break; break;
......
...@@ -300,7 +300,7 @@ make_friend_class (tree type, tree friend_type, bool complain) ...@@ -300,7 +300,7 @@ make_friend_class (tree type, tree friend_type, bool complain)
tf_error); tf_error);
else else
friend_type friend_type
= make_typename_type (ctype, name, tf_error); = make_typename_type (ctype, name, class_type, tf_error);
} }
else else
{ {
......
...@@ -140,7 +140,6 @@ static tree most_specialized (tree, tree, tree); ...@@ -140,7 +140,6 @@ static tree most_specialized (tree, tree, tree);
static tree most_specialized_class (tree, tree); static tree most_specialized_class (tree, tree);
static int template_class_depth_real (tree, int); static int template_class_depth_real (tree, int);
static tree tsubst_aggr_type (tree, tree, tsubst_flags_t, 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_arg_types (tree, tree, tsubst_flags_t, tree);
static tree tsubst_function_type (tree, tree, tsubst_flags_t, tree); static tree tsubst_function_type (tree, tree, tsubst_flags_t, tree);
static void check_specialization_scope (void); static void check_specialization_scope (void);
...@@ -3833,6 +3832,7 @@ convert_template_argument (tree parm, ...@@ -3833,6 +3832,7 @@ convert_template_argument (tree parm,
arg = make_typename_type (TREE_OPERAND (arg, 0), arg = make_typename_type (TREE_OPERAND (arg, 0),
TREE_OPERAND (arg, 1), TREE_OPERAND (arg, 1),
typename_type,
complain & tf_error); complain & tf_error);
is_type = 1; is_type = 1;
} }
...@@ -6140,13 +6140,12 @@ tsubst_default_arguments (tree fn) ...@@ -6140,13 +6140,12 @@ tsubst_default_arguments (tree fn)
TREE_PURPOSE (arg)); TREE_PURPOSE (arg));
} }
/* Substitute the ARGS into the T, which is a _DECL. TYPE is the /* Substitute the ARGS into the T, which is a _DECL. Return the
(already computed) substitution of ARGS into TREE_TYPE (T), if result of the substitution. Issue error and warning messages under
appropriate. Return the result of the substitution. Issue error control of COMPLAIN. */
and warning messages under control of COMPLAIN. */
static tree static tree
tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain) tsubst_decl (tree t, tree args, tsubst_flags_t complain)
{ {
location_t saved_loc; location_t saved_loc;
tree r = NULL_TREE; tree r = NULL_TREE;
...@@ -6267,6 +6266,7 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain) ...@@ -6267,6 +6266,7 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
tree argvec = NULL_TREE; tree argvec = NULL_TREE;
tree *friends; tree *friends;
tree gen_tmpl; tree gen_tmpl;
tree type;
int member; int member;
int args_depth; int args_depth;
int parms_depth; int parms_depth;
...@@ -6376,7 +6376,7 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain) ...@@ -6376,7 +6376,7 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
member = 0; member = 0;
ctx = DECL_CONTEXT (t); ctx = DECL_CONTEXT (t);
} }
type = tsubst (type, args, complain, in_decl); type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (type == error_mark_node) if (type == error_mark_node)
return error_mark_node; return error_mark_node;
...@@ -6485,10 +6485,13 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain) ...@@ -6485,10 +6485,13 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
case PARM_DECL: case PARM_DECL:
{ {
tree type;
r = copy_node (t); r = copy_node (t);
if (DECL_TEMPLATE_PARM_P (t)) if (DECL_TEMPLATE_PARM_P (t))
SET_DECL_TEMPLATE_PARM_P (r); SET_DECL_TEMPLATE_PARM_P (r);
type = tsubst (TREE_TYPE (t), args, complain, in_decl);
TREE_TYPE (r) = type; TREE_TYPE (r) = type;
c_apply_type_quals_to_decl (cp_type_quals (type), r); c_apply_type_quals_to_decl (cp_type_quals (type), r);
...@@ -6513,7 +6516,12 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain) ...@@ -6513,7 +6516,12 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
case FIELD_DECL: case FIELD_DECL:
{ {
tree type;
r = copy_decl (t); 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; TREE_TYPE (r) = type;
c_apply_type_quals_to_decl (cp_type_quals (type), r); c_apply_type_quals_to_decl (cp_type_quals (type), r);
...@@ -6541,19 +6549,6 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain) ...@@ -6541,19 +6549,6 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
break; break;
case TYPE_DECL: 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: case VAR_DECL:
{ {
tree argvec = NULL_TREE; tree argvec = NULL_TREE;
...@@ -6561,8 +6556,25 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain) ...@@ -6561,8 +6556,25 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
tree spec; tree spec;
tree tmpl = NULL_TREE; tree tmpl = NULL_TREE;
tree ctx; tree ctx;
tree type = NULL_TREE;
int local_p; 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. */ /* Assume this is a non-local variable. */
local_p = 0; local_p = 0;
...@@ -6600,6 +6612,9 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain) ...@@ -6600,6 +6612,9 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
r = copy_decl (t); r = copy_decl (t);
if (TREE_CODE (r) == VAR_DECL) 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); type = complete_type (type);
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r) DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r)
= DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (t); = DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (t);
...@@ -6885,6 +6900,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -6885,6 +6900,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
|| TREE_CODE (t) == NAMESPACE_DECL) || TREE_CODE (t) == NAMESPACE_DECL)
return t; return t;
if (DECL_P (t))
return tsubst_decl (t, args, complain);
if (TREE_CODE (t) == IDENTIFIER_NODE) if (TREE_CODE (t) == IDENTIFIER_NODE)
type = IDENTIFIER_TYPE_VALUE (t); type = IDENTIFIER_TYPE_VALUE (t);
else else
...@@ -6892,9 +6910,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -6892,9 +6910,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
gcc_assert (type != unknown_type_node); gcc_assert (type != unknown_type_node);
if (type && TREE_CODE (t) != FUNCTION_DECL if (type
&& TREE_CODE (t) != TYPENAME_TYPE && TREE_CODE (t) != TYPENAME_TYPE
&& TREE_CODE (t) != TEMPLATE_DECL
&& TREE_CODE (t) != IDENTIFIER_NODE && TREE_CODE (t) != IDENTIFIER_NODE
&& TREE_CODE (t) != FUNCTION_TYPE && TREE_CODE (t) != FUNCTION_TYPE
&& TREE_CODE (t) != METHOD_TYPE) && TREE_CODE (t) != METHOD_TYPE)
...@@ -6902,9 +6919,6 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -6902,9 +6919,6 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
if (type == error_mark_node) if (type == error_mark_node)
return error_mark_node; return error_mark_node;
if (DECL_P (t))
return tsubst_decl (t, args, type, complain);
switch (TREE_CODE (t)) switch (TREE_CODE (t))
{ {
case RECORD_TYPE: case RECORD_TYPE:
...@@ -7364,7 +7378,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -7364,7 +7378,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
} }
} }
f = make_typename_type (ctx, f, f = make_typename_type (ctx, f, typename_type,
(complain & tf_error) | tf_keep_type_decl); (complain & tf_error) | tf_keep_type_decl);
if (f == error_mark_node) if (f == error_mark_node)
return f; return f;
...@@ -7374,6 +7388,16 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -7374,6 +7388,16 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
f = TREE_TYPE (f); 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 return cp_build_qualified_type_real
(f, cp_type_quals (f) | cp_type_quals (t), complain); (f, cp_type_quals (f) | cp_type_quals (t), complain);
} }
......
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.
2004-11-29 Diego Novillo <dnovillo@redhat.com> 2004-11-29 Diego Novillo <dnovillo@redhat.com>
PR tree-optimization/18712 PR tree-optimization/18712
......
// PR c++/18512
template <int> struct A {};
struct B : A<0>
{
void foo() { this->A<0>; } // { dg-error "" }
};
// 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>();
}
...@@ -6,7 +6,7 @@ public: ...@@ -6,7 +6,7 @@ public:
Graph(void) {}; // { dg-error "previously defined here" } Graph(void) {}; // { dg-error "previously defined here" }
} }
Graph::Graph(void) // { dg-error "return type|redefinition" } Graph::Graph(void) // { dg-error "return type|redefinition|semicolon" }
{ N = 10; { N = 10;
} }
...@@ -20,7 +20,7 @@ class Y ...@@ -20,7 +20,7 @@ class Y
public: public:
Y(); Y();
} }
X::X( int xi ) // { dg-error "return type|X::X" } X::X( int xi ) // { dg-error "return type|X::X|semicolon" }
{ {
x = xi; x = xi;
} }
......
...@@ -7,7 +7,7 @@ public: ...@@ -7,7 +7,7 @@ public:
virtual ~X(); virtual ~X();
} }
X::x() // { dg-error "return type|member function" } X::x() // { dg-error "return type|member function|semicolon" }
{ {
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment