From 5dc58049178775591a6e2dd04c9ce9cee4007dab Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Sun, 6 Dec 2015 23:34:43 -0500 Subject: [PATCH] PR c++/68597, fix auto9.C and auto-neg1.C with -std=c++1z. * decl.c (check_tag_decl): Use ds_type_spec in auto diagnostic. * typeck.c (check_return_expr): Check for inconsistent deduction. * parser.c (class type_id_in_expr_sentinel): New. (cp_parser_primary_expression) [RID_VA_ARG]: Use it. (cp_parser_new_expression): Use it. (cp_parser_trait_expr): Use it. (cp_parser_type_id_1): Complain about auto if in_type_id_in_expr_p. (cp_parser_default_type_template_argument): Check for auto. (cp_parser_type_id_list): Likewise. (cp_parser_simple_type_specifier): Allow auto parms if flag_concepts. * pt.c (do_auto_deduction): Handle erroneous type. From-SVN: r231349 --- gcc/cp/ChangeLog | 15 ++++ gcc/cp/decl.c | 5 +- gcc/cp/parser.c | 81 +++++++++++++++++-- gcc/cp/pt.c | 27 ++----- gcc/cp/typeck.c | 12 ++- gcc/testsuite/g++.dg/cpp0x/auto9.C | 6 +- .../g++.dg/cpp1y/lambda-deduce-mult-neg.C | 13 +++ gcc/testsuite/g++.dg/other/anon-union3.C | 4 +- 8 files changed, 126 insertions(+), 37 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-deduce-mult-neg.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4568fb8c87a6..2c04ea0133be 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,18 @@ +2015-12-05 Jason Merrill + + PR c++/68597, fix auto9.C and auto-neg1.C with -std=c++1z. + * decl.c (check_tag_decl): Use ds_type_spec in auto diagnostic. + * typeck.c (check_return_expr): Check for inconsistent deduction. + * parser.c (class type_id_in_expr_sentinel): New. + (cp_parser_primary_expression) [RID_VA_ARG]: Use it. + (cp_parser_new_expression): Use it. + (cp_parser_trait_expr): Use it. + (cp_parser_type_id_1): Complain about auto if in_type_id_in_expr_p. + (cp_parser_default_type_template_argument): Check for auto. + (cp_parser_type_id_list): Likewise. + (cp_parser_simple_type_specifier): Allow auto parms if flag_concepts. + * pt.c (do_auto_deduction): Handle erroneous type. + 2015-12-04 Jason Merrill PR c++/68645 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index e895c5a06ce8..0af7bd49224e 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -4555,8 +4555,9 @@ check_tag_decl (cp_decl_specifier_seq *declspecs, permerror (input_location, "declaration does not declare anything"); else if (declared_type != NULL_TREE && type_uses_auto (declared_type)) { - error ("% can only be specified for variables " - "or function declarations"); + error_at (declspecs->locations[ds_type_spec], + "% can only be specified for variables " + "or function declarations"); return error_mark_node; } /* Check for an anonymous union. */ diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index b28d17a9b492..85f6cc18aec2 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -178,6 +178,22 @@ enum required_token { RT_TRANSACTION_CANCEL /* __transaction_cancel */ }; +/* RAII wrapper for parser->in_type_id_in_expr_p, setting it on creation and + reverting it on destruction. */ + +class type_id_in_expr_sentinel +{ + cp_parser *parser; + bool saved; +public: + type_id_in_expr_sentinel (cp_parser *parser, bool set = true) + : parser (parser), + saved (parser->in_type_id_in_expr_p) + { parser->in_type_id_in_expr_p = set; } + ~type_id_in_expr_sentinel () + { parser->in_type_id_in_expr_p = saved; } +}; + /* Prototypes. */ static cp_lexer *cp_lexer_new_main @@ -4888,7 +4904,10 @@ cp_parser_primary_expression (cp_parser *parser, cp_parser_require (parser, CPP_COMMA, RT_COMMA); type_location = cp_lexer_peek_token (parser->lexer)->location; /* Parse the type-id. */ - type = cp_parser_type_id (parser); + { + type_id_in_expr_sentinel s (parser); + type = cp_parser_type_id (parser); + } /* Look for the closing `)'. */ location_t finish_loc = cp_lexer_peek_token (parser->lexer)->location; @@ -7907,7 +7926,10 @@ cp_parser_new_expression (cp_parser* parser) /* Parse the type-id. */ parser->type_definition_forbidden_message = G_("types may not be defined in a new-expression"); - type = cp_parser_type_id (parser); + { + type_id_in_expr_sentinel s (parser); + type = cp_parser_type_id (parser); + } parser->type_definition_forbidden_message = saved_message; /* Look for the closing `)'. */ @@ -9391,7 +9413,10 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword) cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); - type1 = cp_parser_type_id (parser); + { + type_id_in_expr_sentinel s (parser); + type1 = cp_parser_type_id (parser); + } if (type1 == error_mark_node) return error_mark_node; @@ -9400,7 +9425,10 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword) { cp_parser_require (parser, CPP_COMMA, RT_COMMA); - type2 = cp_parser_type_id (parser); + { + type_id_in_expr_sentinel s (parser); + type2 = cp_parser_type_id (parser); + } if (type2 == error_mark_node) return error_mark_node; @@ -12149,6 +12177,11 @@ cp_parser_simple_declaration (cp_parser* parser, && !cp_parser_error_occurred (parser)) cp_parser_commit_to_tentative_parse (parser); + tree last_type, auto_node; + + last_type = NULL_TREE; + auto_node = type_uses_auto (decl_specifiers.type); + /* Keep going until we hit the `;' at the end of the simple declaration. */ saw_declarator = false; @@ -12190,6 +12223,24 @@ cp_parser_simple_declaration (cp_parser* parser, otherwise.) */ if (cp_parser_error_occurred (parser)) goto done; + + if (auto_node) + { + tree type = TREE_TYPE (decl); + if (last_type && !same_type_p (type, last_type)) + { + /* If the list of declarators contains more than one declarator, + the type of each declared variable is determined as described + above. If the type deduced for the template parameter U is not + the same in each deduction, the program is ill-formed. */ + error_at (decl_specifiers.locations[ds_type_spec], + "inconsistent deduction for %qT: %qT and then %qT", + decl_specifiers.type, last_type, type); + auto_node = NULL_TREE; + } + last_type = type; + } + /* Handle function definitions specially. */ if (function_definition_p) { @@ -14188,11 +14239,20 @@ cp_parser_default_type_template_argument (cp_parser *parser) /* Consume the `=' token. */ cp_lexer_consume_token (parser->lexer); + cp_token *token = cp_lexer_peek_token (parser->lexer); + /* Parse the default-argument. */ push_deferring_access_checks (dk_no_deferred); tree default_argument = cp_parser_type_id (parser); pop_deferring_access_checks (); + if (flag_concepts && type_uses_auto (default_argument)) + { + error_at (token->location, + "invalid use of % in default template argument"); + return error_mark_node; + } + return default_argument; } @@ -15870,7 +15930,7 @@ cp_parser_simple_type_specifier (cp_parser* parser, "use of % in parameter declaration " "only available with " "-std=c++14 or -std=gnu++14"); - else + else if (!flag_concepts) pedwarn (token->location, OPT_Wpedantic, "ISO C++ forbids use of % in parameter " "declaration"); @@ -19647,7 +19707,7 @@ cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg, if (type_specifier_seq.type /* The concepts TS allows 'auto' as a type-id. */ - && !flag_concepts + && (!flag_concepts || parser->in_type_id_in_expr_p) /* None of the valid uses of 'auto' in C++14 involve the type-id nonterminal, but it is valid in a trailing-return-type. */ && !(cxx_dialect >= cxx14 && is_trailing_return) @@ -22875,8 +22935,17 @@ cp_parser_type_id_list (cp_parser* parser) cp_token *token; tree type; + token = cp_lexer_peek_token (parser->lexer); + /* Get the next type-id. */ type = cp_parser_type_id (parser); + /* Check for invalid 'auto'. */ + if (flag_concepts && type_uses_auto (type)) + { + error_at (token->location, + "invalid use of % in exception-specification"); + type = error_mark_node; + } /* Parse the optional ellipsis. */ if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)) { diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 8435ddc224ab..6e50fcd1ee92 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -23712,6 +23712,9 @@ do_auto_deduction (tree type, tree init, tree auto_node, } } + if (type == error_mark_node) + return error_mark_node; + init = resolve_nondeduced_context (init); if (AUTO_IS_DECLTYPE (auto_node)) @@ -23770,26 +23773,6 @@ do_auto_deduction (tree type, tree init, tree auto_node, } } - /* If the list of declarators contains more than one declarator, the type - of each declared variable is determined as described above. If the - type deduced for the template parameter U is not the same in each - deduction, the program is ill-formed. */ - if (!flag_concepts && TREE_TYPE (auto_node) - && !same_type_p (TREE_TYPE (auto_node), TREE_VEC_ELT (targs, 0))) - { - if (cfun && auto_node == current_function_auto_return_pattern - && LAMBDA_FUNCTION_P (current_function_decl)) - error ("inconsistent types %qT and %qT deduced for " - "lambda return type", TREE_TYPE (auto_node), - TREE_VEC_ELT (targs, 0)); - else - error ("inconsistent deduction for %qT: %qT and then %qT", - auto_node, TREE_TYPE (auto_node), TREE_VEC_ELT (targs, 0)); - return error_mark_node; - } - if (!flag_concepts) - TREE_TYPE (auto_node) = TREE_VEC_ELT (targs, 0); - /* Check any placeholder constraints against the deduced type. */ if (flag_concepts && !processing_template_decl) if (tree constr = PLACEHOLDER_TYPE_CONSTRAINTS (auto_node)) @@ -23877,7 +23860,9 @@ is_auto_r (tree tp, void */*data*/) tree type_uses_auto (tree type) { - if (flag_concepts) + if (type == NULL_TREE) + return NULL_TREE; + else if (flag_concepts) { /* The Concepts TS allows multiple autos in one type-specifier; just return the first one we find, do_auto_deduction will collect all of diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 0a1e446c95cc..3cf3c953f4b8 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -8644,9 +8644,15 @@ check_return_expr (tree retval, bool *no_warning) /* Leave it. */; else if (functype == current_function_auto_return_pattern) apply_deduced_return_type (current_function_decl, type); - else - /* A mismatch should have been diagnosed in do_auto_deduction. */ - gcc_assert (same_type_p (type, functype)); + else if (!same_type_p (type, functype)) + { + if (LAMBDA_FUNCTION_P (current_function_decl)) + error ("inconsistent types %qT and %qT deduced for " + "lambda return type", functype, type); + else + error ("inconsistent deduction for auto return type: " + "%qT and then %qT", functype, type); + } functype = type; } diff --git a/gcc/testsuite/g++.dg/cpp0x/auto9.C b/gcc/testsuite/g++.dg/cpp0x/auto9.C index 83efbaa534e8..ee204410368a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto9.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto9.C @@ -114,10 +114,10 @@ badthrow2 () throw (auto &) // { dg-error "invalid use of|expected" } template struct G {}; // { dg-error "auto" } template struct H { H (); ~H (); }; -H h; // { dg-error "invalid" } +H h; // { dg-error "invalid|initializer" } -void qq (auto); // { dg-error "auto" } -void qr (auto*); // { dg-error "auto" } +void qq (auto); // { dg-error "auto" "" { target { ! c++1z } } } +void qr (auto*); // { dg-error "auto" "" { target { ! c++1z } } } // PR c++/46145 typedef auto autot; // { dg-error "auto" } diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-deduce-mult-neg.C b/gcc/testsuite/g++.dg/cpp1y/lambda-deduce-mult-neg.C new file mode 100644 index 000000000000..c45fe177cb15 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-deduce-mult-neg.C @@ -0,0 +1,13 @@ +// PR c++/68597 +// { dg-do compile { target c++14 } } + +auto make_test_objective3(double beta) { + auto phi0_prime = [=](double alpha) { + if (alpha <= 1-beta) + return -1; + else if (alpha >= 1+beta) + return 1; + else + return 1 / beta * (alpha - 1); // { dg-error "type" } + }; +} diff --git a/gcc/testsuite/g++.dg/other/anon-union3.C b/gcc/testsuite/g++.dg/other/anon-union3.C index 94d0aecaf03e..3d9982893eea 100644 --- a/gcc/testsuite/g++.dg/other/anon-union3.C +++ b/gcc/testsuite/g++.dg/other/anon-union3.C @@ -3,9 +3,9 @@ class C { auto union // { dg-error "storage class" "" { target { ! c++11 } } } - { + { // { dg-error "auto" "" { target c++11 } 5 } int a; - }; // { dg-error "multiple|specified" "" { target c++11 } } + }; // { dg-error "multiple types" "" { target c++11 } } register union // { dg-error "storage class" } { int b; -- 2.43.5