re PR c++/27102 (ICE with invalid class name in function template)

PR c++/27102
	* class.c (currently_open_class): Tidy.
	* decl.c (grokdeclarator): If we encounter an erroneous
	declarator, assume that we have already issued an error message
	and return.  Return error_mark_node instead of NULL_TREE in more
	places.  Issue errors about function definitions that do not have
	a function declarator.  Check for complete types for all function
	definitions. 
	* cp-tree.h (cp_error_declarator): Remove.
	(currently_open_class): Change return type.
	* parser.c (cp_parser_id_expression): Add optional_p parameter.
	(cp_parser_parse_diagnose_invalid_type_name): Adjust calls.
	(cp_parser_id_expression): Likewise.
	(cp_parser_unqualified_id): If the name is optional, return
	NULL_TREE.
	(cp_parser_postfix_dot_deref_expression): Adjust calls.
	(cp_parser_type_parameter): Likewise.
	(cp_parser_unqualified_id): Likewise.
	(cp_parser_direct_declarator): Likewise.
	(cp_parser_declarator_id): Add optional_p parameter.
	(cp_parser_function_definition_from_specifiers_and_declarator):
	Assume that start_function indicates failure only if it has issued
	an error.
	(cp_parser_omp_var_list_no_open): Adjust calls.
	
	PR c++/27102
	* g++.dg/template/crash35.C: Tweak error markers.
	* g++.dg/template/crash46.C: New test.
	* g++.old-deja/g++.brendan/friend4.C: Tweak error markers.
	* g++.old-deja/g++.pt/incomplete1.C: Likewise.

From-SVN: r113081
This commit is contained in:
Mark Mitchell 2006-04-19 16:58:23 +00:00 committed by Mark Mitchell
parent 74c96e0c14
commit fa6098f817
10 changed files with 136 additions and 66 deletions

View File

@ -1,3 +1,30 @@
2006-04-19 Mark Mitchell <mark@codesourcery.com>
PR c++/27102
* class.c (currently_open_class): Tidy.
* decl.c (grokdeclarator): If we encounter an erroneous
declarator, assume that we have already issued an error message
and return. Return error_mark_node instead of NULL_TREE in more
places. Issue errors about function definitions that do not have
a function declarator. Check for complete types for all function
definitions.
* cp-tree.h (cp_error_declarator): Remove.
(currently_open_class): Change return type.
* parser.c (cp_parser_id_expression): Add optional_p parameter.
(cp_parser_parse_diagnose_invalid_type_name): Adjust calls.
(cp_parser_id_expression): Likewise.
(cp_parser_unqualified_id): If the name is optional, return
NULL_TREE.
(cp_parser_postfix_dot_deref_expression): Adjust calls.
(cp_parser_type_parameter): Likewise.
(cp_parser_unqualified_id): Likewise.
(cp_parser_direct_declarator): Likewise.
(cp_parser_declarator_id): Add optional_p parameter.
(cp_parser_function_definition_from_specifiers_and_declarator):
Assume that start_function indicates failure only if it has issued
an error.
(cp_parser_omp_var_list_no_open): Adjust calls.
2006-04-17 Janis Johnson <janis187@us.ibm.com>
PR c++/26114, c++/26115

View File

@ -5496,25 +5496,33 @@ pop_class_stack (void)
--current_class_stack[current_class_depth - 1].hidden;
}
/* Returns 1 if current_class_type is either T or a nested type of T.
We start looking from 1 because entry 0 is from global scope, and has
no type. */
/* Returns 1 if the class type currently being defined is either T or
a nested type of T. */
int
bool
currently_open_class (tree t)
{
int i;
if (current_class_type && same_type_p (t, current_class_type))
return 1;
for (i = current_class_depth - 1; i > 0; --i)
/* We start looking from 1 because entry 0 is from global scope,
and has no type. */
for (i = current_class_depth; i > 0; --i)
{
if (current_class_stack[i].hidden)
break;
if (current_class_stack[i].type
&& same_type_p (current_class_stack [i].type, t))
return 1;
tree c;
if (i == current_class_depth)
c = current_class_type;
else
{
if (current_class_stack[i].hidden)
break;
c = current_class_stack[i].type;
}
if (!c)
continue;
if (same_type_p (c, t))
return true;
}
return 0;
return false;
}
/* If either current_class_type or one of its enclosing classes are derived

View File

@ -3691,9 +3691,6 @@ struct cp_declarator {
} u;
};
/* An erroneous declarator. */
extern cp_declarator *cp_error_declarator;
/* A parameter list indicating for a function with no parameters,
e.g "int f(void)". */
extern cp_parameter_declarator *no_parameters;
@ -3750,7 +3747,7 @@ extern tree get_vtable_decl (tree, int);
extern void resort_type_method_vec (void *, void *,
gt_pointer_operator, void *);
extern bool add_method (tree, tree, tree);
extern int currently_open_class (tree);
extern bool currently_open_class (tree);
extern tree currently_open_derived_class (tree);
extern tree finish_struct (tree, tree);
extern void finish_struct_1 (tree);

