if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
error_at (location, "%qE in namespace %qE does not name a type",
id, parser->scope);
+ else if (CLASS_TYPE_P (parser->scope)
+ && constructor_name_p (id, parser->scope))
+ {
+ /* A<T>::A<T>() */
+ error_at (location, "%<%T::%E%> names the constructor, not"
+ " the type", parser->scope, id);
+ if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))
+ error_at (location, "and %qT has no template constructors",
+ parser->scope);
+ }
+ else if (TYPE_P (parser->scope)
+ && dependent_scope_p (parser->scope))
+ error_at (location, "need %<typename%> before %<%T::%E%> because "
+ "%qT is a dependent scope",
+ parser->scope, id, parser->scope);
else if (TYPE_P (parser->scope))
error_at (location, "%qE in class %qT does not name a type",
id, parser->scope);
tree id;
cp_token *token = cp_lexer_peek_token (parser->lexer);
+ /* Avoid duplicate error about ambiguous lookup. */
+ if (token->type == CPP_NESTED_NAME_SPECIFIER)
+ {
+ cp_token *next = cp_lexer_peek_nth_token (parser->lexer, 2);
+ if (next->type == CPP_NAME && next->ambiguous_p)
+ goto out;
+ }
+
cp_parser_parse_tentatively (parser);
id = cp_parser_id_expression (parser,
/*template_keyword_p=*/false,
/*template_p=*/NULL,
/*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. */
- if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME)
- || (parser->scope && TYPE_P (parser->scope)
- && dependent_type_p (parser->scope))
+ /* If the next token is a (, this is a function with no explicit return
+ type, i.e. constructor, destructor or conversion op. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)
|| TREE_CODE (id) == TYPE_DECL)
{
cp_parser_abort_tentative_parse (parser);
/* Emit a diagnostic for the invalid type. */
cp_parser_diagnose_invalid_type_name (parser, parser->scope,
id, token->location);
- /* Skip to the end of the declaration; there's no point in
- trying to process it. */
- cp_parser_skip_to_end_of_block_or_statement (parser);
+ out:
+ /* If we aren't in the middle of a declarator (i.e. in a
+ parameter-declaration-clause), skip to the end of the declaration;
+ there's no point in trying to process it. */
+ if (!parser->in_declarator_p)
+ cp_parser_skip_to_end_of_block_or_statement (parser);
return true;
}
if (c_dialect_objc ())
/* We have an Objective-C++ message. */
return cp_parser_objc_expression (parser);
- maybe_warn_cpp0x ("lambda expressions");
+ maybe_warn_cpp0x (CPP0X_LAMBDA_EXPR);
return cp_parser_lambda_expression (parser);
case CPP_OBJC_STRING:
{
tree ambiguous_decls;
+ /* If we already know that this lookup is ambiguous, then
+ we've already issued an error message; there's no reason
+ to check again. */
+ if (id_expr_token->type == CPP_NAME
+ && id_expr_token->ambiguous_p)
+ {
+ cp_parser_simulate_error (parser);
+ return error_mark_node;
+ }
+
decl = cp_parser_lookup_name (parser, id_expression,
none_type,
template_p,
if (scope
&& token->type == CPP_NAME
&& (cp_lexer_peek_nth_token (parser->lexer, 2)->type
- == CPP_OPEN_PAREN)
+ != CPP_LESS)
&& constructor_name_p (token->u.value, scope))
{
cp_lexer_consume_token (parser->lexer);
}
/* If there was an explicit qualification (S::~T), first look
- in the scope given by the qualification (i.e., S). */
+ in the scope given by the qualification (i.e., S).
+
+ Note: in the calls to cp_parser_class_name below we pass
+ typename_type so that lookup finds the injected-class-name
+ rather than the constructor. */
done = false;
type_decl = NULL_TREE;
if (scope)
type_decl = cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
- none_type,
+ typename_type,
/*check_dependency=*/false,
/*class_head_p=*/false,
declarator_p);
= cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
- none_type,
+ typename_type,
/*check_dependency=*/false,
/*class_head_p=*/false,
declarator_p);
= cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
- none_type,
+ typename_type,
/*check_dependency=*/false,
/*class_head_p=*/false,
declarator_p);
= cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
- none_type,
+ typename_type,
/*check_dependency=*/false,
/*class_head_p=*/false,
declarator_p);
&& is_overloaded_fn (postfix_expression))
{
tree fn = get_first_fn (postfix_expression);
+ fn = STRIP_TEMPLATE (fn);
- if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
- fn = OVL_CURRENT (TREE_OPERAND (fn, 0));
-
- /* Only do argument dependent lookup if regular
- lookup does not find a set of member functions.
- [basic.lookup.koenig]/2a */
- if (!DECL_FUNCTION_MEMBER_P (fn))
+ /* Do not do argument dependent lookup if regular
+ lookup finds a member function or a block-scope
+ function declaration. [basic.lookup.argdep]/3 */
+ if (!DECL_FUNCTION_MEMBER_P (fn)
+ && !DECL_LOCAL_FUNCTION_P (fn))
{
koenig_p = true;
if (!any_type_dependent_arguments_p (args))
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
{
/* A braced-init-list. */
- maybe_warn_cpp0x ("extended initializer lists");
+ maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
expr = cp_parser_braced_list (parser, &expr_non_constant_p);
if (non_constant_p && expr_non_constant_p)
*non_constant_p = true;
{
case INDIRECT_REF:
non_constant_p = "%<*%>";
- expression = build_x_indirect_ref (cast_expression, "unary *",
+ expression = build_x_indirect_ref (cast_expression, RO_UNARY_STAR,
tf_warning_or_error);
break;
parser->type_definition_forbidden_message
= "types may not be defined in a new-type-id";
/* Parse the type-specifier-seq. */
- cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+ cp_parser_type_specifier_seq (parser, /*is_declaration=*/false,
/*is_trailing_return=*/false,
&type_specifier_seq);
/* Restore the old message. */
{
tree t;
bool expr_non_constant_p;
- maybe_warn_cpp0x ("extended initializer lists");
+ maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
t = cp_parser_braced_list (parser, &expr_non_constant_p);
CONSTRUCTOR_IS_DIRECT_INIT (t) = 1;
expression_list = make_tree_vector_single (t);
tree rhs = cp_parser_initializer_clause (parser, &non_constant_p);
if (BRACE_ENCLOSED_INITIALIZER_P (rhs))
- maybe_warn_cpp0x ("extended initializer lists");
+ maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
/* An assignment may not appear in a
constant-expression. */
cp_parser_expression_statement (cp_parser* parser, tree in_statement_expr)
{
tree statement = NULL_TREE;
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
/* If the next token is a ';', then there is no expression
statement. */
if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
statement = cp_parser_expression (parser, /*cast_p=*/false, NULL);
+ /* Give a helpful message for "A<T>::type t;" and the like. */
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)
+ && !cp_parser_uncommitted_to_tentative_parse_p (parser))
+ {
+ if (TREE_CODE (statement) == SCOPE_REF)
+ error_at (token->location, "need %<typename%> before %qE because "
+ "%qT is a dependent scope",
+ statement, TREE_OPERAND (statement, 0));
+ else if (is_overloaded_fn (statement)
+ && DECL_CONSTRUCTOR_P (get_first_fn (statement)))
+ {
+ /* A::A a; */
+ tree fn = get_first_fn (statement);
+ error_at (token->location,
+ "%<%T::%D%> names the constructor, not the type",
+ DECL_CONTEXT (fn), DECL_NAME (fn));
+ }
+ }
+
/* Consume the final `;'. */
cp_parser_consume_semicolon_at_end_of_statement (parser);
parser->type_definition_forbidden_message
= "types may not be defined in conditions";
/* Parse the type-specifier-seq. */
- cp_parser_type_specifier_seq (parser, /*is_condition==*/true,
+ cp_parser_type_specifier_seq (parser, /*is_declaration==*/true,
/*is_trailing_return=*/false,
&type_specifiers);
/* Restore the saved message. */
initializer = cp_parser_initializer_clause (parser, &non_constant_p);
}
if (BRACE_ENCLOSED_INITIALIZER_P (initializer))
- maybe_warn_cpp0x ("extended initializer lists");
+ maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
if (!non_constant_p)
initializer = fold_non_dependent_expr (initializer);
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
{
- maybe_warn_cpp0x ("extended initializer lists");
+ maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
expr = cp_parser_braced_list (parser, &expr_non_constant_p);
}
else if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
T t;
where "T" should name a type -- but does not. */
- if (!decl_specifiers.type
+ if (!decl_specifiers.any_type_specifiers_p
&& cp_parser_parse_and_diagnose_invalid_type_name (parser))
{
/* If parsing tentatively, we should commit; we really are
{
constructor_possible_p = false;
found_decl_spec = true;
+ if (!is_cv_qualifier)
+ decl_specs->any_type_specifiers_p = true;
}
}
/* Parse the attributes. */
attributes = cp_parser_attributes_opt (parser);
/* Parse the type-specifiers. */
- cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+ cp_parser_type_specifier_seq (parser, /*is_declaration=*/false,
/*is_trailing_return=*/false,
&type_specifiers);
/* If that didn't work, stop. */
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
{
bool expr_non_constant_p;
- maybe_warn_cpp0x ("extended initializer lists");
+ maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
expression_list = cp_parser_braced_list (parser, &expr_non_constant_p);
CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1;
expression_list = build_tree_list (NULL_TREE, expression_list);
return cp_parser_class_name (parser,
/*typename_keyword_p=*/true,
/*template_keyword_p=*/template_p,
- none_type,
+ typename_type,
/*check_dependency_p=*/true,
/*class_head_p=*/false,
/*is_declaration=*/true);
parm = grokdeclarator (parameter_declarator->declarator,
¶meter_declarator->decl_specifiers,
- PARM, /*initialized=*/0,
+ TPARM, /*initialized=*/0,
/*attrlist=*/NULL);
if (parm == error_mark_node)
return error_mark_node;
case RID_TEMPLATE:
{
- tree parameter_list;
tree identifier;
tree default_argument;
/* Look for the `<'. */
cp_parser_require (parser, CPP_LESS, "%<<%>");
/* Parse the template-parameter-list. */
- parameter_list = cp_parser_template_parameter_list (parser);
+ cp_parser_template_parameter_list (parser);
/* Look for the `>'. */
cp_parser_require (parser, CPP_GREATER, "%<>%>");
/* Look for the `class' keyword. */
cp_token_position start_of_id = 0;
deferred_access_check *chk;
VEC (deferred_access_check,gc) *access_check;
- cp_token *next_token = NULL, *next_token_2 = NULL, *token = NULL;
+ cp_token *next_token = NULL, *next_token_2 = NULL;
bool is_identifier;
/* If the next token corresponds to a template-id, there is no need
/* Parse the template-name. */
is_identifier = false;
- token = cp_lexer_peek_token (parser->lexer);
templ = cp_parser_template_name (parser, template_keyword_p,
check_dependency_p,
is_declaration,
/* Look up the name. */
decl = cp_parser_lookup_name (parser, identifier,
none_type,
- /*is_template=*/false,
+ /*is_template=*/true,
/*is_namespace=*/false,
check_dependency_p,
/*ambiguous_decls=*/NULL,
token->location);
- decl = maybe_get_template_decl_from_type_decl (decl);
/* If DECL is a template, then the name was a template-name. */
if (TREE_CODE (decl) == TEMPLATE_DECL)
cp_parser_abort_tentative_parse (parser);
else
{
+ tree probe;
+
if (TREE_CODE (argument) == INDIRECT_REF)
{
gcc_assert (REFERENCE_REF_P (argument));
argument = TREE_OPERAND (argument, 0);
}
- if (TREE_CODE (argument) == VAR_DECL)
+ /* If we're in a template, we represent a qualified-id referring
+ to a static data member as a SCOPE_REF even if the scope isn't
+ dependent so that we can check access control later. */
+ probe = argument;
+ if (TREE_CODE (probe) == SCOPE_REF)
+ probe = TREE_OPERAND (probe, 1);
+ if (TREE_CODE (probe) == VAR_DECL)
{
/* A variable without external linkage might still be a
valid constant-expression, so no error is issued here
if the external-linkage check fails. */
- if (!address_p && !DECL_EXTERNAL_LINKAGE_P (argument))
+ if (!address_p && !DECL_EXTERNAL_LINKAGE_P (probe))
cp_parser_simulate_error (parser);
}
else if (is_overloaded_fn (argument))
int declares_class_or_enum;
cp_decl_specifier_seq decl_specifiers;
tree extension_specifier = NULL_TREE;
- cp_token *token;
/* Look for an (optional) storage-class-specifier or
function-specifier. */
control while processing explicit instantiation directives. */
push_deferring_access_checks (dk_no_check);
/* Parse a decl-specifier-seq. */
- token = cp_lexer_peek_token (parser->lexer);
cp_parser_decl_specifier_seq (parser,
CP_PARSER_FLAGS_OPTIONAL,
&decl_specifiers,
break;
case RID_AUTO:
- maybe_warn_cpp0x ("C++0x auto");
+ maybe_warn_cpp0x (CPP0X_AUTO);
type = make_auto ();
break;
/* If the type-specifier was for a built-in type, we're done. */
if (type)
{
- tree id;
-
/* Record the type. */
if (decl_specs
&& (token->keyword != RID_SIGNED
decl_specs->any_specifiers_p = true;
/* Consume the token. */
- id = cp_lexer_consume_token (parser->lexer)->u.value;
+ cp_lexer_consume_token (parser->lexer);
/* There is no valid C++ program where a non-template type is
followed by a "<". That usually indicates that the user thought
|| cp_lexer_next_token_is_keyword (parser->lexer, RID_STRUCT))
{
if (cxx_dialect == cxx98)
- maybe_warn_cpp0x ("scoped enums");
+ maybe_warn_cpp0x (CPP0X_SCOPED_ENUMS);
/* Consume the `struct' or `class'. */
cp_lexer_consume_token (parser->lexer);
|| cp_lexer_next_token_is_keyword (parser->lexer, RID_STRUCT))
{
if (cxx_dialect == cxx98)
- maybe_warn_cpp0x ("scoped enums");
+ maybe_warn_cpp0x (CPP0X_SCOPED_ENUMS);
/* Consume the `struct' or `class' token. */
cp_lexer_consume_token (parser->lexer);
cp_lexer_consume_token (parser->lexer);
/* Parse the type-specifier-seq. */
- cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+ cp_parser_type_specifier_seq (parser, /*is_declaration=*/false,
/*is_trailing_return=*/false,
&type_specifiers);
return NULL_TREE;
if (cxx_dialect == cxx98)
- maybe_warn_cpp0x ("scoped enums");
+ maybe_warn_cpp0x (CPP0X_SCOPED_ENUMS);
has_underlying_type = true;
bool* parenthesized_p,
bool member_p)
{
- cp_token *token;
cp_declarator *declarator;
enum tree_code code;
cp_cv_quals cv_quals;
if (cp_parser_allow_gnu_extensions_p (parser))
attributes = cp_parser_attributes_opt (parser);
- /* Peek at the next token. */
- token = cp_lexer_peek_token (parser->lexer);
-
/* Check for the ptr-operator production. */
cp_parser_parse_tentatively (parser);
/* Parse the ptr-operator. */
/*only_current_p=*/false);
/* If that failed, the declarator is invalid. */
if (TREE_CODE (type) == TYPENAME_TYPE)
- error_at (declarator_id_start_token->location,
- "%<%T::%E%> is not a type",
- TYPE_CONTEXT (qualifying_scope),
- TYPE_IDENTIFIER (qualifying_scope));
+ {
+ if (typedef_variant_p (type))
+ error_at (declarator_id_start_token->location,
+ "cannot define member of dependent typedef "
+ "%qT", type);
+ else
+ error_at (declarator_id_start_token->location,
+ "%<%T::%E%> is not a type",
+ TYPE_CONTEXT (qualifying_scope),
+ TYPE_IDENTIFIER (qualifying_scope));
+ }
qualifying_scope = type;
}
unqualified_name = constructor_name (class_type);
sfk = sfk_constructor;
}
+ else if (is_overloaded_fn (unqualified_name)
+ && DECL_CONSTRUCTOR_P (get_first_fn
+ (unqualified_name)))
+ sfk = sfk_constructor;
if (ctor_dtor_or_conv_p && sfk != sfk_none)
*ctor_dtor_or_conv_p = -1;
cp_declarator *abstract_declarator;
/* Parse the type-specifier-seq. */
- cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+ cp_parser_type_specifier_seq (parser, /*is_declaration=*/false,
is_trailing_return,
&type_specifier_seq);
if (type_specifier_seq.type == error_mark_node)
type-specifier-seq:
attributes type-specifier-seq [opt]
- If IS_CONDITION is true, we are at the start of a "condition",
- e.g., we've just seen "if (".
+ If IS_DECLARATION is true, we are at the start of a "condition" or
+ exception-declaration, so we might be followed by a declarator-id.
If IS_TRAILING_RETURN is true, we are in a trailing-return-type,
i.e. we've just seen "->".
static void
cp_parser_type_specifier_seq (cp_parser* parser,
- bool is_condition,
+ bool is_declaration,
bool is_trailing_return,
cp_decl_specifier_seq *type_specifier_seq)
{
would be clearer just to allow a decl-specifier-seq here, and
then add a semantic restriction that if any decl-specifiers
that are not type-specifiers appear, the program is invalid. */
- if (is_condition && !is_cv_qualifier)
+ if (is_declaration && !is_cv_qualifier)
flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES;
}
bool *parenthesized_p)
{
int declares_class_or_enum;
- bool greater_than_is_operator_p;
cp_decl_specifier_seq decl_specifiers;
cp_declarator *declarator;
tree default_argument;
template-parameter, the first non-nested `>' is taken as the end
of the template parameter-list rather than a greater-than
operator. */
- greater_than_is_operator_p = !template_parm_p;
/* Type definitions may not appear in parameter types. */
saved_message = parser->type_definition_forbidden_message;
CP_PARSER_FLAGS_NONE,
&decl_specifiers,
&declares_class_or_enum);
+
+ /* Complain about missing 'typename' or other invalid type names. */
+ if (!decl_specifiers.any_type_specifiers_p)
+ cp_parser_parse_and_diagnose_invalid_type_name (parser);
+
/* If an error occurred, there's no reason to attempt to parse the
rest of the declaration. */
if (cp_parser_error_occurred (parser))
}
else if (token->type == CPP_OPEN_BRACE)
{
- maybe_warn_cpp0x ("extended initializer lists");
+ maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
init = cp_parser_braced_list (parser, non_constant_p);
CONSTRUCTOR_IS_DIRECT_INIT (init) = 1;
}
identifier_token->location);
if (ambiguous_decls)
{
- error_at (identifier_token->location,
- "reference to %qD is ambiguous", identifier);
- print_candidates (ambiguous_decls);
if (cp_parser_parsing_tentatively (parser))
- {
- identifier_token->ambiguous_p = true;
- cp_parser_simulate_error (parser);
- }
+ cp_parser_simulate_error (parser);
return error_mark_node;
}
}
prefix_attributes = decl_specifiers.attributes;
decl_specifiers.attributes = NULL_TREE;
/* Check for an invalid type-name. */
- if (!decl_specifiers.type
+ if (!decl_specifiers.any_type_specifiers_p
&& cp_parser_parse_and_diagnose_invalid_type_name (parser))
return;
/* If there is no declarator, then the decl-specifier-seq should
if (token->keyword == RID_DEFAULT
|| token->keyword == RID_DELETE)
{
- maybe_warn_cpp0x ("defaulted and deleted functions");
+ maybe_warn_cpp0x (CPP0X_DEFAULTED_DELETED);
return token->u.value;
}
= "types may not be defined in exception-declarations";
/* Parse the type-specifier-seq. */
- cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+ cp_parser_type_specifier_seq (parser, /*is_declaration=*/true,
/*is_trailing_return=*/false,
&type_specifiers);
/* If it's a `)', then there is no declarator. */
lookup_member, we must enter the scope here. */
if (dependent_p)
pushed_scope = push_scope (parser->scope);
+
+ /* 3.4.3.1: In a lookup in which the constructor is an acceptable
+ lookup result and the nested-name-specifier nominates a class C:
+ * if the name specified after the nested-name-specifier, when
+ looked up in C, is the injected-class-name of C (Clause 9), or
+ * if the name specified after the nested-name-specifier is the
+ same as the identifier or the simple-template-id's template-
+ name in the last component of the nested-name-specifier,
+ the name is instead considered to name the constructor of
+ class C. [ Note: for example, the constructor is not an
+ acceptable lookup result in an elaborated-type-specifier so
+ the constructor would not be used in place of the
+ injected-class-name. --end note ] Such a constructor name
+ shall be used only in the declarator-id of a declaration that
+ names a constructor or in a using-declaration. */
+ if (tag_type == none_type
+ && CLASS_TYPE_P (parser->scope)
+ && constructor_name_p (name, parser->scope))
+ name = ctor_identifier;
+
/* If the PARSER->SCOPE is a template specialization, it
may be instantiated during name lookup. In that case,
errors may be issued. Even if we rollback the current
if (!decl || decl == error_mark_node)
return error_mark_node;
+ /* Pull out the template from an injected-class-name (or multiple). */
+ if (is_template)
+ decl = maybe_get_template_decl_from_type_decl (decl);
+
/* If it's a TREE_LIST, the result of the lookup was ambiguous. */
if (TREE_CODE (decl) == TREE_LIST)
{
if (declarator->u.id.qualifying_scope)
{
tree scope;
- tree member;
scope = declarator->u.id.qualifying_scope;
- member = declarator->u.id.unqualified_name;
while (scope && CLASS_TYPE_P (scope))
{
template <class T> void S<T>::R<T>::f (); */
if (parser->num_template_parameter_lists < num_templates)
{
- if (declarator)
+ if (declarator && !current_function_decl)
error_at (location, "specializing member %<%T::%E%> "
"requires %<template<>%> syntax",
declarator->u.id.qualifying_scope,
declarator->u.id.unqualified_name);
+ else if (declarator)
+ error_at (location, "invalid declaration of %<%T::%E%>",
+ declarator->u.id.qualifying_scope,
+ declarator->u.id.unqualified_name);
else
error_at (location, "too few template-parameter-lists");
return false;
cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
{
bool constructor_p;
- tree type_decl = NULL_TREE;
- bool nested_name_p;
+ tree nested_name_specifier;
cp_token *next_token;
/* The common case is that this is not a constructor declarator, so
cp_parser_global_scope_opt (parser,
/*current_scope_valid_p=*/false);
/* Look for the nested-name-specifier. */
- nested_name_p
+ nested_name_specifier
= (cp_parser_nested_name_specifier_opt (parser,
/*typename_keyword_p=*/false,
/*check_dependency_p=*/false,
/*type_p=*/false,
- /*is_declaration=*/false)
- != NULL_TREE);
+ /*is_declaration=*/false));
/* Outside of a class-specifier, there must be a
nested-name-specifier. */
- if (!nested_name_p &&
+ if (!nested_name_specifier &&
(!at_class_scope_p () || !TYPE_BEING_DEFINED (current_class_type)
|| friend_p))
constructor_p = false;
+ else if (nested_name_specifier == error_mark_node)
+ constructor_p = false;
+
+ /* If we have a class scope, this is easy; DR 147 says that S::S always
+ names the constructor, and no other qualified name could. */
+ if (constructor_p && nested_name_specifier
+ && TYPE_P (nested_name_specifier))
+ {
+ tree id = cp_parser_unqualified_id (parser,
+ /*template_keyword_p=*/false,
+ /*check_dependency_p=*/false,
+ /*declarator_p=*/true,
+ /*optional_p=*/false);
+ if (is_overloaded_fn (id))
+ id = DECL_NAME (get_first_fn (id));
+ if (!constructor_name_p (id, nested_name_specifier))
+ constructor_p = false;
+ }
/* If we still think that this might be a constructor-declarator,
look for a class-name. */
- if (constructor_p)
+ else if (constructor_p)
{
/* If we have:
- template <typename T> struct S { S(); };
- template <typename T> S<T>::S ();
+ template <typename T> struct S {
+ S();
+ };
- we must recognize that the nested `S' names a class.
- Similarly, for:
-
- template <typename T> S<T>::S<T> ();
-
- we must recognize that the nested `S' names a template. */
+ we must recognize that the nested `S' names a class. */
+ tree type_decl;
type_decl = cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
/*is_declaration=*/false);
/* If there was no class-name, then this is not a constructor. */
constructor_p = !cp_parser_error_occurred (parser);
- }
- /* If we're still considering a constructor, we have to see a `(',
- to begin the parameter-declaration-clause, followed by either a
- `)', an `...', or a decl-specifier. We need to check for a
- type-specifier to avoid being fooled into thinking that:
+ /* If we're still considering a constructor, we have to see a `(',
+ to begin the parameter-declaration-clause, followed by either a
+ `)', an `...', or a decl-specifier. We need to check for a
+ type-specifier to avoid being fooled into thinking that:
- S::S (f) (int);
+ S (f) (int);
- is a constructor. (It is actually a function named `f' that
- takes one parameter (of type `int') and returns a value of type
- `S::S'. */
- if (constructor_p
- && cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
- {
- if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)
+ is a constructor. (It is actually a function named `f' that
+ takes one parameter (of type `int') and returns a value of type
+ `S'. */
+ if (constructor_p
+ && !cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
+ constructor_p = false;
+
+ if (constructor_p
+ && cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)
&& cp_lexer_next_token_is_not (parser->lexer, CPP_ELLIPSIS)
/* A parameter declaration begins with a decl-specifier,
which is either the "attribute" keyword, a storage class
constructor_p = !cp_parser_error_occurred (parser);
}
}
- else
- constructor_p = false;
+
/* We did not really want to consume any tokens. */
cp_parser_abort_tentative_parse (parser);
cp_parser_perform_template_parameter_access_checks (checks);
}
}
+
+ /* Complain about missing 'typename' or other invalid type names. */
+ if (!decl_specifiers.any_type_specifiers_p)
+ cp_parser_parse_and_diagnose_invalid_type_name (parser);
+
/* If it's not a template class, try for a template function. If
the next token is a `;', then this declaration does not declare
anything. But, if there were errors in the decl-specifiers, then
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
{
- maybe_warn_cpp0x ("extended initializer lists");
+ maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
expression_list = cp_parser_braced_list (parser, &nonconst_p);
CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1;
if (TREE_CODE (type) == TYPE_DECL)
cp_parser_condition, from whence the bulk of this is copied. */
cp_parser_parse_tentatively (parser);
- cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+ cp_parser_type_specifier_seq (parser, /*is_declaration=*/true,
/*is_trailing_return=*/false,
&type_specifiers);
if (cp_parser_parse_definitely (parser))
}
collapse_err = true;
cp_parser_statement_seq_opt (parser, NULL);
- cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
+ if (cp_lexer_next_token_is (parser->lexer, CPP_EOF))
+ break;
}
}
void
c_parse_file (void)
{
- bool error_occurred;
static bool already_called = false;
if (already_called)
the_parser = cp_parser_new ();
push_deferring_access_checks (flag_access_control
? dk_no_deferred : dk_no_check);
- error_occurred = cp_parser_translation_unit (the_parser);
+ cp_parser_translation_unit (the_parser);
the_parser = NULL;
}