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 "
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,
/* Emit a diagnostic for the invalid type. */
cp_parser_diagnose_invalid_type_name (parser, parser->scope,
id, token->location);
+ 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 (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:
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;
{
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. */
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;" */
+ /* 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)
- && TREE_CODE (statement) == SCOPE_REF)
- error_at (token->location, "need %<typename%> before %qE because "
- "%qT is a dependent scope",
- statement, TREE_OPERAND (statement, 0));
+ && !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);
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))
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)
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);
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. */
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;
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;
}
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;
}
}
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;
}
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))
{
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);
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)
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;
}