/* Get a new token from the preprocessor. */
token->type
= c_lex_with_flags (&token->u.value, &token->location, &token->flags,
- lexer == NULL ? 0 : C_LEX_RAW_STRINGS);
+ lexer == NULL ? 0 : C_LEX_STRING_NO_JOIN);
token->keyword = RID_MAX;
token->pragma_kind = PRAGMA_NONE;
case CPP_STRING16:
case CPP_STRING32:
case CPP_WSTRING:
+ case CPP_UTF8STRING:
fprintf (stream, " \"%s\"", TREE_STRING_POINTER (token->u.value));
break;
/* The construct is optional. If it is not present, then no error
should be issued. */
CP_PARSER_FLAGS_OPTIONAL = 0x1,
- /* When parsing a type-specifier, do not allow user-defined types. */
- CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES = 0x2
+ /* When parsing a type-specifier, treat user-defined type-names
+ as non-type identifiers. */
+ CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES = 0x2,
+ /* When parsing a type-specifier, do not try to parse a class-specifier
+ or enum-specifier. */
+ CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS = 0x4
};
/* This type is used for parameters and variables which hold
(cp_parser *);
static tree cp_parser_template_type_arg
(cp_parser *);
+static tree cp_parser_trailing_type_id (cp_parser *);
static tree cp_parser_type_id_1
- (cp_parser *, bool);
+ (cp_parser *, bool, bool);
static void cp_parser_type_specifier_seq
- (cp_parser *, bool, cp_decl_specifier_seq *);
+ (cp_parser *, bool, bool, cp_decl_specifier_seq *);
static tree cp_parser_parameter_declaration_clause
(cp_parser *);
static tree cp_parser_parameter_declaration_list
return (token->type == CPP_STRING ||
token->type == CPP_STRING16 ||
token->type == CPP_STRING32 ||
- token->type == CPP_WSTRING);
+ token->type == CPP_WSTRING ||
+ token->type == CPP_UTF8STRING);
}
/* Returns nonzero if TOKEN is the indicated KEYWORD. */
if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
error_at (location, "%qE in namespace %qE does not name a type",
id, parser->scope);
+ else if (TYPE_P (parser->scope)
+ && dependent_scope_p (parser->scope))
+ error_at (location, "need %<typename%> before %<%T::%E%> to name "
+ "a type in dependent scope %qT",
+ 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);
/*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. */
+ otherwise this is not a simple variable declaration. */
if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME)
- || (parser->scope && TYPE_P (parser->scope)
- && dependent_type_p (parser->scope))
|| TREE_CODE (id) == TYPE_DECL)
{
cp_parser_abort_tentative_parse (parser);
{
default:
case CPP_STRING:
+ case CPP_UTF8STRING:
TREE_TYPE (value) = char_array_type_node;
break;
case CPP_STRING16:
case CPP_STRING16:
case CPP_STRING32:
case CPP_WSTRING:
+ case CPP_UTF8STRING:
/* ??? Should wide strings be allowed when parser->translate_strings_p
is false (i.e. in attributes)? If not, we can kill the third
argument to cp_parser_string_literal. */
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. */
parser->type_definition_forbidden_message = saved_message;
LAMBDA_EXPR_CAPTURE_LIST (lambda_expr) = newlist;
}
+ maybe_add_lambda_conv_op (type);
+
type = finish_struct (type, /*attributes=*/NULL_TREE);
parser->num_template_parameter_lists = saved_num_template_parameter_lists;
declarator = make_id_declarator (NULL_TREE, ansi_opname (CALL_EXPR),
sfk_none);
- quals = (LAMBDA_EXPR_MUTABLE_P (lambda_expr)
- ? TYPE_UNQUALIFIED : TYPE_QUAL_CONST);
+ quals = TYPE_UNQUALIFIED;
+ if (LAMBDA_EXPR_CAPTURE_LIST (lambda_expr) == NULL_TREE
+ && LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) == CPLD_NONE)
+ {
+ /* A lambda with no captures has a static op() and a conversion op
+ to function type. */
+ if (LAMBDA_EXPR_MUTABLE_P (lambda_expr))
+ error ("lambda expression with no captures declared mutable");
+ return_type_specs.storage_class = sc_static;
+ }
+ else if (!LAMBDA_EXPR_MUTABLE_P (lambda_expr))
+ quals = TYPE_QUAL_CONST;
declarator = make_call_declarator (declarator, param_list, quals,
exception_spec,
/*late_return_type=*/NULL_TREE);
fco = grokmethod (&return_type_specs,
- declarator,
- attributes);
+ declarator,
+ attributes);
DECL_INITIALIZED_IN_CLASS_P (fco) = 1;
DECL_ARTIFICIAL (fco) = 1;
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;" */
+ 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 to name "
+ "a type in dependent scope %qT",
+ statement, TREE_OPERAND (statement, 0));
+
/* 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. */
parser->type_definition_forbidden_message = saved_message;
cp_parser_parse_definitely (parser);
else
{
+ bool saved_greater_than_is_operator_p;
+
/* Abort our attempt to parse an id-expression or member access
expression. */
cp_parser_abort_tentative_parse (parser);
+ /* Within a parenthesized expression, a `>' token is always
+ the greater-than operator. */
+ saved_greater_than_is_operator_p
+ = parser->greater_than_is_operator_p;
+ parser->greater_than_is_operator_p = true;
+
/* Parse a full expression. */
expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
+
+ /* The `>' token might be the end of a template-id or
+ template-parameter-list now. */
+ parser->greater_than_is_operator_p
+ = saved_greater_than_is_operator_p;
}
/* Go back to evaluating expressions. */
/* 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 (type_specifiers.type == error_mark_node)
switch (keyword)
{
case RID_ENUM:
+ if ((flags & CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS))
+ goto elaborated_type_specifier;
+
/* Look for the enum-specifier. */
type_spec = cp_parser_enum_specifier (parser);
/* If that worked, we're done. */
case RID_CLASS:
case RID_STRUCT:
case RID_UNION:
+ if ((flags & CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS))
+ goto elaborated_type_specifier;
+
/* Parse tentatively so that we can back up if we don't find a
class-specifier. */
cp_parser_parse_tentatively (parser);
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);
/* At this point this is surely not elaborated type specifier. */
#ifdef HANDLE_PRAGMA_VISIBILITY
if (has_visibility)
- pop_visibility ();
+ pop_visibility (1);
#endif
/* Finish the namespace. */
/* Parse a late-specified return type, if any. This is not a separate
non-terminal, but part of a function declarator, which looks like
- -> type-id
+ -> trailing-type-specifier-seq abstract-declarator(opt)
Returns the type indicated by the type-id. */
/* Consume the ->. */
cp_lexer_consume_token (parser->lexer);
- return cp_parser_type_id (parser);
+ return cp_parser_trailing_type_id (parser);
}
/* Parse a declarator-id.
Returns the TYPE specified. */
static tree
-cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg)
+cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg,
+ bool is_trailing_return)
{
cp_decl_specifier_seq type_specifier_seq;
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)
return error_mark_node;
static tree cp_parser_type_id (cp_parser *parser)
{
- return cp_parser_type_id_1 (parser, false);
+ return cp_parser_type_id_1 (parser, false, false);
}
static tree cp_parser_template_type_arg (cp_parser *parser)
{
- return cp_parser_type_id_1 (parser, true);
+ return cp_parser_type_id_1 (parser, true, false);
+}
+
+static tree cp_parser_trailing_type_id (cp_parser *parser)
+{
+ return cp_parser_type_id_1 (parser, false, true);
}
/* Parse a type-specifier-seq.
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 "->".
Sets *TYPE_SPECIFIER_SEQ to represent the sequence. */
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)
{
bool seen_type_specifier = false;
/* Clear the TYPE_SPECIFIER_SEQ. */
clear_decl_specs (type_specifier_seq);
+ /* In the context of a trailing return type, enum E { } is an
+ elaborated-type-specifier followed by a function-body, not an
+ enum-specifier. */
+ if (is_trailing_return)
+ flags |= CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS;
+
/* Parse the type-specifiers and attributes. */
while (true)
{
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;
}
= "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. */
if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
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_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;
}
}