re PR c++/70622 (auto specifier don't deduce value type and its pointer type within...
authorJason Merrill <jason@redhat.com>
Thu, 14 Apr 2016 20:14:49 +0000 (16:14 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 14 Apr 2016 20:14:49 +0000 (16:14 -0400)
PR c++/70622

* parser.c (cp_parser_init_declarator): Add auto_result parm.
(cp_parser_simple_declaration): Pass it.
(strip_declarator_types): New.

From-SVN: r234991

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/g++.dg/cpp0x/auto47.C [new file with mode: 0644]

index 01f13b7..6384ab8 100644 (file)
@@ -1,5 +1,10 @@
 2016-04-14  Jason Merrill  <jason@redhat.com>
 
+       PR c++/70622
+       * parser.c (cp_parser_init_declarator): Add auto_result parm.
+       (cp_parser_simple_declaration): Pass it.
+       (strip_declarator_types): New.
+
        PR c++/70543
        * pt.c (value_dependent_expression_p) [VAR_DECL]: A type-dependent
        initializer also makes the variable value-dependent.
index 00e211e..cba2d65 100644 (file)
@@ -2193,7 +2193,7 @@ static tree cp_parser_decltype
 
 static tree cp_parser_init_declarator
   (cp_parser *, cp_decl_specifier_seq *, vec<deferred_access_check, va_gc> *,
-   bool, bool, int, bool *, tree *, location_t *);
+   bool, bool, int, bool *, tree *, location_t *, tree *);
 static cp_declarator *cp_parser_declarator
   (cp_parser *, cp_parser_declarator_kind, int *, bool *, bool, bool);
 static cp_declarator *cp_parser_direct_declarator
@@ -12337,10 +12337,9 @@ cp_parser_simple_declaration (cp_parser* parser,
       && !cp_parser_error_occurred (parser))
     cp_parser_commit_to_tentative_parse (parser);
 
-  tree last_type, auto_node;
+  tree last_type;
 
   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.  */
@@ -12351,6 +12350,7 @@ cp_parser_simple_declaration (cp_parser* parser,
       cp_token *token;
       bool function_definition_p;
       tree decl;
+      tree auto_result = NULL_TREE;
 
       if (saw_declarator)
        {
@@ -12376,7 +12376,8 @@ cp_parser_simple_declaration (cp_parser* parser,
                                        declares_class_or_enum,
                                        &function_definition_p,
                                        maybe_range_for_decl,
-                                       &init_loc);
+                                       &init_loc,
+                                       &auto_result);
       /* If an error occurred while parsing tentatively, exit quickly.
         (That usually happens when in the body of a function; each
         statement is treated as a declaration-statement until proven
@@ -12384,10 +12385,10 @@ cp_parser_simple_declaration (cp_parser* parser,
       if (cp_parser_error_occurred (parser))
        goto done;
 
-      if (auto_node)
+      if (auto_result)
        {
-         tree type = TREE_TYPE (decl);
-         if (last_type && !same_type_p (type, last_type))
+         if (last_type && last_type != error_mark_node
+             && !same_type_p (auto_result, last_type))
            {
              /* If the list of declarators contains more than one declarator,
                 the type of each declared variable is determined as described
@@ -12395,10 +12396,11 @@ cp_parser_simple_declaration (cp_parser* parser,
                 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;
+                       decl_specifiers.type, last_type, auto_result);
+             last_type = error_mark_node;
            }
-         last_type = type;
+         else
+           last_type = auto_result;
        }
 
       /* Handle function definitions specially.  */
@@ -18221,6 +18223,31 @@ cp_parser_asm_definition (cp_parser* parser)
     }
 }
 
+/* Given the type TYPE of a declaration with declarator DECLARATOR, return the
+   type that comes from the decl-specifier-seq.  */
+
+static tree
+strip_declarator_types (tree type, cp_declarator *declarator)
+{
+  for (cp_declarator *d = declarator; d;)
+    switch (d->kind)
+      {
+      case cdk_id:
+      case cdk_error:
+       d = NULL;
+       break;
+
+      default:
+       if (TYPE_PTRMEMFUNC_P (type))
+         type = TYPE_PTRMEMFUNC_FN_TYPE (type);
+       type = TREE_TYPE (type);
+       d = d->declarator;
+       break;
+      }
+
+  return type;
+}
+
 /* Declarators [gram.dcl.decl] */
 
 /* Parse an init-declarator.
@@ -18286,7 +18313,8 @@ cp_parser_init_declarator (cp_parser* parser,
                           int declares_class_or_enum,
                           bool* function_definition_p,
                           tree* maybe_range_for_decl,
-                          location_t* init_loc)
+                          location_t* init_loc,
+                          tree* auto_result)
 {
   cp_token *token = NULL, *asm_spec_start_token = NULL,
            *attributes_start_token = NULL;
@@ -18677,6 +18705,10 @@ cp_parser_init_declarator (cp_parser* parser,
        finish_fully_implicit_template (parser, /*member_decl_opt=*/0);
     }
 
+  if (auto_result && is_initialized && decl_specifiers->type
+      && type_uses_auto (decl_specifiers->type))
+    *auto_result = strip_declarator_types (TREE_TYPE (decl), declarator);
+
   return decl;
 }
 
@@ -25808,7 +25840,7 @@ cp_parser_single_declaration (cp_parser* parser,
                                        member_p,
                                        declares_class_or_enum,
                                        &function_definition_p,
-                                       NULL, NULL);
+                                       NULL, NULL, NULL);
 
     /* 7.1.1-1 [dcl.stc]
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto47.C b/gcc/testsuite/g++.dg/cpp0x/auto47.C
new file mode 100644 (file)
index 0000000..0d80be6
--- /dev/null
@@ -0,0 +1,7 @@
+// PR c++/70622
+// { dg-do compile { target c++11 } }
+
+int main()
+{
+    auto x = 0, *y = &x;
+}