summaryrefslogtreecommitdiff
path: root/gcc/cp/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r--gcc/cp/parser.c125
1 files changed, 114 insertions, 11 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index d02ad360d16..634047e5d05 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -806,7 +806,7 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer, cp_token *token)
/* Check to see if this token is a keyword. */
if (token->type == CPP_NAME)
{
- if (C_IS_RESERVED_WORD (token->u.value))
+ if (IDENTIFIER_KEYWORD_P (token->u.value))
{
/* Mark this token as a keyword. */
token->type = CPP_KEYWORD;
@@ -2983,7 +2983,9 @@ cp_parser_check_for_invalid_template_id (cp_parser* parser,
if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))
{
- if (TYPE_P (type))
+ if (TREE_CODE (type) == TYPE_DECL)
+ type = TREE_TYPE (type);
+ if (TYPE_P (type) && !template_placeholder_p (type))
error_at (location, "%qT is not a template", type);
else if (identifier_p (type))
{
@@ -3270,9 +3272,21 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id,
}
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);
+ {
+ if (TREE_CODE (parser->scope) == TYPENAME_TYPE)
+ error_at (location,
+ "need %<typename%> before %<%T::%D::%E%> because "
+ "%<%T::%D%> is a dependent scope",
+ TYPE_CONTEXT (parser->scope),
+ TYPENAME_TYPE_FULLNAME (parser->scope),
+ id,
+ TYPE_CONTEXT (parser->scope),
+ TYPENAME_TYPE_FULLNAME (parser->scope));
+ else
+ 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))
{
if (!COMPLETE_TYPE_P (parser->scope))
@@ -8636,6 +8650,85 @@ cp_parser_tokens_start_cast_expression (cp_parser *parser)
}
}
+/* Try to find a legal C++-style cast to DST_TYPE for ORIG_EXPR, trying them
+ in the order: const_cast, static_cast, reinterpret_cast.
+
+ Don't suggest dynamic_cast.
+
+ Return the first legal cast kind found, or NULL otherwise. */
+
+static const char *
+get_cast_suggestion (tree dst_type, tree orig_expr)
+{
+ tree trial;
+
+ /* Reuse the parser logic by attempting to build the various kinds of
+ cast, with "complain" disabled.
+ Identify the first such cast that is valid. */
+
+ /* Don't attempt to run such logic within template processing. */
+ if (processing_template_decl)
+ return NULL;
+
+ /* First try const_cast. */
+ trial = build_const_cast (dst_type, orig_expr, tf_none);
+ if (trial != error_mark_node)
+ return "const_cast";
+
+ /* If that fails, try static_cast. */
+ trial = build_static_cast (dst_type, orig_expr, tf_none);
+ if (trial != error_mark_node)
+ return "static_cast";
+
+ /* Finally, try reinterpret_cast. */
+ trial = build_reinterpret_cast (dst_type, orig_expr, tf_none);
+ if (trial != error_mark_node)
+ return "reinterpret_cast";
+
+ /* No such cast possible. */
+ return NULL;
+}
+
+/* If -Wold-style-cast is enabled, add fix-its to RICHLOC,
+ suggesting how to convert a C-style cast of the form:
+
+ (DST_TYPE)ORIG_EXPR
+
+ to a C++-style cast.
+
+ The primary range of RICHLOC is asssumed to be that of the original
+ expression. OPEN_PAREN_LOC and CLOSE_PAREN_LOC give the locations
+ of the parens in the C-style cast. */
+
+static void
+maybe_add_cast_fixit (rich_location *rich_loc, location_t open_paren_loc,
+ location_t close_paren_loc, tree orig_expr,
+ tree dst_type)
+{
+ /* This function is non-trivial, so bail out now if the warning isn't
+ going to be emitted. */
+ if (!warn_old_style_cast)
+ return;
+
+ /* Try to find a legal C++ cast, trying them in order:
+ const_cast, static_cast, reinterpret_cast. */
+ const char *cast_suggestion = get_cast_suggestion (dst_type, orig_expr);
+ if (!cast_suggestion)
+ return;
+
+ /* Replace the open paren with "CAST_SUGGESTION<". */
+ pretty_printer pp;
+ pp_printf (&pp, "%s<", cast_suggestion);
+ rich_loc->add_fixit_replace (open_paren_loc, pp_formatted_text (&pp));
+
+ /* Replace the close paren with "> (". */
+ rich_loc->add_fixit_replace (close_paren_loc, "> (");
+
+ /* Add a closing paren after the expr (the primary range of RICH_LOC). */
+ rich_loc->add_fixit_insert_after (")");
+}
+
+
/* Parse a cast-expression.
cast-expression:
@@ -8671,6 +8764,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
/* Consume the `('. */
cp_token *open_paren = cp_lexer_consume_token (parser->lexer);
location_t open_paren_loc = open_paren->location;
+ location_t close_paren_loc = UNKNOWN_LOCATION;
/* A very tricky bit is that `(struct S) { 3 }' is a
compound-literal (which we permit in C++ as an extension).
@@ -8733,7 +8827,10 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
/* Look for the type-id. */
type = cp_parser_type_id (parser);
/* Look for the closing `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ cp_token *close_paren
+ = cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ if (close_paren)
+ close_paren_loc = close_paren->location;
parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
}
@@ -8763,8 +8860,13 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
&& !in_system_header_at (input_location)
&& !VOID_TYPE_P (type)
&& current_lang_name != lang_name_c)
- warning (OPT_Wold_style_cast,
- "use of old-style cast to %qT", type);
+ {
+ gcc_rich_location rich_loc (input_location);
+ maybe_add_cast_fixit (&rich_loc, open_paren_loc, close_paren_loc,
+ expr, type);
+ warning_at_rich_loc (&rich_loc, OPT_Wold_style_cast,
+ "use of old-style cast to %qT", type);
+ }
/* Only type conversions to integral or enumeration types
can be used in constant-expressions. */
@@ -16972,7 +17074,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
/* There is no valid C++ program where a non-template type is
followed by a "<". That usually indicates that the user
thought that the type was a template. */
- cp_parser_check_for_invalid_template_id (parser, TREE_TYPE (type),
+ cp_parser_check_for_invalid_template_id (parser, type,
none_type,
token->location);
}
@@ -20001,7 +20103,8 @@ cp_parser_direct_declarator (cp_parser* parser,
{
if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR)
sfk = sfk_destructor;
- else if (IDENTIFIER_TYPENAME_P (unqualified_name))
+ else if (identifier_p (unqualified_name)
+ && IDENTIFIER_CONV_OP_P (unqualified_name))
sfk = sfk_conversion;
else if (/* There's no way to declare a constructor
for an unnamed type, even if the type
@@ -20451,7 +20554,7 @@ inject_this_parameter (tree ctype, cp_cv_quals quals)
return;
}
- this_parm = build_this_parm (ctype, quals);
+ this_parm = build_this_parm (NULL_TREE, ctype, quals);
/* Clear this first to avoid shortcut in cp_build_indirect_ref. */
current_class_ptr = NULL_TREE;
current_class_ref