From fc6a28d7633ddd7c734b759f4d60233b70bf1770 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Mon, 29 Nov 2004 20:10:18 +0000 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 61 ++++++++ gcc/cp/cp-tree.def | 4 +- gcc/cp/cp-tree.h | 13 +- gcc/cp/decl.c | 107 +++++++------ gcc/cp/error.c | 5 +- gcc/cp/friend.c | 2 +- gcc/cp/parser.c | 184 +++++++++++++---------- gcc/cp/pt.c | 76 ++++++---- gcc/testsuite/ChangeLog | 13 ++ gcc/testsuite/g++.dg/template/crash29.C | 8 + gcc/testsuite/g++.dg/template/error16.C | 16 ++ gcc/testsuite/g++.old-deja/g++.brendan/crash16.C | 2 +- gcc/testsuite/g++.old-deja/g++.law/ctors5.C | 2 +- gcc/testsuite/g++.old-deja/g++.other/crash25.C | 2 +- 14 files changed, 339 insertions(+), 156 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/crash29.C create mode 100644 gcc/testsuite/g++.dg/template/error16.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1a1dcbe..449be96 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,64 @@ +2004-11-27 Mark Mitchell + + 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 PR c/7544 diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index 2335e2f..a01ed76 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -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'. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 1dfd52d..ecc09cd 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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'. */ #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); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 7779080..92f294f 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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); - } - - /* 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; + 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 (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 diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 2f14db6..ffdade0 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -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; diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c index 2d177a0..8203dbb 100644 --- a/gcc/cp/friend.c +++ b/gcc/cp/friend.c @@ -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 { diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index b2164b7..ebcf852 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index fca3f3d..34e86c8 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0f3bc3b..7a806bb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,16 @@ +2004-11-29 Mark Mitchell + + 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 PR tree-optimization/18712 diff --git a/gcc/testsuite/g++.dg/template/crash29.C b/gcc/testsuite/g++.dg/template/crash29.C new file mode 100644 index 0000000..55953ed --- /dev/null +++ b/gcc/testsuite/g++.dg/template/crash29.C @@ -0,0 +1,8 @@ +// PR c++/18512 + +template struct A {}; + +struct B : A<0> +{ + void foo() { this->A<0>; } // { dg-error "" } +}; diff --git a/gcc/testsuite/g++.dg/template/error16.C b/gcc/testsuite/g++.dg/template/error16.C new file mode 100644 index 0000000..0da024b --- /dev/null +++ b/gcc/testsuite/g++.dg/template/error16.C @@ -0,0 +1,16 @@ +// PR c++/18674 + +template +static void g() { + enum I::t a; // { dg-error "" } + (void) a; +} + +struct B { + typedef int t; +}; + +void h() +{ + g(); +} diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/crash16.C b/gcc/testsuite/g++.old-deja/g++.brendan/crash16.C index 8b91e6b..8fec8d1 100644 --- a/gcc/testsuite/g++.old-deja/g++.brendan/crash16.C +++ b/gcc/testsuite/g++.old-deja/g++.brendan/crash16.C @@ -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; } diff --git a/gcc/testsuite/g++.old-deja/g++.law/ctors5.C b/gcc/testsuite/g++.old-deja/g++.law/ctors5.C index d08805a..334b597 100644 --- a/gcc/testsuite/g++.old-deja/g++.law/ctors5.C +++ b/gcc/testsuite/g++.old-deja/g++.law/ctors5.C @@ -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; } diff --git a/gcc/testsuite/g++.old-deja/g++.other/crash25.C b/gcc/testsuite/g++.old-deja/g++.other/crash25.C index b18d99b..b8417e8 100644 --- a/gcc/testsuite/g++.old-deja/g++.other/crash25.C +++ b/gcc/testsuite/g++.old-deja/g++.other/crash25.C @@ -7,7 +7,7 @@ public: virtual ~X(); } -X::x() // { dg-error "return type|member function" } +X::x() // { dg-error "return type|member function|semicolon" } { } -- 2.7.4