From 480c18e16fd69998266850b804024a7559f1bc70 Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Tue, 10 Sep 2019 23:22:37 +0000 Subject: [PATCH] PR c++/91673 - ICE with noexcept in alias-declaration. * parser.c (CP_PARSER_FLAGS_DELAY_NOEXCEPT): New parser flag. (cp_parser_lambda_declarator_opt): Pass CP_PARSER_FLAGS_NONE to cp_parser_exception_specification_opt. (cp_parser_direct_declarator): Adjust a call to cp_parser_exception_specification_opt. (cp_parser_member_declaration): Pass CP_PARSER_FLAGS_DELAY_NOEXCEPT to cp_parser_declarator if not processing a friend or typedef declaration. (cp_parser_late_noexcept_specifier): Adjust a call to cp_parser_noexcept_specification_opt. (cp_parser_noexcept_specification_opt): New parameter for parser flags, drop the FRIEND_P parameter. Use the new parameter. (cp_parser_exception_specification_opt): Likewise. (cp_parser_transaction): Adjust a call to cp_parser_noexcept_specification_opt. (cp_parser_transaction_expression): Likewise. * g++.dg/cpp1z/using7.C: New test. * g++.dg/cpp1z/using8.C: New test. From-SVN: r275617 --- gcc/cp/ChangeLog | 20 ++++++++++ gcc/cp/parser.c | 60 ++++++++++++++++------------- gcc/testsuite/ChangeLog | 6 +++ gcc/testsuite/g++.dg/cpp1z/using7.C | 33 ++++++++++++++++ gcc/testsuite/g++.dg/cpp1z/using8.C | 12 ++++++ 5 files changed, 105 insertions(+), 26 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1z/using7.C create mode 100644 gcc/testsuite/g++.dg/cpp1z/using8.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 15b1fbfcd0d..0c37460defb 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,23 @@ +2019-09-10 Marek Polacek + + PR c++/91673 - ICE with noexcept in alias-declaration. + * parser.c (CP_PARSER_FLAGS_DELAY_NOEXCEPT): New parser flag. + (cp_parser_lambda_declarator_opt): Pass CP_PARSER_FLAGS_NONE to + cp_parser_exception_specification_opt. + (cp_parser_direct_declarator): Adjust a call to + cp_parser_exception_specification_opt. + (cp_parser_member_declaration): Pass CP_PARSER_FLAGS_DELAY_NOEXCEPT + to cp_parser_declarator if not processing a friend or typedef + declaration. + (cp_parser_late_noexcept_specifier): Adjust a call to + cp_parser_noexcept_specification_opt. + (cp_parser_noexcept_specification_opt): New parameter for parser flags, + drop the FRIEND_P parameter. Use the new parameter. + (cp_parser_exception_specification_opt): Likewise. + (cp_parser_transaction): Adjust a call to + cp_parser_noexcept_specification_opt. + (cp_parser_transaction_expression): Likewise. + 2019-09-10 Marek Polacek PR c++/91705 - constexpr evaluation rejects ++/-- on floats. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index baa60b8834e..254a77ba54b 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -247,8 +247,6 @@ static void cp_lexer_stop_debugging static cp_token_cache *cp_token_cache_new (cp_token *, cp_token *); -static tree cp_parser_noexcept_specification_opt - (cp_parser *, bool, bool *, bool, bool); static tree cp_parser_late_noexcept_specifier (cp_parser *, tree); static void noexcept_override_late_checks @@ -1830,7 +1828,9 @@ enum /* When parsing a decl-specifier-seq, only allow mutable or constexpr. */ CP_PARSER_FLAGS_ONLY_MUTABLE_OR_CONSTEXPR = 0x10, /* When parsing a decl-specifier-seq, allow missing typename. */ - CP_PARSER_FLAGS_TYPENAME_OPTIONAL = 0x20 + CP_PARSER_FLAGS_TYPENAME_OPTIONAL = 0x20, + /* When parsing of the noexcept-specifier should be delayed. */ + CP_PARSER_FLAGS_DELAY_NOEXCEPT = 0x40 }; /* This type is used for parameters and variables which hold @@ -2380,7 +2380,7 @@ static void cp_parser_explicit_instantiation static void cp_parser_explicit_specialization (cp_parser *); -/* Exception handling [gram.exception] */ +/* Exception handling [gram.except] */ static tree cp_parser_try_block (cp_parser *); @@ -2395,9 +2395,11 @@ static tree cp_parser_exception_declaration static tree cp_parser_throw_expression (cp_parser *); static tree cp_parser_exception_specification_opt - (cp_parser *, bool = false); + (cp_parser *, cp_parser_flags); static tree cp_parser_type_id_list (cp_parser *); +static tree cp_parser_noexcept_specification_opt + (cp_parser *, cp_parser_flags, bool, bool *, bool); /* GNU Extensions */ @@ -10938,7 +10940,8 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) tx_qual = cp_parser_tx_qualifier_opt (parser); /* Parse optional exception specification. */ - exception_spec = cp_parser_exception_specification_opt (parser); + exception_spec + = cp_parser_exception_specification_opt (parser, CP_PARSER_FLAGS_NONE); std_attrs = cp_parser_std_attribute_spec_seq (parser); @@ -20877,7 +20880,7 @@ cp_parser_direct_declarator (cp_parser* parser, tree tx_qual = cp_parser_tx_qualifier_opt (parser); /* And the exception-specification. */ exception_specification - = cp_parser_exception_specification_opt (parser, friend_p); + = cp_parser_exception_specification_opt (parser, flags); attrs = cp_parser_std_attribute_spec_seq (parser); @@ -24780,11 +24783,15 @@ cp_parser_member_declaration (cp_parser* parser) tree asm_specification; int ctor_dtor_or_conv_p; bool static_p = (decl_specifiers.storage_class == sc_static); + cp_parser_flags flags = CP_PARSER_FLAGS_TYPENAME_OPTIONAL; + if (!friend_p + && !decl_spec_seq_has_spec_p (&decl_specifiers, ds_typedef)) + flags |= CP_PARSER_FLAGS_DELAY_NOEXCEPT; /* Parse the declarator. */ declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, - CP_PARSER_FLAGS_TYPENAME_OPTIONAL, + flags, &ctor_dtor_or_conv_p, /*parenthesized_p=*/NULL, /*member_p=*/true, @@ -25359,10 +25366,10 @@ cp_parser_late_noexcept_specifier (cp_parser *parser, tree default_arg) /* Parse the cached noexcept-specifier. */ tree parsed_arg = cp_parser_noexcept_specification_opt (parser, + CP_PARSER_FLAGS_NONE, /*require_constexpr=*/true, /*consumed_expr=*/NULL, - /*return_cond=*/false, - /*friend_p=*/false); + /*return_cond=*/false); /* Revert to the main lexer. */ cp_parser_pop_lexer (parser); @@ -25411,15 +25418,15 @@ noexcept_override_late_checks (tree type, tree fndecl) expression if parentheses follow noexcept, or return BOOLEAN_TRUE_NODE if there are no parentheses. CONSUMED_EXPR will be set accordingly. Otherwise, returns a noexcept specification unless RETURN_COND is true, - in which case a boolean condition is returned instead. If FRIEND_P is true, - the function with this noexcept-specification had the `friend' specifier. */ + in which case a boolean condition is returned instead. The parser flags + FLAGS is used to control parsing. */ static tree cp_parser_noexcept_specification_opt (cp_parser* parser, + cp_parser_flags flags, bool require_constexpr, bool* consumed_expr, - bool return_cond, - bool friend_p) + bool return_cond) { cp_token *token; const char *saved_message; @@ -25446,8 +25453,10 @@ cp_parser_noexcept_specification_opt (cp_parser* parser, /* No need to delay parsing for a number literal or true/false. */ && !literal_p && at_class_scope_p () - /* Don't delay parsing for friend member functions. */ - && !friend_p + /* We don't delay parsing for friend member functions, + alias-declarations, and typedefs, even though the standard seems + to require it. */ + && (flags & CP_PARSER_FLAGS_DELAY_NOEXCEPT) && TYPE_BEING_DEFINED (current_class_type) && !LAMBDA_TYPE_P (current_class_type)) return cp_parser_save_noexcept (parser); @@ -25522,11 +25531,11 @@ cp_parser_noexcept_specification_opt (cp_parser* parser, throw ( type-id-list [opt] ) Returns a TREE_LIST representing the exception-specification. The - TREE_VALUE of each node is a type. If FRIEND_P is true, the function - with this noexcept-specification had the `friend' specifier. */ + TREE_VALUE of each node is a type. The parser flags FLAGS is used to + control parsing. */ static tree -cp_parser_exception_specification_opt (cp_parser* parser, bool friend_p) +cp_parser_exception_specification_opt (cp_parser* parser, cp_parser_flags flags) { cp_token *token; tree type_id_list; @@ -25537,11 +25546,10 @@ cp_parser_exception_specification_opt (cp_parser* parser, bool friend_p) /* Is it a noexcept-specification? */ type_id_list - = cp_parser_noexcept_specification_opt (parser, + = cp_parser_noexcept_specification_opt (parser, flags, /*require_constexpr=*/true, /*consumed_expr=*/NULL, - /*return_cond=*/false, - friend_p); + /*return_cond=*/false); if (type_id_list != NULL_TREE) return type_id_list; @@ -41162,10 +41170,10 @@ cp_parser_transaction (cp_parser *parser, cp_token *token) } else noex = cp_parser_noexcept_specification_opt (parser, + CP_PARSER_FLAGS_NONE, /*require_constexpr=*/true, /*consumed_expr=*/NULL, - /*return_cond=*/true, - /*friend_p=*/false); + /*return_cond=*/true); /* Keep track if we're in the lexical scope of an outer transaction. */ new_in = this_in | (old_in & TM_STMT_ATTR_OUTER); @@ -41226,10 +41234,10 @@ cp_parser_transaction_expression (cp_parser *parser, enum rid keyword) /* Parse a noexcept specification. */ noex = cp_parser_noexcept_specification_opt (parser, + CP_PARSER_FLAGS_NONE, /*require_constexpr=*/false, &noex_expr, - /*return_cond=*/true, - /*friend_p=*/false); + /*return_cond=*/true); if (!noex || !noex_expr || cp_lexer_peek_token (parser->lexer)->type == CPP_OPEN_PAREN) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 464765d5293..bbb5d9520fb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-09-10 Marek Polacek + + PR c++/91673 - ICE with noexcept in alias-declaration. + * g++.dg/cpp1z/using7.C: New test. + * g++.dg/cpp1z/using8.C: New test. + 2019-09-10 Marek Polacek PR c++/91705 - constexpr evaluation rejects ++/-- on floats. diff --git a/gcc/testsuite/g++.dg/cpp1z/using7.C b/gcc/testsuite/g++.dg/cpp1z/using7.C new file mode 100644 index 00000000000..f22ac4584a9 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/using7.C @@ -0,0 +1,33 @@ +// PR c++/91673 - ICE with noexcept in alias-declaration. +// { dg-do compile { target c++17 } } + +template +using U1 = T() noexcept(B); + +template +struct S { + int I; + static constexpr bool b = true; + + template + using U2 = T() noexcept(B); + + template + using U8 = T() noexcept(b); + + template + using U10 = T(int p) noexcept(noexcept(p)); + + template + using U11 = T() noexcept(B2); + + using U3 = void() noexcept(B); + using U9 = void() noexcept(b); + using U4 = void() noexcept(noexcept (I)); + using U5 = void(int p) noexcept(noexcept(p)); + + typedef void(*T1)() noexcept(B); + typedef void(*T2)(int p) noexcept(noexcept(p)); +}; + +S s; diff --git a/gcc/testsuite/g++.dg/cpp1z/using8.C b/gcc/testsuite/g++.dg/cpp1z/using8.C new file mode 100644 index 00000000000..c3e1a06b297 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/using8.C @@ -0,0 +1,12 @@ +// PR c++/91673 - ICE with noexcept in alias-declaration. +// { dg-do compile { target c++17 } } + +template +struct overload; + +template +struct overload { + using signature_t = Ret(Args...) noexcept(NoExcept); +}; + +overload x; -- 2.30.2