break;
case cdk_error:
- break;
+ return error_mark_node;
default:
gcc_unreachable ();
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
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;
TYPE_ARG_TYPES (type));
}
else if (declspecs->specs[(int)ds_typedef]
- || COMPLETE_TYPE_P (complete_type (ctype)))
- {
- /* 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
+ && current_class_type)
{
- cxx_incomplete_type_error (NULL_TREE, ctype);
+ error ("cannot declare member %<%T::%s%> within %qT",
+ ctype, name, current_class_type);
return error_mark_node;
}
}
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. */
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
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
/*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. */
/*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);
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;
/* 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;
else
return cp_parser_unqualified_id (parser, template_keyword_p,
/*check_dependency_p=*/true,
- declarator_p);
+ declarator_p,
+ optional_p);
}
/* Parse an unqualified-id.
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;
/* Fall through. */
default:
+ if (optional_p)
+ return NULL_TREE;
cp_parser_error (parser, "expected unqualified-id");
return error_mark_node;
}
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;
/*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,
/*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))
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. */
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;
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
/*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;
}
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;
}
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;