aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog61
-rw-r--r--gcc/cp/cp-tree.def4
-rw-r--r--gcc/cp/cp-tree.h13
-rw-r--r--gcc/cp/decl.c107
-rw-r--r--gcc/cp/error.c5
-rw-r--r--gcc/cp/friend.c2
-rw-r--r--gcc/cp/parser.c184
-rw-r--r--gcc/cp/pt.c76
-rw-r--r--gcc/testsuite/ChangeLog13
-rw-r--r--gcc/testsuite/g++.dg/template/crash29.C8
-rw-r--r--gcc/testsuite/g++.dg/template/error16.C16
-rw-r--r--gcc/testsuite/g++.old-deja/g++.brendan/crash16.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.law/ctors5.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/crash25.C2
14 files changed, 339 insertions, 156 deletions
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 <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
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<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);
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 <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
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 <int> 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 <typename I>
+static void g() {
+ enum I::t a; // { dg-error "" }
+ (void) a;
+}
+
+struct B {
+ typedef int t;
+};
+
+void h()
+{
+ g<B>();
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/crash16.C b/gcc/testsuite/g++.old-deja/g++.brendan/crash16.C
index 8b91e6b..8fec8d113 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" }
{
}