View File

@ -6956,7 +6956,7 @@ grokdeclarator (const cp_declarator *declarator,
break;
case cdk_error:
break;
return error_mark_node;
default:
gcc_unreachable ();
@ -6966,11 +6966,15 @@ grokdeclarator (const cp_declarator *declarator,
break;
}
/* A function definition's declarator must have the form of
a function declarator. */
/* [dcl.fct.edf]
The declarator in a function-definition shall have the form
D1 ( parameter-declaration-clause) ... */
if (funcdef_flag && innermost_code != cdk_function)
return NULL_TREE;
{
error ("function definition does not declare parameters");
return error_mark_node;
}
if (((dname && IDENTIFIER_OPNAME_P (dname)) || flags == TYPENAME_FLAG)
&& innermost_code != cdk_function
@ -7711,6 +7715,20 @@ grokdeclarator (const cp_declarator *declarator,
pedwarn ("extra qualification %<%T::%> on member %qs",
ctype, name);
}
else if (/* If the qualifying type is already complete, then we
can skip the following checks. */
!COMPLETE_TYPE_P (ctype)
/* If a function is being defined, then the qualifing
type must be complete. The qualifing type may be
incomplete for a declaration only if the qualitying
type is one of the classes presently being defined,
or if it is a dependent type. */
&& (funcdef_flag
|| !(dependent_type_p (ctype)
|| currently_open_class (ctype)))
/* Check that the qualifing type is complete. */
&& !complete_type_or_else (ctype, NULL_TREE))
return error_mark_node;
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
tree sname = declarator->u.id.unqualified_name;
@ -7736,23 +7754,10 @@ grokdeclarator (const cp_declarator *declarator,
TYPE_ARG_TYPES (type));
}
else if (declspecs->specs[(int)ds_typedef]
|| COMPLETE_TYPE_P (complete_type (ctype)))
&& current_class_type)
{
/* Have to move this code elsewhere in this function.
this code is used for i.e., typedef int A::M; M *pm;
It is? How? jason 10/2/94 */
if (current_class_type)
{
error ("cannot declare member %<%T::%s%> within %qT",
ctype, name, current_class_type);
return void_type_node;
}
}
else
{
cxx_incomplete_type_error (NULL_TREE, ctype);
error ("cannot declare member %<%T::%s%> within %qT",
ctype, name, current_class_type);
return error_mark_node;
}
}

View File

