Implement P0634R3, Down with typename!
* parser.c (CP_PARSER_FLAGS_TYPENAME_OPTIONAL): New enumerator. (cp_parser_type_name): Remove declaration. (cp_parser_postfix_expression): Pass CP_PARSER_FLAGS_TYPENAME_OPTIONAL to cp_parser_type_id. (cp_parser_new_type_id): Pass CP_PARSER_FLAGS_TYPENAME_OPTIONAL to cp_parser_type_specifier_seq. (cp_parser_lambda_declarator_opt): Pass CP_PARSER_FLAGS_TYPENAME_OPTIONAL to cp_parser_parameter_declaration_clause. (cp_parser_condition): Pass CP_PARSER_FLAGS_NONE to cp_parser_declarator. (cp_parser_simple_declaration): Pass CP_PARSER_FLAGS_NONE to cp_parser_init_declarator. (cp_parser_conversion_type_id): Pass CP_PARSER_FLAGS_NONE to cp_parser_type_specifier_seq. (cp_parser_default_type_template_argument): Pass CP_PARSER_FLAGS_TYPENAME_OPTIONAL to cp_parser_type_id. (cp_parser_template_parameter): Pass CP_PARSER_FLAGS_TYPENAME_OPTIONAL to cp_parser_parameter_declaration. (cp_parser_explicit_instantiation): Pass CP_PARSER_FLAGS_NONE to cp_parser_declarator. (cp_parser_simple_type_specifier): Adjust call to cp_parser_type_name to relay if we should treat the typename keyword as optional. Maybe call cp_parser_make_typename_type is parsing a template-id and it's not a TYPE_DECL. (cp_parser_type_name): Remove unused function. (cp_parser_enum_specifier): Pass to CP_PARSER_FLAGS_NONE cp_parser_type_specifier_seq. (cp_parser_alias_declaration): Pass CP_PARSER_FLAGS_TYPENAME_OPTIONAL to cp_parser_type_id. (cp_parser_init_declarator): New parameter. Pass it down to cp_parser_declarator. (cp_parser_declarator): New parameter. Pass CP_PARSER_FLAGS_NONE to cp_parser_declarator. Pass the new parameter to cp_parser_direct_declarator. (cp_parser_direct_declarator): New parameter. Pass it to cp_parser_parameter_declaration_clause and cp_parser_declarator. (cp_parser_declarator_id): (cp_parser_type_id_1): New parameter. Pass it to cp_parser_type_specifier_seq. Adjust call to cp_parser_declarator. (cp_parser_type_id): New parameter. Pass it to cp_parser_type_id_1. (cp_parser_template_type_arg): Pass CP_PARSER_FLAGS_NONE to cp_parser_type_id_1. (cp_parser_trailing_type_id): Pass CP_PARSER_FLAGS_TYPENAME_OPTIONAL to cp_parser_type_id_1. (cp_parser_type_specifier_seq): New parameter. (function_being_declared_is_template_p): (cp_parser_parameter_declaration_clause): New parameter. Pass it to cp_parser_parameter_declaration_list. (cp_parser_parameter_declaration_list): New parameter. Pass it to cp_parser_parameter_declaration. (cp_parser_parameter_declaration): New parameter. Pass it to cp_parser_decl_specifier_seq. Pass CP_PARSER_FLAGS_NONE to cp_parser_declarator. (cp_parser_member_declaration): Adjust call to cp_parser_decl_specifier_seq to also include CP_PARSER_FLAGS_TYPENAME_OPTIONAL. Pass CP_PARSER_FLAGS_TYPENAME_OPTIONAL to cp_parser_declarator. (cp_parser_exception_declaration): Pass CP_PARSER_FLAGS_NONE to cp_parser_type_specifier_seq and cp_parser_declarator. (cp_parser_requirement_parameter_list): Pass CP_PARSER_FLAGS_NONE to cp_parser_parameter_declaration_clause. (cp_parser_constructor_declarator_p): Resolve the TYPENAME_TYPE. (cp_parser_single_declaration): Pass CP_PARSER_FLAGS_TYPENAME_OPTIONAL to cp_parser_decl_specifier_seq and cp_parser_init_declarator. (cp_parser_cache_defarg): Pass CP_PARSER_FLAGS_NONE to cp_parser_declarator and cp_parser_parameter_declaration_list. (cp_parser_objc_method_tail_params_opt): Pass CP_PARSER_FLAGS_NONE to cp_parser_parameter_declaration. (cp_parser_objc_class_ivars): Pass CP_PARSER_FLAGS_NONE to cp_parser_declarator. (cp_parser_objc_try_catch_finally_statement): Pass CP_PARSER_FLAGS_NONE to cp_parser_parameter_declaration (cp_parser_objc_struct_declaration): Pass CP_PARSER_FLAGS_NONE to cp_parser_declarator. (cp_parser_omp_for_loop_init): Pass CP_PARSER_FLAGS_NONE to cp_parser_declarator and cp_parser_type_specifier_seq. * g++.dg/cpp0x/alias-decl-43.C: Adjust dg-error. * g++.dg/cpp0x/decltype67.C: Only expect error in c++17_down. * g++.dg/cpp1z/typename1.C: New test. * g++.dg/cpp2a/typename1.C: New test. * g++.dg/cpp2a/typename10.C: New test. * g++.dg/cpp2a/typename11.C: New test. * g++.dg/cpp2a/typename2.C: New test. * g++.dg/cpp2a/typename3.C: New test. * g++.dg/cpp2a/typename4.C: New test. * g++.dg/cpp2a/typename5.C: New test. * g++.dg/cpp2a/typename6.C: New test. * g++.dg/cpp2a/typename7.C: New test. * g++.dg/cpp2a/typename8.C: New test. * g++.dg/cpp2a/typename9.C: New test. * g++.dg/diagnostic/missing-typename.C: Only run the test in c++17_down. * g++.dg/other/crash-9.C: Add template disambiguator. * g++.dg/other/nontype-1.C: Only expect error in c++17_down. * g++.dg/parse/crash13.C: Likewise. * g++.dg/parse/error36.C: Likewise. * g++.dg/parse/no-typename1.C: Likewise. * g++.dg/parse/typedef2.C: Likewise. * g++.dg/parse/typename11.C: Likewise. * g++.dg/template/crash48.C: Adjust dg-error. * g++.dg/template/dependent-name5.C: Only expect error in c++17_down. Add dg-error. * g++.dg/template/error29.C: Only expect error in c++17_down. * g++.dg/template/nested5.C: Add template disambiguator. * g++.dg/template/pr84789.C: Only expect error in c++17_down. * g++.dg/template/static30.C: Add dg-error. * g++.dg/template/typedef6.C: Adjust dg-error. * g++.dg/template/typename3.C: Only expect error in c++17_down. From-SVN: r266710
This commit is contained in:
parent
e770ab191c
commit
96c35892be
33 changed files with 789 additions and 84 deletions
|
@ -1,3 +1,84 @@
|
|||
2018-12-01 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
Implement P0634R3, Down with typename!
|
||||
* parser.c (CP_PARSER_FLAGS_TYPENAME_OPTIONAL): New enumerator.
|
||||
(cp_parser_type_name): Remove declaration.
|
||||
(cp_parser_postfix_expression): Pass CP_PARSER_FLAGS_TYPENAME_OPTIONAL
|
||||
to cp_parser_type_id.
|
||||
(cp_parser_new_type_id): Pass CP_PARSER_FLAGS_TYPENAME_OPTIONAL to
|
||||
cp_parser_type_specifier_seq.
|
||||
(cp_parser_lambda_declarator_opt): Pass
|
||||
CP_PARSER_FLAGS_TYPENAME_OPTIONAL to
|
||||
cp_parser_parameter_declaration_clause.
|
||||
(cp_parser_condition): Pass CP_PARSER_FLAGS_NONE to
|
||||
cp_parser_declarator.
|
||||
(cp_parser_simple_declaration): Pass CP_PARSER_FLAGS_NONE to
|
||||
cp_parser_init_declarator.
|
||||
(cp_parser_conversion_type_id): Pass CP_PARSER_FLAGS_NONE to
|
||||
cp_parser_type_specifier_seq.
|
||||
(cp_parser_default_type_template_argument): Pass
|
||||
CP_PARSER_FLAGS_TYPENAME_OPTIONAL to cp_parser_type_id.
|
||||
(cp_parser_template_parameter): Pass CP_PARSER_FLAGS_TYPENAME_OPTIONAL
|
||||
to cp_parser_parameter_declaration.
|
||||
(cp_parser_explicit_instantiation): Pass CP_PARSER_FLAGS_NONE to
|
||||
cp_parser_declarator.
|
||||
(cp_parser_simple_type_specifier): Adjust call to cp_parser_type_name
|
||||
to relay if we should treat the typename keyword as optional. Maybe
|
||||
call cp_parser_make_typename_type is parsing a template-id and it's
|
||||
not a TYPE_DECL.
|
||||
(cp_parser_type_name): Remove unused function.
|
||||
(cp_parser_enum_specifier): Pass to CP_PARSER_FLAGS_NONE
|
||||
cp_parser_type_specifier_seq.
|
||||
(cp_parser_alias_declaration): Pass CP_PARSER_FLAGS_TYPENAME_OPTIONAL
|
||||
to cp_parser_type_id.
|
||||
(cp_parser_init_declarator): New parameter. Pass it down to
|
||||
cp_parser_declarator.
|
||||
(cp_parser_declarator): New parameter. Pass CP_PARSER_FLAGS_NONE to
|
||||
cp_parser_declarator. Pass the new parameter to
|
||||
cp_parser_direct_declarator.
|
||||
(cp_parser_direct_declarator): New parameter. Pass it to
|
||||
cp_parser_parameter_declaration_clause and cp_parser_declarator.
|
||||
(cp_parser_declarator_id):
|
||||
(cp_parser_type_id_1): New parameter. Pass it to
|
||||
cp_parser_type_specifier_seq. Adjust call to cp_parser_declarator.
|
||||
(cp_parser_type_id): New parameter. Pass it to cp_parser_type_id_1.
|
||||
(cp_parser_template_type_arg): Pass CP_PARSER_FLAGS_NONE to
|
||||
cp_parser_type_id_1.
|
||||
(cp_parser_trailing_type_id): Pass CP_PARSER_FLAGS_TYPENAME_OPTIONAL
|
||||
to cp_parser_type_id_1.
|
||||
(cp_parser_type_specifier_seq): New parameter.
|
||||
(function_being_declared_is_template_p):
|
||||
(cp_parser_parameter_declaration_clause): New parameter. Pass it to
|
||||
cp_parser_parameter_declaration_list.
|
||||
(cp_parser_parameter_declaration_list): New parameter. Pass it to
|
||||
cp_parser_parameter_declaration.
|
||||
(cp_parser_parameter_declaration): New parameter. Pass it to
|
||||
cp_parser_decl_specifier_seq. Pass CP_PARSER_FLAGS_NONE to
|
||||
cp_parser_declarator.
|
||||
(cp_parser_member_declaration): Adjust call to
|
||||
cp_parser_decl_specifier_seq to also include
|
||||
CP_PARSER_FLAGS_TYPENAME_OPTIONAL. Pass
|
||||
CP_PARSER_FLAGS_TYPENAME_OPTIONAL to cp_parser_declarator.
|
||||
(cp_parser_exception_declaration): Pass CP_PARSER_FLAGS_NONE to
|
||||
cp_parser_type_specifier_seq and cp_parser_declarator.
|
||||
(cp_parser_requirement_parameter_list): Pass CP_PARSER_FLAGS_NONE to
|
||||
cp_parser_parameter_declaration_clause.
|
||||
(cp_parser_constructor_declarator_p): Resolve the TYPENAME_TYPE.
|
||||
(cp_parser_single_declaration): Pass CP_PARSER_FLAGS_TYPENAME_OPTIONAL
|
||||
to cp_parser_decl_specifier_seq and cp_parser_init_declarator.
|
||||
(cp_parser_cache_defarg): Pass CP_PARSER_FLAGS_NONE to
|
||||
cp_parser_declarator and cp_parser_parameter_declaration_list.
|
||||
(cp_parser_objc_method_tail_params_opt): Pass CP_PARSER_FLAGS_NONE to
|
||||
cp_parser_parameter_declaration.
|
||||
(cp_parser_objc_class_ivars): Pass CP_PARSER_FLAGS_NONE to
|
||||
cp_parser_declarator.
|
||||
(cp_parser_objc_try_catch_finally_statement): Pass CP_PARSER_FLAGS_NONE
|
||||
to cp_parser_parameter_declaration
|
||||
(cp_parser_objc_struct_declaration): Pass CP_PARSER_FLAGS_NONE to
|
||||
cp_parser_declarator.
|
||||
(cp_parser_omp_for_loop_init): Pass CP_PARSER_FLAGS_NONE to
|
||||
cp_parser_declarator and cp_parser_type_specifier_seq.
|
||||
|
||||
2018-11-30 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* typeck2.c: Include "gcc-rich-location.h".
|
||||
|
|
207
gcc/cp/parser.c
207
gcc/cp/parser.c
|
@ -1791,7 +1791,9 @@ enum
|
|||
constexpr. */
|
||||
CP_PARSER_FLAGS_ONLY_TYPE_OR_CONSTEXPR = 0x8,
|
||||
/* When parsing a decl-specifier-seq, only allow mutable or constexpr. */
|
||||
CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR = 0x10
|
||||
CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR = 0x10,
|
||||
/* When parsing a decl-specifier-seq, allow missing typename. */
|
||||
CP_PARSER_FLAGS_TYPENAME_OPTIONAL = 0x20
|
||||
};
|
||||
|
||||
/* This type is used for parameters and variables which hold
|
||||
|
@ -2156,8 +2158,6 @@ static tree cp_parser_simple_type_specifier
|
|||
(cp_parser *, cp_decl_specifier_seq *, cp_parser_flags);
|
||||
static tree cp_parser_type_name
|
||||
(cp_parser *, bool);
|
||||
static tree cp_parser_type_name
|
||||
(cp_parser *);
|
||||
static tree cp_parser_nonclass_name
|
||||
(cp_parser* parser);
|
||||
static tree cp_parser_elaborated_type_specifier
|
||||
|
@ -2198,12 +2198,14 @@ static tree cp_parser_decomposition_declaration
|
|||
/* Declarators [gram.dcl.decl] */
|
||||
|
||||
static tree cp_parser_init_declarator
|
||||
(cp_parser *, cp_decl_specifier_seq *, vec<deferred_access_check, va_gc> *,
|
||||
bool, bool, int, bool *, tree *, location_t *, tree *);
|
||||
(cp_parser *, cp_parser_flags, cp_decl_specifier_seq *,
|
||||
vec<deferred_access_check, va_gc> *, bool, bool, int, bool *, tree *,
|
||||
location_t *, tree *);
|
||||
static cp_declarator *cp_parser_declarator
|
||||
(cp_parser *, cp_parser_declarator_kind, int *, bool *, bool, bool);
|
||||
(cp_parser *, cp_parser_declarator_kind, cp_parser_flags, int *, bool *,
|
||||
bool, bool);
|
||||
static cp_declarator *cp_parser_direct_declarator
|
||||
(cp_parser *, cp_parser_declarator_kind, int *, bool, bool);
|
||||
(cp_parser *, cp_parser_declarator_kind, cp_parser_flags, int *, bool, bool);
|
||||
static enum tree_code cp_parser_ptr_operator
|
||||
(cp_parser *, tree *, cp_cv_quals *, tree *);
|
||||
static cp_cv_quals cp_parser_cv_qualifier_seq_opt
|
||||
|
@ -2219,20 +2221,20 @@ static tree cp_parser_late_return_type_opt
|
|||
static tree cp_parser_declarator_id
|
||||
(cp_parser *, bool);
|
||||
static tree cp_parser_type_id
|
||||
(cp_parser *, location_t * = NULL);
|
||||
(cp_parser *, cp_parser_flags = CP_PARSER_FLAGS_NONE, location_t * = NULL);
|
||||
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, bool, location_t *);
|
||||
(cp_parser *, cp_parser_flags, bool, bool, location_t *);
|
||||
static void cp_parser_type_specifier_seq
|
||||
(cp_parser *, bool, bool, cp_decl_specifier_seq *);
|
||||
(cp_parser *, cp_parser_flags, bool, bool, cp_decl_specifier_seq *);
|
||||
static tree cp_parser_parameter_declaration_clause
|
||||
(cp_parser *);
|
||||
(cp_parser *, cp_parser_flags);
|
||||
static tree cp_parser_parameter_declaration_list
|
||||
(cp_parser *);
|
||||
(cp_parser *, cp_parser_flags);
|
||||
static cp_parameter_declarator *cp_parser_parameter_declaration
|
||||
(cp_parser *, bool, bool *);
|
||||
(cp_parser *, cp_parser_flags, bool, bool *);
|
||||
static tree cp_parser_default_argument
|
||||
(cp_parser *, bool);
|
||||
static void cp_parser_function_body
|
||||
|
@ -6789,7 +6791,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
|
|||
/* Parse the type to which we are casting. */
|
||||
saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p;
|
||||
parser->in_type_id_in_expr_p = true;
|
||||
type = cp_parser_type_id (parser);
|
||||
type = cp_parser_type_id (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL,
|
||||
NULL);
|
||||
parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
|
||||
/* Look for the closing `>'. */
|
||||
cp_parser_require (parser, CPP_GREATER, RT_GREATER);
|
||||
|
@ -8710,7 +8713,8 @@ cp_parser_new_type_id (cp_parser* parser, tree *nelts)
|
|||
parser->type_definition_forbidden_message
|
||||
= G_("types may not be defined in a new-type-id");
|
||||
/* Parse the type-specifier-seq. */
|
||||
cp_parser_type_specifier_seq (parser, /*is_declaration=*/false,
|
||||
cp_parser_type_specifier_seq (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL,
|
||||
/*is_declaration=*/false,
|
||||
/*is_trailing_return=*/false,
|
||||
&type_specifier_seq);
|
||||
/* Restore the old message. */
|
||||
|
@ -10727,7 +10731,9 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
|
|||
begin_scope (sk_function_parms, /*entity=*/NULL_TREE);
|
||||
|
||||
/* Parse parameters. */
|
||||
param_list = cp_parser_parameter_declaration_clause (parser);
|
||||
param_list
|
||||
= cp_parser_parameter_declaration_clause
|
||||
(parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL);
|
||||
|
||||
/* Default arguments shall not be specified in the
|
||||
parameter-declaration-clause of a lambda-declarator. */
|
||||
|
@ -11913,6 +11919,7 @@ cp_parser_condition (cp_parser* parser)
|
|||
|
||||
/* Parse the declarator. */
|
||||
declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
|
||||
CP_PARSER_FLAGS_NONE,
|
||||
/*ctor_dtor_or_conv_p=*/NULL,
|
||||
/*parenthesized_p=*/NULL,
|
||||
/*member_p=*/false,
|
||||
|
@ -13387,7 +13394,9 @@ cp_parser_simple_declaration (cp_parser* parser,
|
|||
saw_declarator = true;
|
||||
|
||||
/* Parse the init-declarator. */
|
||||
decl = cp_parser_init_declarator (parser, &decl_specifiers,
|
||||
decl = cp_parser_init_declarator (parser,
|
||||
CP_PARSER_FLAGS_NONE,
|
||||
&decl_specifiers,
|
||||
/*checks=*/NULL,
|
||||
function_definition_allowed_p,
|
||||
/*member_p=*/false,
|
||||
|
@ -14653,7 +14662,8 @@ cp_parser_conversion_type_id (cp_parser* parser)
|
|||
= G_("types may not be defined in a conversion-type-id");
|
||||
|
||||
/* Parse the type-specifiers. */
|
||||
cp_parser_type_specifier_seq (parser, /*is_declaration=*/false,
|
||||
cp_parser_type_specifier_seq (parser, CP_PARSER_FLAGS_NONE,
|
||||
/*is_declaration=*/false,
|
||||
/*is_trailing_return=*/false,
|
||||
&type_specifiers);
|
||||
|
||||
|
@ -15742,7 +15752,9 @@ cp_parser_default_type_template_argument (cp_parser *parser)
|
|||
|
||||
/* Parse the default-argument. */
|
||||
push_deferring_access_checks (dk_no_deferred);
|
||||
tree default_argument = cp_parser_type_id (parser);
|
||||
tree default_argument = cp_parser_type_id (parser,
|
||||
CP_PARSER_FLAGS_TYPENAME_OPTIONAL,
|
||||
NULL);
|
||||
pop_deferring_access_checks ();
|
||||
|
||||
if (flag_concepts && type_uses_auto (default_argument))
|
||||
|
@ -15869,7 +15881,9 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type,
|
|||
of the template parameter-list rather than a greater-than
|
||||
operator. */
|
||||
parameter_declarator
|
||||
= cp_parser_parameter_declaration (parser, /*template_parm_p=*/true,
|
||||
= cp_parser_parameter_declaration (parser,
|
||||
CP_PARSER_FLAGS_TYPENAME_OPTIONAL,
|
||||
/*template_parm_p=*/true,
|
||||
/*parenthesized_p=*/NULL);
|
||||
|
||||
if (!parameter_declarator)
|
||||
|
@ -17016,6 +17030,7 @@ cp_parser_explicit_instantiation (cp_parser* parser)
|
|||
/* Parse the declarator. */
|
||||
declarator
|
||||
= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
|
||||
CP_PARSER_FLAGS_NONE,
|
||||
/*ctor_dtor_or_conv_p=*/NULL,
|
||||
/*parenthesized_p=*/NULL,
|
||||
/*member_p=*/false,
|
||||
|
@ -17616,6 +17631,8 @@ cp_parser_simple_type_specifier (cp_parser* parser,
|
|||
{
|
||||
bool qualified_p;
|
||||
bool global_p;
|
||||
const bool typename_p = (cxx_dialect >= cxx2a
|
||||
&& (flags & CP_PARSER_FLAGS_TYPENAME_OPTIONAL));
|
||||
|
||||
/* Don't gobble tokens or issue error messages if this is an
|
||||
optional type-specifier. */
|
||||
|
@ -17652,13 +17669,21 @@ cp_parser_simple_type_specifier (cp_parser* parser,
|
|||
luck. */
|
||||
if (TREE_CODE (type) != TYPE_DECL)
|
||||
{
|
||||
cp_parser_error (parser, "expected template-id for type");
|
||||
type = NULL_TREE;
|
||||
/* ...unless we pretend we have seen 'typename'. */
|
||||
if (typename_p)
|
||||
type = cp_parser_make_typename_type (parser, type,
|
||||
token->location);
|
||||
else
|
||||
{
|
||||
cp_parser_error (parser, "expected template-id for type");
|
||||
type = NULL_TREE;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Otherwise, look for a type-name. */
|
||||
else
|
||||
type = cp_parser_type_name (parser);
|
||||
type = cp_parser_type_name (parser, (qualified_p && typename_p));
|
||||
|
||||
/* Keep track of all name-lookups performed in class scopes. */
|
||||
if (type
|
||||
&& !global_p
|
||||
|
@ -17783,13 +17808,6 @@ cp_parser_simple_type_specifier (cp_parser* parser,
|
|||
|
||||
Returns a TYPE_DECL for the type. */
|
||||
|
||||
static tree
|
||||
cp_parser_type_name (cp_parser* parser)
|
||||
{
|
||||
return cp_parser_type_name (parser, /*typename_keyword_p=*/false);
|
||||
}
|
||||
|
||||
/* See above. */
|
||||
static tree
|
||||
cp_parser_type_name (cp_parser* parser, bool typename_keyword_p)
|
||||
{
|
||||
|
@ -18577,7 +18595,8 @@ cp_parser_enum_specifier (cp_parser* parser)
|
|||
cp_lexer_consume_token (parser->lexer);
|
||||
|
||||
/* Parse the type-specifier-seq. */
|
||||
cp_parser_type_specifier_seq (parser, /*is_declaration=*/false,
|
||||
cp_parser_type_specifier_seq (parser, CP_PARSER_FLAGS_NONE,
|
||||
/*is_declaration=*/false,
|
||||
/*is_trailing_return=*/false,
|
||||
&type_specifiers);
|
||||
|
||||
|
@ -19434,7 +19453,8 @@ cp_parser_alias_declaration (cp_parser* parser)
|
|||
G_("types may not be defined in alias template declarations");
|
||||
}
|
||||
|
||||
type = cp_parser_type_id (parser, &type_location);
|
||||
type = cp_parser_type_id (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL,
|
||||
&type_location);
|
||||
|
||||
/* Restore the error message if need be. */
|
||||
if (parser->num_template_parameter_lists)
|
||||
|
@ -19814,6 +19834,8 @@ strip_declarator_types (tree type, cp_declarator *declarator)
|
|||
function-definition:
|
||||
decl-specifier-seq [opt] declarator function-transaction-block
|
||||
|
||||
The parser flags FLAGS is used to control type-specifier parsing.
|
||||
|
||||
The DECL_SPECIFIERS apply to this declarator. Returns a
|
||||
representation of the entity declared. If MEMBER_P is TRUE, then
|
||||
this declarator appears in a class scope. The new DECL created by
|
||||
|
@ -19845,6 +19867,7 @@ strip_declarator_types (tree type, cp_declarator *declarator)
|
|||
|
||||
static tree
|
||||
cp_parser_init_declarator (cp_parser* parser,
|
||||
cp_parser_flags flags,
|
||||
cp_decl_specifier_seq *decl_specifiers,
|
||||
vec<deferred_access_check, va_gc> *checks,
|
||||
bool function_definition_allowed_p,
|
||||
|
@ -19901,7 +19924,7 @@ cp_parser_init_declarator (cp_parser* parser,
|
|||
/* Parse the declarator. */
|
||||
declarator
|
||||
= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
|
||||
&ctor_dtor_or_conv_p,
|
||||
flags, &ctor_dtor_or_conv_p,
|
||||
/*parenthesized_p=*/NULL,
|
||||
member_p, friend_p);
|
||||
/* Gather up the deferred checks. */
|
||||
|
@ -20300,6 +20323,8 @@ cp_parser_init_declarator (cp_parser* parser,
|
|||
attributes [opt] ptr-operator abstract-declarator [opt]
|
||||
attributes [opt] direct-abstract-declarator
|
||||
|
||||
The parser flags FLAGS is used to control type-specifier parsing.
|
||||
|
||||
If CTOR_DTOR_OR_CONV_P is not NULL, *CTOR_DTOR_OR_CONV_P is used to
|
||||
detect constructors, destructors, deduction guides, or conversion operators.
|
||||
It is set to -1 if the declarator is a name, and +1 if it is a
|
||||
|
@ -20324,6 +20349,7 @@ cp_parser_init_declarator (cp_parser* parser,
|
|||
static cp_declarator *
|
||||
cp_parser_declarator (cp_parser* parser,
|
||||
cp_parser_declarator_kind dcl_kind,
|
||||
cp_parser_flags flags,
|
||||
int* ctor_dtor_or_conv_p,
|
||||
bool* parenthesized_p,
|
||||
bool member_p, bool friend_p)
|
||||
|
@ -20364,6 +20390,7 @@ cp_parser_declarator (cp_parser* parser,
|
|||
|
||||
/* Parse the dependent declarator. */
|
||||
declarator = cp_parser_declarator (parser, dcl_kind,
|
||||
CP_PARSER_FLAGS_NONE,
|
||||
/*ctor_dtor_or_conv_p=*/NULL,
|
||||
/*parenthesized_p=*/NULL,
|
||||
/*member_p=*/false,
|
||||
|
@ -20385,7 +20412,7 @@ cp_parser_declarator (cp_parser* parser,
|
|||
*parenthesized_p = cp_lexer_next_token_is (parser->lexer,
|
||||
CPP_OPEN_PAREN);
|
||||
declarator = cp_parser_direct_declarator (parser, dcl_kind,
|
||||
ctor_dtor_or_conv_p,
|
||||
flags, ctor_dtor_or_conv_p,
|
||||
member_p, friend_p);
|
||||
}
|
||||
|
||||
|
@ -20420,12 +20447,15 @@ cp_parser_declarator (cp_parser* parser,
|
|||
we are parsing a direct-declarator. It is
|
||||
CP_PARSER_DECLARATOR_EITHER, if we can accept either - in the case
|
||||
of ambiguity we prefer an abstract declarator, as per
|
||||
[dcl.ambig.res]. CTOR_DTOR_OR_CONV_P, MEMBER_P, and FRIEND_P are
|
||||
[dcl.ambig.res].
|
||||
The parser flags FLAGS is used to control type-specifier parsing.
|
||||
CTOR_DTOR_OR_CONV_P, MEMBER_P, and FRIEND_P are
|
||||
as for cp_parser_declarator. */
|
||||
|
||||
static cp_declarator *
|
||||
cp_parser_direct_declarator (cp_parser* parser,
|
||||
cp_parser_declarator_kind dcl_kind,
|
||||
cp_parser_flags flags,
|
||||
int* ctor_dtor_or_conv_p,
|
||||
bool member_p, bool friend_p)
|
||||
{
|
||||
|
@ -20512,7 +20542,8 @@ cp_parser_direct_declarator (cp_parser* parser,
|
|||
begin_scope (sk_function_parms, NULL_TREE);
|
||||
|
||||
/* Parse the parameter-declaration-clause. */
|
||||
params = cp_parser_parameter_declaration_clause (parser);
|
||||
params
|
||||
= cp_parser_parameter_declaration_clause (parser, flags);
|
||||
|
||||
/* Consume the `)'. */
|
||||
parens.require_close (parser);
|
||||
|
@ -20603,7 +20634,8 @@ cp_parser_direct_declarator (cp_parser* parser,
|
|||
saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p;
|
||||
parser->in_type_id_in_expr_p = true;
|
||||
declarator
|
||||
= cp_parser_declarator (parser, dcl_kind, ctor_dtor_or_conv_p,
|
||||
= cp_parser_declarator (parser, dcl_kind, flags,
|
||||
ctor_dtor_or_conv_p,
|
||||
/*parenthesized_p=*/NULL,
|
||||
member_p, friend_p);
|
||||
parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
|
||||
|
@ -21453,17 +21485,26 @@ cp_parser_declarator_id (cp_parser* parser, bool optional_p)
|
|||
type-id:
|
||||
type-specifier-seq abstract-declarator [opt]
|
||||
|
||||
The parser flags FLAGS is used to control type-specifier parsing.
|
||||
|
||||
If IS_TEMPLATE_ARG is true, we are parsing a template argument.
|
||||
|
||||
If IS_TRAILING_RETURN is true, we are in a trailing-return-type,
|
||||
i.e. we've just seen "->".
|
||||
|
||||
Returns the TYPE specified. */
|
||||
|
||||
static tree
|
||||
cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg,
|
||||
bool is_trailing_return, location_t * type_location)
|
||||
cp_parser_type_id_1 (cp_parser *parser, cp_parser_flags flags,
|
||||
bool is_template_arg, bool is_trailing_return,
|
||||
location_t *type_location)
|
||||
{
|
||||
cp_decl_specifier_seq type_specifier_seq;
|
||||
cp_declarator *abstract_declarator;
|
||||
|
||||
/* Parse the type-specifier-seq. */
|
||||
cp_parser_type_specifier_seq (parser, /*is_declaration=*/false,
|
||||
cp_parser_type_specifier_seq (parser, flags,
|
||||
/*is_declaration=*/false,
|
||||
is_trailing_return,
|
||||
&type_specifier_seq);
|
||||
if (type_location)
|
||||
|
@ -21486,7 +21527,8 @@ cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg,
|
|||
cp_parser_parse_tentatively (parser);
|
||||
/* Look for the declarator. */
|
||||
abstract_declarator
|
||||
= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_ABSTRACT, NULL,
|
||||
= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_ABSTRACT,
|
||||
CP_PARSER_FLAGS_NONE, NULL,
|
||||
/*parenthesized_p=*/NULL,
|
||||
/*member_p=*/false,
|
||||
/*friend_p=*/false);
|
||||
|
@ -21533,12 +21575,17 @@ cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg,
|
|||
is_template_arg);
|
||||
}
|
||||
|
||||
/* Wrapper for cp_parser_type_id_1. */
|
||||
|
||||
static tree
|
||||
cp_parser_type_id (cp_parser *parser, location_t * type_location)
|
||||
cp_parser_type_id (cp_parser *parser, cp_parser_flags flags,
|
||||
location_t *type_location)
|
||||
{
|
||||
return cp_parser_type_id_1 (parser, false, false, type_location);
|
||||
return cp_parser_type_id_1 (parser, flags, false, false, type_location);
|
||||
}
|
||||
|
||||
/* Wrapper for cp_parser_type_id_1. */
|
||||
|
||||
static tree
|
||||
cp_parser_template_type_arg (cp_parser *parser)
|
||||
{
|
||||
|
@ -21546,7 +21593,7 @@ cp_parser_template_type_arg (cp_parser *parser)
|
|||
const char *saved_message = parser->type_definition_forbidden_message;
|
||||
parser->type_definition_forbidden_message
|
||||
= G_("types may not be defined in template arguments");
|
||||
r = cp_parser_type_id_1 (parser, true, false, NULL);
|
||||
r = cp_parser_type_id_1 (parser, CP_PARSER_FLAGS_NONE, true, false, NULL);
|
||||
parser->type_definition_forbidden_message = saved_message;
|
||||
if (cxx_dialect >= cxx14 && !flag_concepts && type_uses_auto (r))
|
||||
{
|
||||
|
@ -21556,10 +21603,13 @@ cp_parser_template_type_arg (cp_parser *parser)
|
|||
return r;
|
||||
}
|
||||
|
||||
/* Wrapper for cp_parser_type_id_1. */
|
||||
|
||||
static tree
|
||||
cp_parser_trailing_type_id (cp_parser *parser)
|
||||
{
|
||||
return cp_parser_type_id_1 (parser, false, true, NULL);
|
||||
return cp_parser_type_id_1 (parser, CP_PARSER_FLAGS_TYPENAME_OPTIONAL,
|
||||
false, true, NULL);
|
||||
}
|
||||
|
||||
/* Parse a type-specifier-seq.
|
||||
|
@ -21572,6 +21622,8 @@ cp_parser_trailing_type_id (cp_parser *parser)
|
|||
type-specifier-seq:
|
||||
attributes type-specifier-seq [opt]
|
||||
|
||||
The parser flags FLAGS is used to control type-specifier parsing.
|
||||
|
||||
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.
|
||||
|
||||
|
@ -21582,17 +21634,18 @@ cp_parser_trailing_type_id (cp_parser *parser)
|
|||
|
||||
static void
|
||||
cp_parser_type_specifier_seq (cp_parser* parser,
|
||||
cp_parser_flags flags,
|
||||
bool is_declaration,
|
||||
bool is_trailing_return,
|
||||
cp_decl_specifier_seq *type_specifier_seq)
|
||||
{
|
||||
bool seen_type_specifier = false;
|
||||
cp_parser_flags flags = CP_PARSER_FLAGS_OPTIONAL;
|
||||
cp_token *start_token = NULL;
|
||||
|
||||
/* Clear the TYPE_SPECIFIER_SEQ. */
|
||||
clear_decl_specs (type_specifier_seq);
|
||||
|
||||
flags |= CP_PARSER_FLAGS_OPTIONAL;
|
||||
/* In the context of a trailing return type, enum E { } is an
|
||||
elaborated-type-specifier followed by a function-body, not an
|
||||
enum-specifier. */
|
||||
|
@ -21698,12 +21751,15 @@ function_being_declared_is_template_p (cp_parser* parser)
|
|||
parameter-declaration-list [opt] ... [opt]
|
||||
parameter-declaration-list , ...
|
||||
|
||||
The parser flags FLAGS is used to control type-specifier parsing.
|
||||
|
||||
Returns a representation for the parameter declarations. A return
|
||||
value of NULL indicates a parameter-declaration-clause consisting
|
||||
only of an ellipsis. */
|
||||
|
||||
static tree
|
||||
cp_parser_parameter_declaration_clause (cp_parser* parser)
|
||||
cp_parser_parameter_declaration_clause (cp_parser* parser,
|
||||
cp_parser_flags flags)
|
||||
{
|
||||
tree parameters;
|
||||
cp_token *token;
|
||||
|
@ -21746,7 +21802,7 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
|
|||
}
|
||||
|
||||
/* Parse the parameter-declaration-list. */
|
||||
parameters = cp_parser_parameter_declaration_list (parser);
|
||||
parameters = cp_parser_parameter_declaration_list (parser, flags);
|
||||
/* If a parse error occurred while parsing the
|
||||
parameter-declaration-list, then the entire
|
||||
parameter-declaration-clause is erroneous. */
|
||||
|
@ -21789,12 +21845,14 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
|
|||
parameter-declaration
|
||||
parameter-declaration-list , parameter-declaration
|
||||
|
||||
The parser flags FLAGS is used to control type-specifier parsing.
|
||||
|
||||
Returns a representation of the parameter-declaration-list, as for
|
||||
cp_parser_parameter_declaration_clause. However, the
|
||||
`void_list_node' is never appended to the list. */
|
||||
|
||||
static tree
|
||||
cp_parser_parameter_declaration_list (cp_parser* parser)
|
||||
cp_parser_parameter_declaration_list (cp_parser* parser, cp_parser_flags flags)
|
||||
{
|
||||
tree parameters = NULL_TREE;
|
||||
tree *tail = ¶meters;
|
||||
|
@ -21817,7 +21875,7 @@ cp_parser_parameter_declaration_list (cp_parser* parser)
|
|||
|
||||
/* Parse the parameter. */
|
||||
parameter
|
||||
= cp_parser_parameter_declaration (parser,
|
||||
= cp_parser_parameter_declaration (parser, flags,
|
||||
/*template_parm_p=*/false,
|
||||
&parenthesized_p);
|
||||
|
||||
|
@ -21949,6 +22007,8 @@ cp_parser_parameter_declaration_list (cp_parser* parser)
|
|||
decl-specifier-seq ... [opt] abstract-declarator [opt]
|
||||
decl-specifier-seq abstract-declarator [opt] = assignment-expression
|
||||
|
||||
The parser flags FLAGS is used to control type-specifier parsing.
|
||||
|
||||
If TEMPLATE_PARM_P is TRUE, then this parameter-declaration
|
||||
declares a template parameter. (In that case, a non-nested `>'
|
||||
token encountered during the parsing of the assignment-expression
|
||||
|
@ -21960,6 +22020,7 @@ cp_parser_parameter_declaration_list (cp_parser* parser)
|
|||
|
||||
static cp_parameter_declarator *
|
||||
cp_parser_parameter_declaration (cp_parser *parser,
|
||||
cp_parser_flags flags,
|
||||
bool template_parm_p,
|
||||
bool *parenthesized_p)
|
||||
{
|
||||
|
@ -21992,7 +22053,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
|
|||
/* Parse the declaration-specifiers. */
|
||||
cp_token *decl_spec_token_start = cp_lexer_peek_token (parser->lexer);
|
||||
cp_parser_decl_specifier_seq (parser,
|
||||
CP_PARSER_FLAGS_NONE,
|
||||
flags,
|
||||
&decl_specifiers,
|
||||
&declares_class_or_enum);
|
||||
|
||||
|
@ -22051,6 +22112,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
|
|||
declarator_token_start = token;
|
||||
declarator = cp_parser_declarator (parser,
|
||||
CP_PARSER_DECLARATOR_EITHER,
|
||||
CP_PARSER_FLAGS_NONE,
|
||||
/*ctor_dtor_or_conv_p=*/NULL,
|
||||
parenthesized_p,
|
||||
/*member_p=*/false,
|
||||
|
@ -24024,7 +24086,8 @@ cp_parser_member_declaration (cp_parser* parser)
|
|||
/* Parse the decl-specifier-seq. */
|
||||
decl_spec_token_start = cp_lexer_peek_token (parser->lexer);
|
||||
cp_parser_decl_specifier_seq (parser,
|
||||
CP_PARSER_FLAGS_OPTIONAL,
|
||||
(CP_PARSER_FLAGS_OPTIONAL
|
||||
| CP_PARSER_FLAGS_TYPENAME_OPTIONAL),
|
||||
&decl_specifiers,
|
||||
&declares_class_or_enum);
|
||||
/* Check for an invalid type-name. */
|
||||
|
@ -24261,6 +24324,7 @@ cp_parser_member_declaration (cp_parser* parser)
|
|||
/* Parse the declarator. */
|
||||
declarator
|
||||
= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
|
||||
CP_PARSER_FLAGS_TYPENAME_OPTIONAL,
|
||||
&ctor_dtor_or_conv_p,
|
||||
/*parenthesized_p=*/NULL,
|
||||
/*member_p=*/true,
|
||||
|
@ -25132,7 +25196,8 @@ cp_parser_exception_declaration (cp_parser* parser)
|
|||
= G_("types may not be defined in exception-declarations");
|
||||
|
||||
/* Parse the type-specifier-seq. */
|
||||
cp_parser_type_specifier_seq (parser, /*is_declaration=*/true,
|
||||
cp_parser_type_specifier_seq (parser, CP_PARSER_FLAGS_NONE,
|
||||
/*is_declaration=*/true,
|
||||
/*is_trailing_return=*/false,
|
||||
&type_specifiers);
|
||||
/* If it's a `)', then there is no declarator. */
|
||||
|
@ -25140,6 +25205,7 @@ cp_parser_exception_declaration (cp_parser* parser)
|
|||
declarator = NULL;
|
||||
else
|
||||
declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_EITHER,
|
||||
CP_PARSER_FLAGS_NONE,
|
||||
/*ctor_dtor_or_conv_p=*/NULL,
|
||||
/*parenthesized_p=*/NULL,
|
||||
/*member_p=*/false,
|
||||
|
@ -26295,7 +26361,8 @@ cp_parser_requirement_parameter_list (cp_parser *parser)
|
|||
if (!parens.require_open (parser))
|
||||
return error_mark_node;
|
||||
|
||||
tree parms = cp_parser_parameter_declaration_clause (parser);
|
||||
tree parms
|
||||
= cp_parser_parameter_declaration_clause (parser, CP_PARSER_FLAGS_NONE);
|
||||
|
||||
if (!parens.require_close (parser))
|
||||
return error_mark_node;
|
||||
|
@ -27049,6 +27116,16 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
|
|||
/*type_p=*/false,
|
||||
/*is_declaration=*/false));
|
||||
|
||||
/* Resolve the TYPENAME_TYPE, because the call above didn't do it. */
|
||||
if (nested_name_specifier
|
||||
&& TREE_CODE (nested_name_specifier) == TYPENAME_TYPE)
|
||||
{
|
||||
tree s = resolve_typename_type (nested_name_specifier,
|
||||
/*only_current_p=*/false);
|
||||
if (TREE_CODE (s) != TYPENAME_TYPE)
|
||||
nested_name_specifier = s;
|
||||
}
|
||||
|
||||
outside_class_specifier_p = (!at_class_scope_p ()
|
||||
|| !TYPE_BEING_DEFINED (current_class_type)
|
||||
|| friend_p);
|
||||
|
@ -27727,7 +27804,8 @@ cp_parser_single_declaration (cp_parser* parser,
|
|||
alternative. */
|
||||
decl_spec_token_start = cp_lexer_peek_token (parser->lexer);
|
||||
cp_parser_decl_specifier_seq (parser,
|
||||
CP_PARSER_FLAGS_OPTIONAL,
|
||||
(CP_PARSER_FLAGS_OPTIONAL
|
||||
| CP_PARSER_FLAGS_TYPENAME_OPTIONAL),
|
||||
&decl_specifiers,
|
||||
&declares_class_or_enum);
|
||||
if (friend_p)
|
||||
|
@ -27817,6 +27895,7 @@ cp_parser_single_declaration (cp_parser* parser,
|
|||
|| decl_specifiers.type != error_mark_node))
|
||||
{
|
||||
decl = cp_parser_init_declarator (parser,
|
||||
CP_PARSER_FLAGS_TYPENAME_OPTIONAL,
|
||||
&decl_specifiers,
|
||||
checks,
|
||||
/*function_definition_allowed_p=*/true,
|
||||
|
@ -29451,6 +29530,7 @@ cp_parser_cache_defarg (cp_parser *parser, bool nsdmi)
|
|||
int ctor_dtor_or_conv_p;
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
|
||||
CP_PARSER_FLAGS_NONE,
|
||||
&ctor_dtor_or_conv_p,
|
||||
/*parenthesized_p=*/NULL,
|
||||
/*member_p=*/true,
|
||||
|
@ -29470,8 +29550,9 @@ cp_parser_cache_defarg (cp_parser *parser, bool nsdmi)
|
|||
{
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
begin_scope (sk_function_parms, NULL_TREE);
|
||||
if (cp_parser_parameter_declaration_list (parser)
|
||||
== error_mark_node)
|
||||
tree t = cp_parser_parameter_declaration_list
|
||||
(parser, CP_PARSER_FLAGS_NONE);
|
||||
if (t == error_mark_node)
|
||||
error = true;
|
||||
pop_bindings_and_leave_scope ();
|
||||
}
|
||||
|
@ -30486,7 +30567,8 @@ cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp,
|
|||
}
|
||||
|
||||
/* TODO: parse attributes for tail parameters. */
|
||||
parmdecl = cp_parser_parameter_declaration (parser, false, NULL);
|
||||
parmdecl = cp_parser_parameter_declaration (parser, CP_PARSER_FLAGS_NONE,
|
||||
false, NULL);
|
||||
parm = grokdeclarator (parmdecl->declarator,
|
||||
&parmdecl->decl_specifiers,
|
||||
PARM, /*initialized=*/0,
|
||||
|
@ -30815,6 +30897,7 @@ cp_parser_objc_class_ivars (cp_parser* parser)
|
|||
/* Parse the declarator. */
|
||||
declarator
|
||||
= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
|
||||
CP_PARSER_FLAGS_NONE,
|
||||
&ctor_dtor_or_conv_p,
|
||||
/*parenthesized_p=*/NULL,
|
||||
/*member_p=*/false,
|
||||
|
@ -31168,7 +31251,8 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser)
|
|||
{
|
||||
/* We have "@catch (NSException *exception)" or something
|
||||
like that. Parse the parameter declaration. */
|
||||
parm = cp_parser_parameter_declaration (parser, false, NULL);
|
||||
parm = cp_parser_parameter_declaration (parser, CP_PARSER_FLAGS_NONE,
|
||||
false, NULL);
|
||||
if (parm == NULL)
|
||||
parameter_declaration = error_mark_node;
|
||||
else
|
||||
|
@ -31374,6 +31458,7 @@ cp_parser_objc_struct_declaration (cp_parser *parser)
|
|||
|
||||
/* Parse the declarator. */
|
||||
declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
|
||||
CP_PARSER_FLAGS_NONE,
|
||||
NULL, NULL, false, false);
|
||||
|
||||
/* Look for attributes that apply to the ivar. */
|
||||
|
@ -35985,7 +36070,8 @@ cp_parser_omp_for_loop_init (cp_parser *parser,
|
|||
cp_parser_condition, from whence the bulk of this is copied. */
|
||||
|
||||
cp_parser_parse_tentatively (parser);
|
||||
cp_parser_type_specifier_seq (parser, /*is_declaration=*/true,
|
||||
cp_parser_type_specifier_seq (parser, CP_PARSER_FLAGS_NONE,
|
||||
/*is_declaration=*/true,
|
||||
/*is_trailing_return=*/false,
|
||||
&type_specifiers);
|
||||
if (cp_parser_parse_definitely (parser))
|
||||
|
@ -35997,6 +36083,7 @@ cp_parser_omp_for_loop_init (cp_parser *parser,
|
|||
|
||||
declarator = cp_parser_declarator (parser,
|
||||
CP_PARSER_DECLARATOR_NAMED,
|
||||
CP_PARSER_FLAGS_NONE,
|
||||
/*ctor_dtor_or_conv_p=*/NULL,
|
||||
/*parenthesized_p=*/NULL,
|
||||
/*member_p=*/false,
|
||||
|
|
|
@ -1,3 +1,39 @@
|
|||
2018-12-01 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
Implement P0634R3, Down with typename!
|
||||
* g++.dg/cpp0x/alias-decl-43.C: Adjust dg-error.
|
||||
* g++.dg/cpp0x/decltype67.C: Only expect error in c++17_down.
|
||||
* g++.dg/cpp1z/typename1.C: New test.
|
||||
* g++.dg/cpp2a/typename1.C: New test.
|
||||
* g++.dg/cpp2a/typename10.C: New test.
|
||||
* g++.dg/cpp2a/typename11.C: New test.
|
||||
* g++.dg/cpp2a/typename2.C: New test.
|
||||
* g++.dg/cpp2a/typename3.C: New test.
|
||||
* g++.dg/cpp2a/typename4.C: New test.
|
||||
* g++.dg/cpp2a/typename5.C: New test.
|
||||
* g++.dg/cpp2a/typename6.C: New test.
|
||||
* g++.dg/cpp2a/typename7.C: New test.
|
||||
* g++.dg/cpp2a/typename8.C: New test.
|
||||
* g++.dg/cpp2a/typename9.C: New test.
|
||||
* g++.dg/diagnostic/missing-typename.C: Only run the test in
|
||||
c++17_down.
|
||||
* g++.dg/other/crash-9.C: Add template disambiguator.
|
||||
* g++.dg/other/nontype-1.C: Only expect error in c++17_down.
|
||||
* g++.dg/parse/crash13.C: Likewise.
|
||||
* g++.dg/parse/error36.C: Likewise.
|
||||
* g++.dg/parse/no-typename1.C: Likewise.
|
||||
* g++.dg/parse/typedef2.C: Likewise.
|
||||
* g++.dg/parse/typename11.C: Likewise.
|
||||
* g++.dg/template/crash48.C: Adjust dg-error.
|
||||
* g++.dg/template/dependent-name5.C: Only expect error in c++17_down.
|
||||
Add dg-error.
|
||||
* g++.dg/template/error29.C: Only expect error in c++17_down.
|
||||
* g++.dg/template/nested5.C: Add template disambiguator.
|
||||
* g++.dg/template/pr84789.C: Only expect error in c++17_down.
|
||||
* g++.dg/template/static30.C: Add dg-error.
|
||||
* g++.dg/template/typedef6.C: Adjust dg-error.
|
||||
* g++.dg/template/typename3.C: Only expect error in c++17_down.
|
||||
|
||||
2018-12-01 Jeff Law <law@redhat.com>
|
||||
|
||||
* gcc.dg/predict-22.c: Update expected output.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// PR c++/59120
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
template<typename T> using X = int T::T*; // { dg-error "expected" }
|
||||
template<typename T> using X = int T::T*; // { dg-error "expected|two or more" }
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
|
||||
template<typename T> struct A
|
||||
{
|
||||
void foo(decltype(T())::Y); // { dg-error {decltype\(T\(\)\)::Y} }
|
||||
void foo(decltype(T())::Y); // { dg-error "decltype\\(T\\(\\)\\)::Y" "" { target c++17_down } }
|
||||
};
|
||||
|
|
117
gcc/testsuite/g++.dg/cpp1z/typename1.C
Normal file
117
gcc/testsuite/g++.dg/cpp1z/typename1.C
Normal file
|
@ -0,0 +1,117 @@
|
|||
// P0634R3
|
||||
// { dg-do compile { target c++17_only } }
|
||||
|
||||
// (5.2.1) simple-declaration or a function-definition in namespace scope
|
||||
|
||||
template<typename T>
|
||||
T::X fn1 (int); // { dg-error "need .typename." }
|
||||
|
||||
template<typename T>
|
||||
T::X fn1 (int) // { dg-error "need .typename." }
|
||||
{
|
||||
return 42;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T::X v1; // { dg-error "need .typename." }
|
||||
|
||||
namespace N {
|
||||
template<typename T>
|
||||
T::X v2; // { dg-error "need .typename." }
|
||||
}
|
||||
|
||||
// (5.2.2) member-declaration
|
||||
|
||||
template<typename T>
|
||||
struct S {
|
||||
[[noreturn]] T::X fn2 (); // { dg-error "need .typename." }
|
||||
T::X fn3 (); // { dg-error "need .typename." }
|
||||
T::X fn4 () { return 5; } // { dg-error "need .typename." }
|
||||
T::X fn5 () final; // { dg-error "need .typename." }
|
||||
T::X fn6 () = 0; // { dg-error "need .typename." }
|
||||
T::X fn8 () override; // { dg-error "need .typename." }
|
||||
T::X v3; // { dg-error "need .typename." }
|
||||
T::X *v4; // { dg-error "need .typename." }
|
||||
T::X v5[5]; // { dg-error "need .typename." }
|
||||
T::X v6 = 0; // { dg-error "need .typename." }
|
||||
T::X v7{0}; // { dg-error "need .typename.|;" }
|
||||
T::X v8 : 16; // { dg-error "need .typename." }
|
||||
static constexpr T::X v9 = 0; // { dg-error "need .typename." }
|
||||
typedef T::X T2; // { dg-error "need .typename." }
|
||||
friend T::X fn7<int> (); // { dg-error "need .typename." }
|
||||
static inline T::X v10; // { dg-error "need .typename." }
|
||||
};
|
||||
|
||||
// (5.2.3) parameter-declaration in a member-declaration,
|
||||
// unless that parameter-declaration appears in a default argument
|
||||
|
||||
template<typename T>
|
||||
struct S2 {
|
||||
friend int fn1<T::X> (); // { dg-error "" }
|
||||
int fn2 (T::X p); // { dg-error "not a type" }
|
||||
int fn5 (int = T::X);
|
||||
};
|
||||
|
||||
// (5.2.4) parameter-declaration in a declarator of a function or function
|
||||
// template declaration whose declarator-id is qualified,
|
||||
// unless that parameter-declaration appears in a default argument
|
||||
template<typename T>
|
||||
int fn3 (T::X);
|
||||
|
||||
template<typename T>
|
||||
int fn4 (T::X p) { return p; } // { dg-error "" }
|
||||
|
||||
// (5.2.6) parameter-declaration of a (non-type) template-parameter
|
||||
|
||||
template<typename T, T::X N> // { dg-error "not a type" }
|
||||
struct S3 { };
|
||||
|
||||
// default argument of a type-parameter of a template
|
||||
template<typename T, typename U = T::X> // { dg-error "need .typename." }
|
||||
struct S4 { };
|
||||
|
||||
// type-id of a static_cast, const_cast, reinterpret_cast, or dynamic_cast
|
||||
template<typename T>
|
||||
struct S5 {
|
||||
void fn6 (T::X p) // { dg-error "not a type" }
|
||||
{
|
||||
int i = static_cast<T::Y>(p); // { dg-error "need .typename." }
|
||||
i = dynamic_cast<T::Y>(p); // { dg-error "need .typename." }
|
||||
i = reinterpret_cast<T::Y>(p); // { dg-error "need .typename." }
|
||||
i = const_cast<T::Y>(p); // { dg-error "need .typename." }
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
void fn7 (T::X p) // { dg-error "" }
|
||||
{
|
||||
int i = static_cast<T::Y>(p);
|
||||
i = dynamic_cast<T::Y>(p);
|
||||
i = reinterpret_cast<T::Y>(p);
|
||||
i = const_cast<T::Y>(p);
|
||||
}
|
||||
|
||||
// new-type-id
|
||||
template<typename T>
|
||||
void
|
||||
fn8 ()
|
||||
{
|
||||
new T::X[10]; // { dg-error "need .typename." }
|
||||
}
|
||||
|
||||
// defining-type-id
|
||||
|
||||
template<typename T>
|
||||
struct W { typedef int M; };
|
||||
|
||||
template<typename T>
|
||||
struct S6 {
|
||||
using TT = T::X; // { dg-error "need .typename." }
|
||||
using TT2 = W<T>::M; // { dg-error "need .typename." }
|
||||
};
|
||||
|
||||
// trailing-return-type
|
||||
template<typename T>
|
||||
struct S7 {
|
||||
auto fn9() -> W<T>::M; // { dg-error "need .typename." }
|
||||
};
|
42
gcc/testsuite/g++.dg/cpp2a/typename1.C
Normal file
42
gcc/testsuite/g++.dg/cpp2a/typename1.C
Normal file
|
@ -0,0 +1,42 @@
|
|||
// P0634R3
|
||||
// { dg-do compile { target c++2a } }
|
||||
|
||||
// OK, return type of a function declaration at global scope.
|
||||
template<class T> T::R f();
|
||||
|
||||
// Ill-formed (no diagnostic required), attempt to declare
|
||||
// a void variable template
|
||||
template<class T> void f(T::R);
|
||||
|
||||
template <class T> struct A;
|
||||
template <class T> using B = A<T>::U;
|
||||
|
||||
template<typename T>
|
||||
struct PtrTraits { typedef int Ptr; };
|
||||
|
||||
template<class T> struct S {
|
||||
// OK, in a defining-type-id.
|
||||
using Ptr = PtrTraits<T>::Ptr;
|
||||
|
||||
// OK, trailing-return-type.
|
||||
auto g() -> S<T*>::Ptr;
|
||||
|
||||
// OK, class scope
|
||||
T::R
|
||||
f (T::P p)
|
||||
{
|
||||
// OK, type-id of a static_cast
|
||||
return static_cast<T::R>(p);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
void f ()
|
||||
{
|
||||
// Variable pf of type void* initialized with T::X
|
||||
void (*pf)(T::X);
|
||||
|
||||
// Error: T::X at block scope does not denote a type
|
||||
// (attempt to declare a void variable)
|
||||
void g(T::X); // { dg-error "declared void" }
|
||||
}
|
20
gcc/testsuite/g++.dg/cpp2a/typename10.C
Normal file
20
gcc/testsuite/g++.dg/cpp2a/typename10.C
Normal file
|
@ -0,0 +1,20 @@
|
|||
// P0634R3
|
||||
// { dg-do compile { target c++2a } }
|
||||
|
||||
namespace N {
|
||||
// template<typename T> extern T::type v; // #1a
|
||||
template<typename T> T::type v(typename T::value); // #1b
|
||||
}
|
||||
template<typename T> T::type N::v(T::value); // #2
|
||||
|
||||
namespace N2 {
|
||||
template<typename T> extern T::type v; // #1a
|
||||
//template<typename T> T::type v(typename T::value); // #1b
|
||||
}
|
||||
template<typename T> T::type N2::v(T::value); // { dg-error "" }
|
||||
|
||||
namespace A {
|
||||
inline namespace B { template<typename T> int f(typename T::foo); }
|
||||
inline namespace C { template<typename T> extern int f; }
|
||||
}
|
||||
template<typename T> int A::f(T::foo); // { dg-error "ambiguous" }
|
17
gcc/testsuite/g++.dg/cpp2a/typename11.C
Normal file
17
gcc/testsuite/g++.dg/cpp2a/typename11.C
Normal file
|
@ -0,0 +1,17 @@
|
|||
// P0634R3
|
||||
// { dg-do compile { target c++2a } }
|
||||
|
||||
template<typename T>
|
||||
struct A
|
||||
{
|
||||
typedef int I;
|
||||
};
|
||||
|
||||
template<typename T> struct B
|
||||
{
|
||||
A<T>::I i;
|
||||
typename A<T>::I i2;
|
||||
|
||||
A<int>::I i3;
|
||||
typename A<int>::I i4;
|
||||
};
|
22
gcc/testsuite/g++.dg/cpp2a/typename2.C
Normal file
22
gcc/testsuite/g++.dg/cpp2a/typename2.C
Normal file
|
@ -0,0 +1,22 @@
|
|||
// P0634R3
|
||||
// { dg-do compile { target c++2a } }
|
||||
|
||||
template<class T> typename T::R f();
|
||||
|
||||
template <class T> struct A;
|
||||
template <class T> using B = typename A<T>::U;
|
||||
|
||||
template<typename T>
|
||||
struct PtrTraits { typedef int Ptr; };
|
||||
|
||||
template<class T> struct S {
|
||||
using Ptr = typename PtrTraits<T>::Ptr;
|
||||
|
||||
auto g() -> typename S<T*>::Ptr;
|
||||
|
||||
typename T::R
|
||||
f (typename T::P p)
|
||||
{
|
||||
return static_cast<typename T::R>(p);
|
||||
}
|
||||
};
|
23
gcc/testsuite/g++.dg/cpp2a/typename3.C
Normal file
23
gcc/testsuite/g++.dg/cpp2a/typename3.C
Normal file
|
@ -0,0 +1,23 @@
|
|||
// P0634R3
|
||||
// { dg-do compile { target c++2a } }
|
||||
|
||||
template<class T>
|
||||
void f(int i)
|
||||
{
|
||||
T::x * i; // { dg-error "dependent-name" }
|
||||
}
|
||||
|
||||
struct Foo {
|
||||
typedef int x;
|
||||
};
|
||||
|
||||
struct Bar {
|
||||
static int const x = 5;
|
||||
};
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
f<Bar>(1);
|
||||
f<Foo>(1);
|
||||
}
|
8
gcc/testsuite/g++.dg/cpp2a/typename4.C
Normal file
8
gcc/testsuite/g++.dg/cpp2a/typename4.C
Normal file
|
@ -0,0 +1,8 @@
|
|||
// P0634R3
|
||||
// { dg-do compile { target c++2a } }
|
||||
|
||||
template<class T>
|
||||
struct A {
|
||||
typedef int B;
|
||||
B b;
|
||||
};
|
65
gcc/testsuite/g++.dg/cpp2a/typename5.C
Normal file
65
gcc/testsuite/g++.dg/cpp2a/typename5.C
Normal file
|
@ -0,0 +1,65 @@
|
|||
// P0634R3
|
||||
// { dg-do compile { target c++2a } }
|
||||
|
||||
struct X {
|
||||
template<typename T>
|
||||
struct N { };
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Y {
|
||||
template<typename U>
|
||||
struct N { };
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct A
|
||||
{
|
||||
template <typename U>
|
||||
struct N { };
|
||||
|
||||
typedef typename A::template N<int> a1;
|
||||
typedef typename A::template N<T> a2;
|
||||
typename A::template N<int> a3;
|
||||
typename A::template N<T> a4;
|
||||
A::template N<int> a9;
|
||||
A::template N<T> a10;
|
||||
typedef A<T>::template N<int> a13;
|
||||
typedef A<T>::template N<T> a14;
|
||||
|
||||
typedef typename X::template N<int> x1;
|
||||
typedef typename X::template N<T> x2;
|
||||
typename X::template N<int> x3;
|
||||
typename X::template N<T> x4;
|
||||
typedef X::N<int> x5;
|
||||
typedef X::N<T> x6;
|
||||
typedef typename X::N<int> x7;
|
||||
typedef typename X::N<T> x8;
|
||||
X::N<int> x9;
|
||||
X::N<T> x10;
|
||||
typename X::N<int> x11;
|
||||
typename X::N<T> x12;
|
||||
|
||||
typedef typename Y<int>::template N<int> y1;
|
||||
typedef typename Y<int>::template N<T> y2;
|
||||
typedef typename Y<T>::template N<int> y3;
|
||||
typedef typename Y<T>::template N<T> y4;
|
||||
typename Y<int>::template N<int> y5;
|
||||
typename Y<int>::template N<T> y6;
|
||||
typename Y<T>::template N<int> y7;
|
||||
typename Y<T>::template N<T> y8;
|
||||
typedef Y<int>::N<int> y9;
|
||||
typedef Y<int>::N<T> y10;
|
||||
typedef Y<T>::template N<int> y11;
|
||||
typedef Y<T>::template N<T> y12;
|
||||
typedef typename Y<int>::N<int> y13;
|
||||
typedef typename Y<int>::N<T> y14;
|
||||
Y<int>::N<int> y17;
|
||||
Y<int>::N<T> y18;
|
||||
typename Y<int>::N<int> y21;
|
||||
typename Y<int>::N<T> y22;
|
||||
typedef Y<int>::N<int> y25;
|
||||
typedef Y<int>::N<T> y26;
|
||||
typedef Y<T>::template N<int> y27;
|
||||
typedef Y<T>::template N<T> y28;
|
||||
};
|
126
gcc/testsuite/g++.dg/cpp2a/typename6.C
Normal file
126
gcc/testsuite/g++.dg/cpp2a/typename6.C
Normal file
|
@ -0,0 +1,126 @@
|
|||
// P0634R3
|
||||
// { dg-do compile { target c++2a } }
|
||||
|
||||
// (5.2.1) simple-declaration or a function-definition in namespace scope
|
||||
|
||||
template<typename T>
|
||||
T::X fn1 (int);
|
||||
|
||||
template<typename T>
|
||||
T::X fn1 (int)
|
||||
{
|
||||
return 42;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T::X v1;
|
||||
|
||||
namespace N {
|
||||
template<typename T>
|
||||
T::X v2;
|
||||
}
|
||||
|
||||
// (5.2.2) member-declaration
|
||||
|
||||
template<typename T>
|
||||
struct S {
|
||||
[[noreturn]] T::X fn2 ();
|
||||
T::X fn3 ();
|
||||
T::X fn4 () { return 5; }
|
||||
T::X fn5 () final;
|
||||
T::X fn6 () = 0;
|
||||
T::X fn8 () override;
|
||||
T::X v3;
|
||||
T::X *v4;
|
||||
T::X v5[5];
|
||||
T::X v6 = 0;
|
||||
T::X v7{0};
|
||||
T::X v8 : 16;
|
||||
static constexpr T::X v9 = 0;
|
||||
typedef T::X T2;
|
||||
friend T::X fn7<int> ();
|
||||
static inline T::X v10;
|
||||
};
|
||||
|
||||
// (5.2.3) parameter-declaration in a member-declaration,
|
||||
// unless that parameter-declaration appears in a default argument
|
||||
|
||||
template<typename T>
|
||||
struct S2 {
|
||||
friend int fn1<T::X> ();
|
||||
int fn2 (T::X p);
|
||||
int fn5 (int = T::X);
|
||||
};
|
||||
|
||||
// (5.2.4) parameter-declaration in a declarator of a function or function
|
||||
// template declaration whose declarator-id is qualified,
|
||||
// unless that parameter-declaration appears in a default argument
|
||||
template<typename T>
|
||||
int fn3 (T::X);
|
||||
|
||||
template<typename T>
|
||||
int fn4 (T::X p) { return p; }
|
||||
|
||||
// (5.2.5) parameter-declaration in a lambda-declarator,
|
||||
// unless that parameter-declaration appears in a default argument
|
||||
|
||||
void
|
||||
fn5 ()
|
||||
{
|
||||
auto j = []<typename T>(T::X t, int i) { return i; };
|
||||
}
|
||||
|
||||
// (5.2.6) parameter-declaration of a (non-type) template-parameter
|
||||
|
||||
template<typename T, T::X N>
|
||||
struct S3 { };
|
||||
|
||||
// default argument of a type-parameter of a template
|
||||
template<typename T, typename U = T::X>
|
||||
struct S4 { };
|
||||
|
||||
// type-id of a static_cast, const_cast, reinterpret_cast, or dynamic_cast
|
||||
template<typename T>
|
||||
struct S5 {
|
||||
void fn6 (T::X p)
|
||||
{
|
||||
int i = static_cast<T::Y>(p);
|
||||
i = dynamic_cast<T::Y>(p);
|
||||
i = reinterpret_cast<T::Y>(p);
|
||||
i = const_cast<T::Y>(p);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
void fn7 (T::X p)
|
||||
{
|
||||
int i = static_cast<T::Y>(p);
|
||||
i = dynamic_cast<T::Y>(p);
|
||||
i = reinterpret_cast<T::Y>(p);
|
||||
i = const_cast<T::Y>(p);
|
||||
}
|
||||
|
||||
// new-type-id
|
||||
template<typename T>
|
||||
void
|
||||
fn8 ()
|
||||
{
|
||||
new T::X[10];
|
||||
}
|
||||
|
||||
// defining-type-id
|
||||
|
||||
template<typename T>
|
||||
struct W { typedef int M; };
|
||||
|
||||
template<typename T>
|
||||
struct S6 {
|
||||
using TT = T::X;
|
||||
using TT2 = W<T>::M;
|
||||
};
|
||||
|
||||
// trailing-return-type
|
||||
template<typename T>
|
||||
struct S7 {
|
||||
auto fn9() -> W<T>::M;
|
||||
};
|
26
gcc/testsuite/g++.dg/cpp2a/typename7.C
Normal file
26
gcc/testsuite/g++.dg/cpp2a/typename7.C
Normal file
|
@ -0,0 +1,26 @@
|
|||
// P0634R3
|
||||
// { dg-do compile { target c++2a } }
|
||||
|
||||
// Not in namespace scope.
|
||||
template<typename T>
|
||||
void fn1 ()
|
||||
{
|
||||
// init-statement -> simple-declaration
|
||||
if (T::X r = 0; 0) // { dg-error "need .typename.|expected" }
|
||||
;
|
||||
|
||||
for (T::X g = 0; ;) // { dg-error "need .typename.|expected" }
|
||||
;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
fn2 ()
|
||||
{
|
||||
T::X fn3 (); // { dg-error "need .typename.|expected" }
|
||||
T::X v1; // { dg-error "need .typename.|expected" }
|
||||
T::X v2 = 0; // { dg-error "need .typename.|expected" }
|
||||
T::X v3{0}; // { dg-error "need .typename.|expected" }
|
||||
static constexpr T::X v4 = 0; // { dg-error "need .typename." }
|
||||
typedef T::X T2; // { dg-error "need .typename." }
|
||||
}
|
20
gcc/testsuite/g++.dg/cpp2a/typename8.C
Normal file
20
gcc/testsuite/g++.dg/cpp2a/typename8.C
Normal file
|
@ -0,0 +1,20 @@
|
|||
// P0634R3
|
||||
// { dg-do compile { target c++2a } }
|
||||
|
||||
template<typename T>
|
||||
struct S {
|
||||
static int foo ();
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
int
|
||||
f ()
|
||||
{
|
||||
return S<T>::foo();
|
||||
}
|
||||
|
||||
void
|
||||
test ()
|
||||
{
|
||||
f<int>();
|
||||
}
|
12
gcc/testsuite/g++.dg/cpp2a/typename9.C
Normal file
12
gcc/testsuite/g++.dg/cpp2a/typename9.C
Normal file
|
@ -0,0 +1,12 @@
|
|||
// P0634R3
|
||||
// { dg-do compile { target c++2a } }
|
||||
// { dg-options "-fconcepts" }
|
||||
|
||||
template <typename, typename> class A { class B; };
|
||||
|
||||
template <typename T, typename U> class A<T, U>::B {
|
||||
B(A &);
|
||||
};
|
||||
|
||||
template <typename T, typename U>
|
||||
A<T, U>::B::B(A<T, U> &) {}
|
|
@ -1,4 +1,5 @@
|
|||
// fix-it hint for missing "typename" (PR c++/63392)
|
||||
// { dg-do compile { target c++17_down } }
|
||||
// { dg-options "-fdiagnostics-show-caret" }
|
||||
|
||||
template<typename T>
|
||||
|
|
|
@ -11,5 +11,5 @@ class A
|
|||
};
|
||||
};
|
||||
template <typename T> template <typename U>
|
||||
A<T>::B<U> A<T>::B<U>::foo() {}
|
||||
A<T>::template B<U> A<T>::B<U>::foo() {}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
template <class Op>
|
||||
bool asfun(Op f,
|
||||
Op::first_argument_type a, // { dg-error "not a type" }
|
||||
Op::second_argument_type b) // { dg-error "not a type" }
|
||||
Op::first_argument_type a, // { dg-error "not a type" "" { target c++17_down } }
|
||||
Op::second_argument_type b) // { dg-error "not a type" "" { target c++17_down } }
|
||||
{
|
||||
return Op(a, b);
|
||||
}
|
||||
|
|
|
@ -12,11 +12,11 @@ struct A
|
|||
};
|
||||
|
||||
template <typename T>
|
||||
void func(A<T>::B* ) // { dg-error "variable|template|expression" }
|
||||
void func(A<T>::B* ) // { dg-error "variable|template|expression" "" { target c++17_down } }
|
||||
{
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
func<void>(0); // { dg-error "not declared|expression|;" }
|
||||
func<void>(0); // { dg-error "not declared|expression|;" "" { target c++17_down } }
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ template <class T> struct B
|
|||
|
||||
// PR c++/40738
|
||||
template <class T>
|
||||
void g(const A<T>::type &t); // { dg-error "typename" "typename" }
|
||||
void g(const A<T>::type &t); // { dg-error "typename" "" { target c++17_down } }
|
||||
|
||||
// PR c++/18451
|
||||
template <class T> A<T>::B A<T>::b; // { dg-error "typename" }
|
||||
template <class T> A<T>::B A<T>::b; // { dg-error "typename" "" { target c++17_down } }
|
||||
|
|
|
@ -6,6 +6,6 @@ template <typename T> struct A
|
|||
{
|
||||
template <typename U> struct B
|
||||
{
|
||||
A<T>::template B<U> foo(); // { dg-error "" }
|
||||
A<T>::template B<U> foo(); // { dg-error "" "" { target c++17_down } }
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
template <typename T> struct B { typedef typename T::X X; };
|
||||
template <typename T> struct A { typedef B<T>::X::Y Z; }; // { dg-error "before 'B<T>::X::Y' because 'B<T>::X'" }
|
||||
template <typename T> struct A { typedef B<T>::X::Y Z; }; // { dg-error "before 'B<T>::X::Y' because 'B<T>::X'" "" { target c++17_down } }
|
||||
|
|
|
@ -10,7 +10,7 @@ template <int dim> struct Y : X<dim> {
|
|||
|
||||
// note: I is nested type in X, not Y!
|
||||
template <int dim>
|
||||
Y<dim>::I::I () {} // { dg-error "dependent typedef" "typedef" }
|
||||
// { dg-error "no type|dependent type" "no type" { target *-*-* } .-1 }
|
||||
Y<dim>::I::I () {} // { dg-error "expected|dependent typedef" "typedef" }
|
||||
// { dg-error "no type|dependent type" "no type" { target c++17_down } .-1 }
|
||||
|
||||
template struct Y<1>;
|
||||
|
|
|
@ -7,4 +7,4 @@ template<typename T> struct A
|
|||
typedef typename T::X X;
|
||||
};
|
||||
|
||||
template<typename T> A<T>::X::X() {} // { dg-error "no type|invalid use|not a type|dependent" }
|
||||
template<typename T> A<T>::X::X() {} // { dg-error "expected|no type|invalid use|not a type|dependent" }
|
||||
|
|
|
@ -17,13 +17,15 @@ struct A
|
|||
typedef Bar type1;
|
||||
typedef A::Bar type2;
|
||||
typedef A<T>::Bar type3;
|
||||
typedef A<T*>::Bar type4; // { dg-error "" }
|
||||
typedef A<T*>::Bar type4; // { dg-error "" "" { target c++17_down } }
|
||||
typedef typename A<T*>::Bar type5;
|
||||
|
||||
typedef N<int> type6;
|
||||
typedef A::N<int> type7;
|
||||
// { dg-error "" "" { target c++2a } .-1 }
|
||||
typedef A<T>::N<int> type8;
|
||||
typedef A<T*>::template N<int> type9; // { dg-error "" }
|
||||
// { dg-error "" "" { target c++2a } .-1 }
|
||||
typedef A<T*>::template N<int> type9; // { dg-error "" "" { target c++17_down } }
|
||||
typedef typename A<T*>::template N<int> type10;
|
||||
|
||||
typedef D Bar2;
|
||||
|
@ -36,7 +38,7 @@ struct A
|
|||
|
||||
typedef A::N2 type12;
|
||||
typedef typename type12::K k2;
|
||||
typedef type12::K k1; // { dg-error "" }
|
||||
typedef type12::K k1; // { dg-error "" "" { target c++17_down } }
|
||||
|
||||
// Check that A::Bar2 is not considered dependent even if we use
|
||||
// the typename keyword.
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// PR c++/33209
|
||||
|
||||
template<typename T> void foo(int, T::x); // { dg-error "T::x" }
|
||||
template<typename T> void foo(int, T::x); // { dg-error "T::x" "" { target c++17_down } }
|
||||
|
||||
template<template<typename> class T> void foo2(int, T<int>::x); // { dg-error "T<int>::x" }
|
||||
template<template<typename> class T> void foo2(int, T<int>::x); // { dg-error "T<int>::x" "" { target c++17_down } }
|
||||
|
|
|
@ -6,7 +6,7 @@ template <typename T> struct A
|
|||
{
|
||||
template <typename U> struct D {};
|
||||
};
|
||||
template <typename S> static C::D<S> bar (S const &);
|
||||
template <typename S> static C::template D<S> bar (S const &);
|
||||
};
|
||||
|
||||
struct E {};
|
||||
|
|
|
@ -9,5 +9,5 @@ template<typename> struct B : A {};
|
|||
|
||||
template<typename T> struct C : B<T>
|
||||
{
|
||||
B<T>::A::I::I i; // { dg-error "not a class type|does not name a type|typename" }
|
||||
B<T>::A::I::I i; // { dg-error "not a class type|does not name a type|typename" "" { target c++17_down } }
|
||||
};
|
||||
|
|
|
@ -6,5 +6,5 @@ template <int> struct A
|
|||
static const int i2;
|
||||
};
|
||||
|
||||
template <int N> const int A<N>::i1(A<N>::i);
|
||||
template <int N> const int A<N>::i1(A<N>::i); // { dg-error "no declaration matches" "" { target c++2a } }
|
||||
template <int N> const int A<N>::i2(3, A<N>::i); // { dg-error "expression list" }
|
||||
|
|
|
@ -5,4 +5,4 @@ template<typename T> struct A
|
|||
typedef struct typename T::X X; // { dg-error "expected identifier|two or more" }
|
||||
};
|
||||
|
||||
template<typename T> A<T>::X::X() {} // { dg-error "not a type|forbids declaration|invalid use of" }
|
||||
template<typename T> A<T>::X::X() {} // { dg-error "expected|not a type|forbids declaration|invalid use of" }
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
|
||||
template <class A>
|
||||
struct B {
|
||||
typedef A::C::D E; // { dg-error "" }
|
||||
typedef A::C::D E; // { dg-error "" "" { target c++17_down } }
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue