summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog15
-rw-r--r--gcc/cp/decl.c5
-rw-r--r--gcc/cp/parser.c81
-rw-r--r--gcc/cp/pt.c27
-rw-r--r--gcc/cp/typeck.c12
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto9.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/lambda-deduce-mult-neg.C13
-rw-r--r--gcc/testsuite/g++.dg/other/anon-union3.C4
8 files changed, 126 insertions, 37 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 4568fb8c87a..2c04ea0133b 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,18 @@
+2015-12-05 Jason Merrill <jason@redhat.com>
+
+ 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 <jason@redhat.com>
PR c++/68645
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index e895c5a06ce..0af7bd49224 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 ("%<auto%> can only be specified for variables "
- "or function declarations");
+ error_at (declspecs->locations[ds_type_spec],
+ "%<auto%> 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 b28d17a9b49..85f6cc18aec 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 %<auto%> 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 %<auto%> 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 %<auto%> 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 %<auto%> 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 8435ddc224a..6e50fcd1ee9 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 0a1e446c95c..3cf3c953f4b 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 83efbaa534e..ee204410368 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 <auto V = 4> struct G {}; // { dg-error "auto" }
template <typename T> struct H { H (); ~H (); };
-H<auto> h; // { dg-error "invalid" }
+H<auto> 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 00000000000..c45fe177cb1
--- /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 94d0aecaf03..3d9982893ee 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;