@ -780,7 +780,8 @@ static cp_parameter_declarator *make_parameter_declarator
static cp_declarator *make_ptrmem_declarator
(cp_cv_quals, tree, cp_declarator *);
cp_declarator *cp_error_declarator;
/* An erroneous declarator. */
static cp_declarator *cp_error_declarator;
/* The obstack on which declarators and related data structures are
allocated. */
@ -1389,9 +1390,9 @@ static bool cp_parser_translation_unit
static tree cp_parser_primary_expression
(cp_parser *, bool, bool, bool, cp_id_kind *);
static tree cp_parser_id_expression
(cp_parser *, bool, bool, bool *, bool);
(cp_parser *, bool, bool, bool *, bool, bool);
static tree cp_parser_unqualified_id
(cp_parser *, bool, bool, bool);
(cp_parser *, bool, bool, bool, bool);
static tree cp_parser_nested_name_specifier_opt
(cp_parser *, bool, bool, bool, bool);
static tree cp_parser_nested_name_specifier
@ -1536,7 +1537,7 @@ static enum tree_code cp_parser_ptr_operator
static cp_cv_quals cp_parser_cv_qualifier_seq_opt
(cp_parser *);
static tree cp_parser_declarator_id
(cp_parser *);
(cp_parser *, bool);
static tree cp_parser_type_id
(cp_parser *);
static void cp_parser_type_specifier_seq
@ -2142,7 +2143,8 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
/*template_keyword_p=*/false,
/*check_dependency_p=*/true,
/*template_p=*/NULL,
/*declarator_p=*/true);
/*declarator_p=*/true,
/*optional_p=*/false);
/* After the id-expression, there should be a plain identifier,
otherwise this is not a simple variable declaration. Also, if
the scope is dependent, we cannot do much. */
@ -3021,7 +3023,8 @@ cp_parser_primary_expression (cp_parser *parser,
/*template_keyword_p=*/false,
/*check_dependency_p=*/true,
&template_p,
/*declarator_p=*/false);
/*declarator_p=*/false,
/*optional_p=*/false);
if (id_expression == error_mark_node)
return error_mark_node;
token = cp_lexer_peek_token (parser->lexer);
@ -3154,7 +3157,8 @@ cp_parser_id_expression (cp_parser *parser,
bool template_keyword_p,
bool check_dependency_p,
bool *template_p,
bool declarator_p)
bool declarator_p,
bool optional_p)
{
bool global_scope_p;
bool nested_name_specifier_p;
@ -3197,7 +3201,8 @@ cp_parser_id_expression (cp_parser *parser,
/* Process the final unqualified-id. */
unqualified_id = cp_parser_unqualified_id (parser, *template_p,
check_dependency_p,
declarator_p);
declarator_p,
/*optional_p=*/false);
/* Restore the SAVED_SCOPE for our caller. */
parser->scope = saved_scope;
parser->object_scope = saved_object_scope;
@ -3255,7 +3260,8 @@ cp_parser_id_expression (cp_parser *parser,
else
return cp_parser_unqualified_id (parser, template_keyword_p,
/*check_dependency_p=*/true,
declarator_p);
declarator_p,
optional_p);
}
/* Parse an unqualified-id.
@ -3284,7 +3290,8 @@ static tree
cp_parser_unqualified_id (cp_parser* parser,
bool template_keyword_p,
bool check_dependency_p,
bool declarator_p)
bool declarator_p,
bool optional_p)
{
cp_token *token;
@ -3505,6 +3512,8 @@ cp_parser_unqualified_id (cp_parser* parser,
/* Fall through. */
default:
if (optional_p)
return NULL_TREE;
cp_parser_error (parser, "expected unqualified-id");
return error_mark_node;
}
@ -4501,7 +4510,8 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
cp_parser_optional_template_keyword (parser),
/*check_dependency_p=*/true,
&template_p,
/*declarator_p=*/false));
/*declarator_p=*/false,
/*optional_p=*/false));
/* In general, build a SCOPE_REF if the member name is qualified.
However, if the name was not dependent and has already been
resolved; there is no need to build the SCOPE_REF. For example;
@ -8623,7 +8633,8 @@ cp_parser_type_parameter (cp_parser* parser)
/*template_keyword_p=*/false,
/*check_dependency_p=*/true,
/*template_p=*/&is_template,
/*declarator_p=*/false);
/*declarator_p=*/false,
/*optional_p=*/false);
if (TREE_CODE (default_argument) == TYPE_DECL)
/* If the id-expression was a template-id that refers to
a template-class, we already have the declaration here,
@ -9177,7 +9188,8 @@ cp_parser_template_argument (cp_parser* parser)
/*template_keyword_p=*/false,
/*check_dependency_p=*/true,
&template_p,
/*declarator_p=*/false);
/*declarator_p=*/false,
/*optional_p=*/false);
/* If the next token isn't a `,' or a `>', then this argument wasn't
really finished. */
if (!cp_parser_next_token_ends_template_argument_p (parser))
@ -10624,7 +10636,8 @@ cp_parser_using_declaration (cp_parser* parser)
identifier = cp_parser_unqualified_id (parser,
/*template_keyword_p=*/false,
/*check_dependency_p=*/true,
/*declarator_p=*/true);
/*declarator_p=*/true,
/*optional_p=*/false);
/* The function we call to handle a using-declaration is different
depending on what scope we are in. */
@ -11515,25 +11528,31 @@ cp_parser_direct_declarator (cp_parser* parser,
tree qualifying_scope;
tree unqualified_name;
special_function_kind sfk;
bool abstract_ok;
/* Parse a declarator-id */
if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
abstract_ok = (dcl_kind == CP_PARSER_DECLARATOR_EITHER);
if (abstract_ok)
cp_parser_parse_tentatively (parser);
unqualified_name = cp_parser_declarator_id (parser);
unqualified_name
= cp_parser_declarator_id (parser, /*optional_p=*/abstract_ok);
qualifying_scope = parser->scope;
if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
if (abstract_ok)
{
if (!cp_parser_parse_definitely (parser))
unqualified_name = error_mark_node;
else if (qualifying_scope
|| (TREE_CODE (unqualified_name)
!= IDENTIFIER_NODE))
else if (unqualified_name
&& (qualifying_scope
|| (TREE_CODE (unqualified_name)
!= IDENTIFIER_NODE)))
{
cp_parser_error (parser, "expected unqualified-id");
unqualified_name = error_mark_node;
}
}
if (!unqualified_name)
return NULL;
if (unqualified_name == error_mark_node)
{
declarator = cp_error_declarator;
@ -11853,7 +11872,7 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
unqualified-id. */
static tree
cp_parser_declarator_id (cp_parser* parser)
cp_parser_declarator_id (cp_parser* parser, bool optional_p)
{
tree id;
/* The expression must be an id-expression. Assume that qualified
@ -11874,8 +11893,9 @@ cp_parser_declarator_id (cp_parser* parser)
/*template_keyword_p=*/false,
/*check_dependency_p=*/false,
/*template_p=*/NULL,
/*declarator_p=*/true);
if (BASELINK_P (id))
/*declarator_p=*/true,
optional_p);
if (id && BASELINK_P (id))
id = BASELINK_FUNCTIONS (id);
return id;
}
@ -15298,7 +15318,6 @@ cp_parser_function_definition_from_specifiers_and_declarator
if (!success_p)
{
/* Skip the entire function. */
error ("invalid function declaration");
cp_parser_skip_to_end_of_block_or_statement (parser);
fn = error_mark_node;
}
@ -17786,7 +17805,8 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
name = cp_parser_id_expression (parser, /*template_p=*/false,
/*check_dependency_p=*/true,
/*template_p=*/NULL,
/*declarator_p=*/false);
/*declarator_p=*/false,
/*optional_p=*/false);
if (name == error_mark_node)
goto skip_comma;

