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
This commit is contained in:
Mark Mitchell 2004-11-29 20:10:18 +00:00 committed by Mark Mitchell
parent b7034e060b
commit fc6a28d763
14 changed files with 338 additions and 155 deletions

View File

@ -1,3 +1,64 @@
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>
PR c/7544

View File

@ -182,9 +182,7 @@ DEFTREECODE (BOUND_TEMPLATE_TEMPLATE_PARM, "bound_template_template_parm",
/* 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'. */
TREE_TYPE is always NULL. */
DEFTREECODE (TYPENAME_TYPE, "typename_type", tcc_type, 0)
/* For template template argument of the form `T::template C'.

View File

@ -47,6 +47,7 @@ struct diagnostic_context;
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.
@ -54,6 +55,7 @@ struct diagnostic_context;
(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)
@ -2254,6 +2256,15 @@ struct lang_decl GTY(())
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))
@ -3718,7 +3729,7 @@ 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_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);

View File

@ -121,7 +121,6 @@ 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;
@ -2538,83 +2537,101 @@ typename_hash (const void* k)
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;
tree t2;
tree d1;
tree d2;
const typename_info *t2;
t1 = (tree) k1;
t2 = (tree) k2;
d1 = TYPE_NAME (t1);
d2 = TYPE_NAME (t2);
t2 = (const typename_info *) k2;
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));
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'. 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.
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)
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);
}
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;
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 (typename_htab, t, INSERT);
e = htab_find_slot_with_hash (typename_htab, &ti, hash, INSERT);
if (*e)
t = (tree) *e;
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;
}
/* 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. */
/* 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, tsubst_flags_t complain)
make_typename_type (tree context, tree name, enum tag_types tag_type,
tsubst_flags_t complain)
{
tree fullname;
@ -2728,7 +2745,7 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain)
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

View File

@ -348,7 +348,10 @@ dump_type (tree t, int flags)
}
case TYPENAME_TYPE:
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);
break;

View File

@ -300,7 +300,7 @@ make_friend_class (tree type, tree friend_type, bool complain)
tf_error);
else
friend_type
= make_typename_type (ctype, name, tf_error);
= make_typename_type (ctype, name, class_type, tf_error);
}
else
{

View File

@ -1514,7 +1514,7 @@ static bool cp_parser_ctor_initializer_opt_and_function_body
/* Classes [gram.class] */
static tree cp_parser_class_name
(cp_parser *, bool, bool, bool, bool, bool, bool);
(cp_parser *, bool, bool, enum tag_types, bool, bool, bool);
static tree cp_parser_class_specifier
(cp_parser *);
static tree cp_parser_class_head
@ -1623,7 +1623,7 @@ static void cp_parser_label_declaration
/* Utility Routines */
static tree cp_parser_lookup_name
(cp_parser *, tree, bool, bool, bool, bool, bool *);
(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
@ -1713,7 +1713,7 @@ static bool cp_parser_simulate_error
static void cp_parser_check_type_definition
(cp_parser *);
static void cp_parser_check_for_definition_in_return_type
(cp_declarator *, int);
(cp_declarator *, tree);
static void cp_parser_check_for_invalid_template_id
(cp_parser *, tree);
static bool cp_parser_non_integral_constant_expression
@ -1861,14 +1861,14 @@ cp_parser_check_type_definition (cp_parser* parser)
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. */
/* 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,
int declares_class_or_enum)
tree type)
{
/* [dcl.fct] forbids type definitions in return types.
Unfortunately, it's not easy to know whether or not we are
@ -1879,9 +1879,12 @@ cp_parser_check_for_definition_in_return_type (cp_declarator *declarator,
|| 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");
&& 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
@ -2295,12 +2298,13 @@ 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);
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, tf_error);
return make_typename_type (scope, id, typename_type, tf_error);
}
@ -2831,7 +2835,7 @@ cp_parser_primary_expression (cp_parser *parser,
bool ambiguous_p;
decl = cp_parser_lookup_name (parser, id_expression,
/*is_type=*/false,
none_type,
/*is_template=*/false,
/*is_namespace=*/false,
/*check_dependency=*/true,
@ -3164,7 +3168,7 @@ cp_parser_unqualified_id (cp_parser* parser,
type_decl = cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
/*type_p=*/false,
none_type,
/*check_dependency=*/false,
/*class_head_p=*/false,
declarator_p);
@ -3182,7 +3186,7 @@ cp_parser_unqualified_id (cp_parser* parser,
= cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
/*type_p=*/false,
none_type,
/*check_dependency=*/false,
/*class_head_p=*/false,
declarator_p);
@ -3200,7 +3204,7 @@ cp_parser_unqualified_id (cp_parser* parser,
= cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
/*type_p=*/false,
none_type,
/*check_dependency=*/false,
/*class_head_p=*/false,
declarator_p);
@ -3215,7 +3219,7 @@ cp_parser_unqualified_id (cp_parser* parser,
= cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
/*type_p=*/false,
none_type,
/*check_dependency=*/false,
/*class_head_p=*/false,
declarator_p);
@ -3579,7 +3583,7 @@ cp_parser_class_or_namespace_name (cp_parser *parser,
scope = cp_parser_class_name (parser,
typename_keyword_p,
template_keyword_p,
type_p,
type_p ? class_type : none_type,
check_dependency_p,
/*class_head_p=*/false,
is_declaration);
@ -3815,6 +3819,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
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);
@ -4275,18 +4280,28 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
if (parser->scope)
*idk = CP_ID_KIND_QUALIFIED;
if (name != error_mark_node && !BASELINK_P (name) && parser->scope)
/* 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)
{
name = build_nt (SCOPE_REF, parser->scope, name);
parser->scope = NULL_TREE;
parser->qualifying_scope = NULL_TREE;
parser->object_scope = NULL_TREE;
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);
}
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
@ -7659,7 +7674,7 @@ cp_parser_mem_initializer_id (cp_parser* parser)
return cp_parser_class_name (parser,
/*typename_keyword_p=*/true,
/*template_keyword_p=*/template_p,
/*type_p=*/false,
none_type,
/*check_dependency_p=*/true,
/*class_head_p=*/false,
/*is_declaration=*/true);
@ -7669,7 +7684,7 @@ cp_parser_mem_initializer_id (cp_parser* parser)
id = cp_parser_class_name (parser,
/*typename_keyword_p=*/true,
/*template_keyword_p=*/false,
/*type_p=*/false,
none_type,
/*check_dependency_p=*/true,
/*class_head_p=*/false,
/*is_declaration=*/true);
@ -8223,11 +8238,11 @@ cp_parser_type_parameter (cp_parser* parser)
/* 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);
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);
@ -8578,7 +8593,7 @@ cp_parser_template_name (cp_parser* parser,
/* Look up the name. */
decl = cp_parser_lookup_name (parser, identifier,
/*is_type=*/false,
none_type,
/*is_template=*/false,
/*is_namespace=*/false,
check_dependency_p,
@ -8769,7 +8784,7 @@ cp_parser_template_argument (cp_parser* parser)
at this point in that case. */
if (TREE_CODE (argument) != TYPE_DECL)
argument = cp_parser_lookup_name (parser, argument,
/*is_type=*/false,
none_type,
/*is_template=*/template_p,
/*is_namespace=*/false,
/*check_dependency=*/true,
@ -8971,8 +8986,9 @@ cp_parser_explicit_instantiation (cp_parser* parser)
/*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 (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,
@ -9460,7 +9476,7 @@ cp_parser_type_name (cp_parser* parser)
type_decl = cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
/*type_p=*/false,
none_type,
/*check_dependency_p=*/true,
/*class_head_p=*/false,
/*is_declaration=*/false);
@ -9612,6 +9628,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
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);
@ -9641,7 +9658,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
types, so we set IS_TYPE to TRUE when calling
cp_parser_lookup_name. */
decl = cp_parser_lookup_name (parser, identifier,
/*is_type=*/true,
tag_type,
/*is_template=*/false,
/*is_namespace=*/false,
/*check_dependency=*/true,
@ -9929,7 +9946,7 @@ cp_parser_namespace_name (cp_parser* parser)
function if the token after the name is the scope resolution
operator.) */
namespace_decl = cp_parser_lookup_name (parser, identifier,
/*is_type=*/false,
none_type,
/*is_template=*/false,
/*is_namespace=*/true,
/*check_dependency=*/true,
@ -10416,8 +10433,9 @@ cp_parser_init_declarator (cp_parser* parser,
if (declarator == cp_error_declarator)
return error_mark_node;
cp_parser_check_for_definition_in_return_type (declarator,
declares_class_or_enum);
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
@ -12100,11 +12118,10 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
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.
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. */
@ -12112,7 +12129,7 @@ static tree
cp_parser_class_name (cp_parser *parser,
bool typename_keyword_p,
bool template_keyword_p,
bool type_p,
enum tag_types tag_type,
bool check_dependency_p,
bool class_head_p,
bool is_declaration)
@ -12168,10 +12185,10 @@ cp_parser_class_name (cp_parser *parser,
resolution operator, object, function, and enumerator
names are ignored. */
if (cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))
type_p = true;
tag_type = typename_type;
/* Look up the name. */
decl = cp_parser_lookup_name (parser, identifier,
type_p,
tag_type,
/*is_template=*/false,
/*is_namespace=*/false,
check_dependency_p,
@ -12193,7 +12210,7 @@ cp_parser_class_name (cp_parser *parser,
/* If this is a typename, create a TYPENAME_TYPE. */
if (typename_p && decl != error_mark_node)
{
decl = make_typename_type (scope, decl, /*complain=*/1);
decl = make_typename_type (scope, decl, typename_type, /*complain=*/1);
if (decl != error_mark_node)
decl = TYPE_NAME (decl);
}
@ -12212,7 +12229,7 @@ cp_parser_class_name (cp_parser *parser,
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));
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)))
@ -12500,7 +12517,7 @@ cp_parser_class_head (cp_parser* parser,
type = cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
/*type_p=*/true,
class_type,
/*check_dependency_p=*/false,
/*class_head_p=*/true,
/*is_declaration=*/false);
@ -13058,8 +13075,9 @@ cp_parser_member_declaration (cp_parser* parser)
return;
}
cp_parser_check_for_definition_in_return_type
(declarator, declares_class_or_enum);
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);
@ -13414,7 +13432,7 @@ cp_parser_base_specifier (cp_parser* parser)
cp_parser_nested_name_specifier_opt (parser,
/*typename_keyword_p=*/true,
/*check_dependency_p=*/true,
/*type_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. */
@ -13425,7 +13443,7 @@ cp_parser_base_specifier (cp_parser* parser)
type = cp_parser_class_name (parser,
class_scope_p,
template_p,
/*type_p=*/true,
typename_type,
/*check_dependency_p=*/true,
/*class_head_p=*/false,
/*is_declaration=*/true);
@ -14049,8 +14067,9 @@ cp_parser_label_declaration (cp_parser* parser)
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 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.
@ -14066,7 +14085,8 @@ cp_parser_label_declaration (cp_parser* parser)
static tree
cp_parser_lookup_name (cp_parser *parser, tree name,
bool is_type, bool is_template, bool is_namespace,
enum tag_types tag_type,
bool is_template, bool is_namespace,
bool check_dependency,
bool *ambiguous_p)
{
@ -14144,13 +14164,21 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
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));
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,
@ -14173,7 +14201,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
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,
decl = lookup_qualified_name (parser->scope, name,
tag_type != none_type,
/*complain=*/true);
if (pop_p)
pop_scope (parser->scope);
@ -14193,9 +14222,11 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
parse, those errors are valid. */
object_decl = lookup_member (object_type,
name,
/*protect=*/0, is_type);
/*protect=*/0,
tag_type != none_type);
/* Look it up in the enclosing context, too. */
decl = lookup_name_real (name, is_type, /*nonclass=*/0,
decl = lookup_name_real (name, tag_type != none_type,
/*nonclass=*/0,
/*block_p=*/true, is_namespace,
/*flags=*/0);
parser->object_scope = object_type;
@ -14205,7 +14236,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
}
else
{
decl = lookup_name_real (name, is_type, /*nonclass=*/0,
decl = lookup_name_real (name, tag_type != none_type,
/*nonclass=*/0,
/*block_p=*/true, is_namespace,
/*flags=*/0);
parser->qualifying_scope = NULL_TREE;
@ -14261,7 +14293,7 @@ static tree
cp_parser_lookup_name_simple (cp_parser* parser, tree name)
{
return cp_parser_lookup_name (parser, name,
/*is_type=*/false,
none_type,
/*is_template=*/false,
/*is_namespace=*/false,
/*check_dependency=*/true,
@ -14519,7 +14551,7 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
type_decl = cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
/*type_p=*/false,
none_type,
/*check_dependency_p=*/false,
/*class_head_p=*/false,
/*is_declaration=*/false);

View File

@ -140,7 +140,6 @@ 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);
@ -3833,6 +3832,7 @@ convert_template_argument (tree parm,
arg = make_typename_type (TREE_OPERAND (arg, 0),
TREE_OPERAND (arg, 1),
typename_type,
complain & tf_error);
is_type = 1;
}
@ -6140,13 +6140,12 @@ tsubst_default_arguments (tree fn)
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. */
/* 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, tree type, tsubst_flags_t complain)
tsubst_decl (tree t, tree args, tsubst_flags_t complain)
{
location_t saved_loc;
tree r = NULL_TREE;
@ -6267,6 +6266,7 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
tree argvec = NULL_TREE;
tree *friends;
tree gen_tmpl;
tree type;
int member;
int args_depth;
int parms_depth;
@ -6376,7 +6376,7 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
member = 0;
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)
return error_mark_node;
@ -6485,10 +6485,13 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
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);
@ -6513,7 +6516,12 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
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);
@ -6541,19 +6549,6 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
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;
@ -6561,8 +6556,25 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
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;
@ -6600,6 +6612,9 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
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);
@ -6885,6 +6900,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
|| 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
@ -6892,9 +6910,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
gcc_assert (type != unknown_type_node);
if (type && TREE_CODE (t) != FUNCTION_DECL
if (type
&& 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)
@ -6902,9 +6919,6 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree 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:
@ -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);
if (f == error_mark_node)
return f;
@ -7374,6 +7388,16 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
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);
}

View File

@ -1,3 +1,16 @@
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>
PR tree-optimization/18712

View File

@ -0,0 +1,8 @@
// PR c++/18512
template <int> struct A {};
struct B : A<0>
{
void foo() { this->A<0>; } // { dg-error "" }
};

View File

@ -0,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>();
}

View File

@ -6,7 +6,7 @@ public:
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;
}

View File

@ -20,7 +20,7 @@ class Y
public:
Y();
}
X::X( int xi ) // { dg-error "return type|X::X" }
X::X( int xi ) // { dg-error "return type|X::X|semicolon" }
{
x = xi;
}

View File

@ -7,7 +7,7 @@ public:
virtual ~X();
}
X::x() // { dg-error "return type|member function" }
X::x() // { dg-error "return type|member function|semicolon" }
{
}