diff options
author | Nathan Sidwell <nathan@acm.org> | 2020-11-03 08:45:15 -0800 |
---|---|---|
committer | Nathan Sidwell <nathan@acm.org> | 2020-11-03 08:49:27 -0800 |
commit | cee45e49126d18fe2dc8efc83c190662cd41914d (patch) | |
tree | 055b8c78ad9ddd204792b60acb51dbfabc52a6a9 /gcc/cp/parser.c | |
parent | 1c8b8efa5becb70e04216a60021b835387ffea4e (diff) | |
download | gcc-cee45e49126d18fe2dc8efc83c190662cd41914d.zip gcc-cee45e49126d18fe2dc8efc83c190662cd41914d.tar.gz gcc-cee45e49126d18fe2dc8efc83c190662cd41914d.tar.bz2 |
c++: Directly fixup deferred eh-specs
eh-specifiers in a class definition are complete-definition contexts,
and we sometimes need to deferr their parsing. We create a deferred
eh specifier, which can end up persisting in the type system due to
variants being created before the deferred parse. This causes
problems in modules handling.
This patch adds fixup_deferred_exception_variants, which directly
modifies the variants of such an eh spec once parsed. As commented,
the general case is quite hard, so it doesn't deal with everything.
But I do catch the cases I encountered (from the std library).
gcc/cp/
* cp-tree.h (fixup_deferred_exception_variants): Declare.
* parser.c (cp_parser_class_specifier_1): Call it when
completing deferred parses rather than creating a variant.
(cp_parser_member_declaration): Move comment from ...
(cp_parser_noexcept_specification_opt): ... here. Refactor the
deferred parse.
* tree.c (fixup_deferred_exception_variants): New.
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r-- | gcc/cp/parser.c | 26 |
1 files changed, 14 insertions, 12 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index dd8c4b5..274797f 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -24334,8 +24334,12 @@ cp_parser_class_specifier_1 (cp_parser* parser) /* Now we can parse the noexcept-specifier. */ spec = cp_parser_late_noexcept_specifier (parser, spec); - if (spec != error_mark_node) - TREE_TYPE (decl) = build_exception_variant (TREE_TYPE (decl), spec); + if (spec == error_mark_node) + spec = NULL_TREE; + + /* Update the fn's type directly -- it might have escaped + beyond this decl :( */ + fixup_deferred_exception_variants (TREE_TYPE (decl), spec); /* Restore the state of local_variables_forbidden_p. */ parser->local_variables_forbidden_p = local_variables_forbidden_p; @@ -25371,6 +25375,9 @@ cp_parser_member_declaration (cp_parser* parser) int ctor_dtor_or_conv_p; bool static_p = (decl_specifiers.storage_class == sc_static); cp_parser_flags flags = CP_PARSER_FLAGS_TYPENAME_OPTIONAL; + /* We can't delay parsing for friends, + alias-declarations, and typedefs, even though the + standard seems to require it. */ if (!friend_p && !decl_spec_seq_has_spec_p (&decl_specifiers, ds_typedef)) flags |= CP_PARSER_FLAGS_DELAY_NOEXCEPT; @@ -26059,19 +26066,14 @@ cp_parser_noexcept_specification_opt (cp_parser* parser, a class. So, if the noexcept-specifier has the optional expression, just save the tokens, and reparse this after we're done with the class. */ - const bool literal_p - = ((cp_lexer_nth_token_is (parser->lexer, 3, CPP_NUMBER) - || cp_lexer_nth_token_is (parser->lexer, 3, CPP_KEYWORD)) - && cp_lexer_nth_token_is (parser->lexer, 4, CPP_CLOSE_PAREN)); - if (cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_PAREN) + if ((flags & CP_PARSER_FLAGS_DELAY_NOEXCEPT) + && cp_lexer_nth_token_is (parser->lexer, 2, CPP_OPEN_PAREN) /* No need to delay parsing for a number literal or true/false. */ - && !literal_p + && !((cp_lexer_nth_token_is (parser->lexer, 3, CPP_NUMBER) + || cp_lexer_nth_token_is (parser->lexer, 3, CPP_KEYWORD)) + && cp_lexer_nth_token_is (parser->lexer, 4, CPP_CLOSE_PAREN)) && at_class_scope_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); |