View File

@ -1,3 +1,11 @@
2006-04-19 Mark Mitchell <mark@codesourcery.com>
PR c++/27102
* g++.dg/template/crash35.C: Tweak error markers.
* g++.dg/template/crash46.C: New test.
* g++.old-deja/g++.brendan/friend4.C: Tweak error markers.
* g++.old-deja/g++.pt/incomplete1.C: Likewise.
2006-04-19 Andreas Krebbel <krebbel1@de.ibm.com>
PR rtl-optimization/14261

View File

@ -5,5 +5,5 @@ template <typename T> struct C; // { dg-error "declaration" }
template <typename T> void C<T>::f() // { dg-error "invalid|template" }
{
const foo bar; // { dg-error "name a type" }
const foo bar;
}

View File

@ -0,0 +1,5 @@
// PR c++/27102
template <class T>
void T::foo() {} // { dg-error "invalid" }

View File

@ -2,5 +2,5 @@
// GROUPS passed friends
// do_friend should complain that foo was declared as a friend of
// A before A was defined
struct A;
struct A; // { dg-error "forward" }
struct B { friend A::foo (); };// { dg-error "" } .*

View File

@ -6,6 +6,6 @@
// Inspired by by 756. We'd ICE when trying to define a member of an
// incomplete template type.
template<class X> struct ObjCount; // { dg-error "" } forward decl
template<class X> struct ObjCount;
template<class X> int ObjCount<X>::m; // { dg-error "" } undefined type