PR c++/68597, fix auto9.C and auto-neg1.C with -std=c++1z.
authorJason Merrill <jason@redhat.com>
Mon, 7 Dec 2015 04:34:43 +0000 (23:34 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 7 Dec 2015 04:34:43 +0000 (23:34 -0500)
* 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
gcc/cp/decl.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/typeck.c
gcc/testsuite/g++.dg/cpp0x/auto9.C
gcc/testsuite/g++.dg/cpp1y/lambda-deduce-mult-neg.C [new file with mode: 0644]
gcc/testsuite/g++.dg/other/anon-union3.C

index 4568fb8c87a6a505f45e9b422cb1b31a1a84835a..2c04ea0133be810bbe2bc97dcd99ff4cc9f3f6f8 100644 (file)
@@ -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
index e895c5a06ce8d756c6b0d2594a3606bb8e3cc9d9..0af7bd49224e76f56af3d370c2c0bd8db953bbc5 100644 (file)
@@ -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.  */
index b28d17a9b492c3037d75a48594c6a6f620d98c59..85f6cc18aec2863774ab4880564d8a77cdafe3f7 100644 (file)
@@ -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))
         {
index 8435ddc224ab1d301ab9d528b0103f0859bdb7c3..6e50fcd1ee9244db47b911d90b894fb0ec36fdad 100644 (file)
@@ -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
index 0a1e446c95cc001323194ef2be9709fe7f09ed36..3cf3c953f4b8d96efd09d6023e3b3eaf0843a65b 100644 (file)
@@ -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;
     }
 
index 83efbaa534e812f172501fb8fefb68ec0ab404a6..ee204410368a16b150adf83733968d345e58501e 100644 (file)
@@ -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 (file)
index 0000000..c45fe17
--- /dev/null
@@ -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" }
+  };
+}
index 94d0aecaf03e4e0a7fddd98764e8d3f57db6da84..3d9982893eea91c80e3cb3753d379a7d915b19c9 100644 (file)
@@ -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;