]> gcc.gnu.org Git - gcc.git/commitdiff
cp-tree.h (AUTO_IS_DECLTYPE): New.
authorJason Merrill <jason@redhat.com>
Fri, 29 Mar 2013 19:51:36 +0000 (15:51 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 29 Mar 2013 19:51:36 +0000 (15:51 -0400)
N3582
* cp-tree.h (AUTO_IS_DECLTYPE): New.
* parser.c (cp_parser_decltype): Handle decltype(auto).
(cp_parser_type_id_1): Allow auto without a late-specified
return in C++1y.
(cp_parser_primary_expression): Use the return value of
finish_parenthesized_expr.
(cp_parser_transaction_expression): Likewise.
* semantics.c (force_paren_expr): New.
(finish_parenthesized_expr): Use it.
* call.c (build_conditional_expr_1): Likewise.
* pt.c (do_auto_deduction): Handle decltype(auto).
(tsubst_copy): Handle PAREN_EXPR.
(tsubst_copy_and_build): Likewise.
* error.c (dump_expr): Handle PAREN_EXPR.
* cxx-pretty-print.c (pp_cxx_expression): Likewise.
* mangle.c (write_expression): Ignore PAREN_EXPR.

* parser.c (cp_parser_decltype_expr): Split out...
(cp_parser_decltype): ...from here.

From-SVN: r197248

13 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/cxx-pretty-print.c
gcc/cp/error.c
gcc/cp/mangle.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/testsuite/g++.dg/cpp1y/auto-fn15.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/auto-fn16.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/auto-fn17.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/mangle1.C [new file with mode: 0644]

index 577740963c9f092be335d86f921c726349823a68..8059562e581b470ba66cec7440c071843798cb1d 100644 (file)
@@ -1,5 +1,23 @@
 2013-03-29  Jason Merrill  <jason@redhat.com>
 
+       N3582
+       * cp-tree.h (AUTO_IS_DECLTYPE): New.
+       * parser.c (cp_parser_decltype): Handle decltype(auto).
+       (cp_parser_type_id_1): Allow auto without a late-specified
+       return in C++1y.
+       (cp_parser_primary_expression): Use the return value of
+       finish_parenthesized_expr.
+       (cp_parser_transaction_expression): Likewise.
+       * semantics.c (force_paren_expr): New.
+       (finish_parenthesized_expr): Use it.
+       * call.c (build_conditional_expr_1): Likewise.
+       * pt.c (do_auto_deduction): Handle decltype(auto).
+       (tsubst_copy): Handle PAREN_EXPR.
+       (tsubst_copy_and_build): Likewise.
+       * error.c (dump_expr): Handle PAREN_EXPR.
+       * cxx-pretty-print.c (pp_cxx_expression): Likewise.
+       * mangle.c (write_expression): Ignore PAREN_EXPR.
+
        * parser.c (cp_parser_decltype_expr): Split out...
        (cp_parser_decltype): ...from here.
 
index d1777a0ce288350d2894997d08809eb384157f95..62d6e15ff7b059527515f0fc90d968c7230cdb02 100644 (file)
@@ -4845,6 +4845,8 @@ build_conditional_expr_1 (tree arg1, tree arg2, tree arg3,
         lvalue, we must add a NON_LVALUE_EXPR.  */
       result = rvalue (result);
     }
+  else
+    result = force_paren_expr (result);
 
   return result;
 }
index edf46d4c262ae373ad917750687d9032aa657878..521da0054abfc48fe38a66fc6a58c401f03602c9 100644 (file)
@@ -121,6 +121,7 @@ c-common.h, not after.
    4: TYPE_HAS_NONTRIVIAL_DESTRUCTOR
    5: CLASS_TYPE_P (in RECORD_TYPE and UNION_TYPE)
       ENUM_FIXED_UNDERLYING_TYPE_P (in ENUMERAL_TYPE)
+      AUTO_IS_DECLTYPE (in TEMPLATE_TYPE_PARM)
    6: TYPE_DEPENDENT_P_VALID
 
    Usage of DECL_LANG_FLAG_?:
@@ -4604,6 +4605,10 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
 #define TEMPLATE_TYPE_PARAMETER_PACK(NODE) \
   (TEMPLATE_PARM_PARAMETER_PACK (TEMPLATE_TYPE_PARM_INDEX (NODE)))
 
+/* True iff this TEMPLATE_TYPE_PARM represents decltype(auto).  */
+#define AUTO_IS_DECLTYPE(NODE) \
+  (TYPE_LANG_FLAG_5 (TEMPLATE_TYPE_PARM_CHECK (NODE)))
+
 /* These constants can used as bit flags in the process of tree formatting.
 
    TFF_PLAIN_IDENTIFIER: unqualified part of a name.
@@ -5659,6 +5664,7 @@ extern tree finish_asm_stmt                       (int, tree, tree, tree, tree,
 extern tree finish_label_stmt                  (tree);
 extern void finish_label_decl                  (tree);
 extern tree finish_parenthesized_expr          (tree);
+extern tree force_paren_expr                   (tree);
 extern tree finish_non_static_data_member       (tree, tree, tree);
 extern tree begin_stmt_expr                    (void);
 extern tree finish_stmt_expr_expr              (tree, tree);
index 45ad20cd9a996fcd03cff47d2e997b80386e12f7..4275b45c1e75c5d73392f05dd062b9e1b92a2d8c 100644 (file)
@@ -1167,6 +1167,12 @@ pp_cxx_expression (cxx_pretty_printer *pp, tree t)
       pp_cxx_ws_string (pp, "<lambda>");
       break;
 
+    case PAREN_EXPR:
+      pp_cxx_left_paren (pp);
+      pp_cxx_expression (pp, TREE_OPERAND (t, 0));
+      pp_cxx_right_paren (pp);
+      break;
+
     default:
       pp_c_expression (pp_c_base (pp), t);
       break;
index 2af900ded8bba42d5fa3aefc7223df5cf4825609..dd27e6cc2f3a34597b172425793bd58269bad573 100644 (file)
@@ -2506,6 +2506,12 @@ dump_expr (tree t, int flags)
       pp_string (cxx_pp, M_("<lambda>"));
       break;
 
+    case PAREN_EXPR:
+      pp_cxx_left_paren (cxx_pp);
+      dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
+      pp_cxx_right_paren (cxx_pp);
+      break;
+
       /*  This list is incomplete, but should suffice for now.
          It is very important that `sorry' does not call
          `report_error_function'.  That could cause an infinite loop.  */
index 08bfa22e0fab67bf2e678c5e166827ca65aae0cb..e303ea245b1cff038603c1598d58516a369a145c 100644 (file)
@@ -2555,6 +2555,8 @@ write_expression (tree expr)
      is converted (via qualification conversions) to another
      type.  */
   while (TREE_CODE (expr) == NOP_EXPR
+        /* Parentheses aren't mangled.  */
+        || code == PAREN_EXPR
         || TREE_CODE (expr) == NON_LVALUE_EXPR)
     {
       expr = TREE_OPERAND (expr, 0);
index d36c984d9d57cb9c775cabac405815d5c8b0a5f0..8ad877ef82bb6a95aae9b25fe47cb73f9f73dab9 100644 (file)
@@ -4106,7 +4106,7 @@ cp_parser_primary_expression (cp_parser *parser,
               example, the expression is of the form `A::B', since
               `&A::B' might be a pointer-to-member, but `&(A::B)' is
               not.  */
-           finish_parenthesized_expr (expr);
+           expr = finish_parenthesized_expr (expr);
            /* DR 705: Wrapping an unqualified name in parentheses
               suppresses arg-dependent lookup.  We want to pass back
               CP_ID_KIND_QUALIFIED for suppressing vtable lookup
@@ -11399,7 +11399,9 @@ cp_parser_decltype_expr (cp_parser *parser,
 /* Parse a `decltype' type. Returns the type.
 
    simple-type-specifier:
-     decltype ( expression )  */
+     decltype ( expression )
+   C++14 proposal:
+     decltype ( auto )  */
 
 static tree
 cp_parser_decltype (cp_parser *parser)
@@ -11427,6 +11429,18 @@ cp_parser_decltype (cp_parser *parser)
   if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
     return error_mark_node;
 
+  /* decltype (auto) */
+  if (cxx_dialect >= cxx1y
+      && cp_lexer_next_token_is_keyword (parser->lexer, RID_AUTO))
+    {
+      cp_lexer_consume_token (parser->lexer);
+      if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+       return error_mark_node;
+      expr = make_auto ();
+      AUTO_IS_DECLTYPE (expr) = true;
+      goto rewrite;
+    }
+
   /* Types cannot be defined in a `decltype' expression.  Save away the
      old message.  */
   saved_message = parser->type_definition_forbidden_message;
@@ -11485,6 +11499,7 @@ cp_parser_decltype (cp_parser *parser)
   expr = finish_decltype_type (expr, id_expression_or_member_access_p,
                               tf_warning_or_error);
 
+ rewrite:
   /* Replace the decltype with a CPP_DECLTYPE so we don't need to parse
      it again.  */
   start_token->type = CPP_DECLTYPE;
@@ -17207,6 +17222,7 @@ cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg,
     abstract_declarator = NULL;
 
   if (type_specifier_seq.type
+      && cxx_dialect < cxx1y
       && type_uses_auto (type_specifier_seq.type))
     {
       /* A type-id with type 'auto' is only ok if the abstract declarator
@@ -28003,7 +28019,7 @@ cp_parser_transaction_expression (cp_parser *parser, enum rid keyword)
       cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
 
       expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
-      finish_parenthesized_expr (expr);
+      expr = finish_parenthesized_expr (expr);
 
       cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
     }
index 4ef4ede1621133cb4baed1bcf19d0d59967af1a5..2fc282e91121a7c4b4a92e70f5216f603c5ed847 100644 (file)
@@ -12303,6 +12303,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
     case TYPEID_EXPR:
     case REALPART_EXPR:
     case IMAGPART_EXPR:
+    case PAREN_EXPR:
       return build1
        (code, tsubst (TREE_TYPE (t), args, complain, in_decl),
         tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl));
@@ -14549,6 +14550,9 @@ tsubst_copy_and_build (tree t,
       RETURN (tsubst_expr(t, args, complain, in_decl,
             integral_constant_expression_p));
 
+    case PAREN_EXPR:
+      RETURN (finish_parenthesized_expr (RECUR (TREE_OPERAND (t, 0))));
+
     default:
       /* Handle Objective-C++ constructs, if appropriate.  */
       {
@@ -20593,9 +20597,7 @@ listify_autos (tree type, tree auto_node)
 tree
 do_auto_deduction (tree type, tree init, tree auto_node)
 {
-  tree parms, tparms, targs;
-  tree args[1];
-  int val;
+  tree targs;
 
   if (init == error_mark_node)
     return error_mark_node;
@@ -20614,32 +20616,42 @@ do_auto_deduction (tree type, tree init, tree auto_node)
 
   init = resolve_nondeduced_context (init);
 
-  parms = build_tree_list (NULL_TREE, type);
-  args[0] = init;
-  tparms = make_tree_vec (1);
   targs = make_tree_vec (1);
-  TREE_VEC_ELT (tparms, 0)
-    = build_tree_list (NULL_TREE, TYPE_NAME (auto_node));
-  val = type_unification_real (tparms, targs, parms, args, 1, 0,
-                              DEDUCE_CALL, LOOKUP_NORMAL,
-                              /*explain_p=*/false);
-  if (val > 0)
-    {
-      if (processing_template_decl)
-       /* Try again at instantiation time.  */
-       return type;
-      if (type && type != error_mark_node)
-       /* If type is error_mark_node a diagnostic must have been
-          emitted by now.  Also, having a mention to '<type error>'
-          in the diagnostic is not really useful to the user.  */
+  if (AUTO_IS_DECLTYPE (auto_node))
+    {
+      bool id = (DECL_P (init) || TREE_CODE (init) == COMPONENT_REF);
+      TREE_VEC_ELT (targs, 0)
+       = finish_decltype_type (init, id, tf_warning_or_error);
+    }
+  else
+    {
+      tree parms = build_tree_list (NULL_TREE, type);
+      tree tparms = make_tree_vec (1);
+      int val;
+
+      TREE_VEC_ELT (tparms, 0)
+       = build_tree_list (NULL_TREE, TYPE_NAME (auto_node));
+      val = type_unification_real (tparms, targs, parms, &init, 1, 0,
+                                  DEDUCE_CALL, LOOKUP_NORMAL,
+                                  /*explain_p=*/false);
+      if (val > 0)
        {
-         if (cfun && auto_node == current_function_auto_return_pattern
-             && LAMBDA_FUNCTION_P (current_function_decl))
-           error ("unable to deduce lambda return type from %qE", init);
-         else
-           error ("unable to deduce %qT from %qE", type, init);
+         if (processing_template_decl)
+           /* Try again at instantiation time.  */
+           return type;
+         if (type && type != error_mark_node)
+           /* If type is error_mark_node a diagnostic must have been
+              emitted by now.  Also, having a mention to '<type error>'
+              in the diagnostic is not really useful to the user.  */
+           {
+             if (cfun && auto_node == current_function_auto_return_pattern
+                 && LAMBDA_FUNCTION_P (current_function_decl))
+               error ("unable to deduce lambda return type from %qE", init);
+             else
+               error ("unable to deduce %qT from %qE", type, init);
+           }
+         return error_mark_node;
        }
-      return error_mark_node;
     }
 
   /* If the list of declarators contains more than one declarator, the type
index 8bd76120fc70b328705f28954bd7978754f6631b..63f18d022f910054e06364ead0bfba4bb0644b10 100644 (file)
@@ -1507,6 +1507,38 @@ finish_mem_initializers (tree mem_inits)
     emit_mem_initializers (mem_inits);
 }
 
+/* Obfuscate EXPR if it looks like an id-expression or member access so
+   that the call to finish_decltype in do_auto_deduction will give the
+   right result.  */
+
+tree
+force_paren_expr (tree expr)
+{
+  /* This is only needed for decltype(auto) in C++14.  */
+  if (cxx_dialect < cxx1y)
+    return expr;
+
+  if (!DECL_P (expr) && TREE_CODE (expr) != COMPONENT_REF
+      && TREE_CODE (expr) != SCOPE_REF)
+    return expr;
+
+  if (processing_template_decl)
+    expr = build1 (PAREN_EXPR, TREE_TYPE (expr), expr);
+  else
+    {
+      cp_lvalue_kind kind = lvalue_kind (expr);
+      if ((kind & ~clk_class) != clk_none)
+       {
+         tree type = unlowered_expr_type (expr);
+         bool rval = !!(kind & clk_rvalueref);
+         type = cp_build_reference_type (type, rval);
+         expr = build_static_cast (type, expr, tf_warning_or_error);
+       }
+    }
+
+  return expr;
+}
+
 /* Finish a parenthesized expression EXPR.  */
 
 tree
@@ -1525,6 +1557,8 @@ finish_parenthesized_expr (tree expr)
   if (TREE_CODE (expr) == STRING_CST)
     PAREN_STRING_LITERAL_P (expr) = 1;
 
+  expr = force_paren_expr (expr);
+
   return expr;
 }
 
diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn15.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn15.C
new file mode 100644 (file)
index 0000000..bab58a6
--- /dev/null
@@ -0,0 +1,50 @@
+// { dg-options "-std=c++1y -Wno-return-local-addr" }
+
+template<class,class> struct same_type;
+template<class T> struct same_type<T,T> {};
+
+int& f();
+int i;
+
+decltype(auto) g() { return f(); }
+decltype(auto) h1() { return i; }
+decltype(auto) h2() { return (i); }
+decltype(auto) h2a() { return 0,i; }
+
+struct A { int i; };
+A a;
+
+decltype(auto) h3() { return a.i; }
+decltype(auto) h4() { return (a.i); }
+
+template <class T>
+decltype(auto) h5(T t) { return t.i; }
+template <class T>
+decltype(auto) h6(T t) { return (t.i); }
+
+int main()
+{
+  decltype(auto) i = f();
+  same_type<decltype(i),int&>();
+  decltype(auto) i2 = i;
+  same_type<decltype(i2),int&>();
+  decltype(auto) i3 = ::i;
+  same_type<decltype(i3),int>();
+  decltype(auto) i4 = (::i);
+  same_type<decltype(i4),int&>();
+  decltype(auto) i5 = a.i;
+  same_type<decltype(i5),int>();
+  decltype(auto) i6 = (a.i);
+  same_type<decltype(i6),int&>();
+  decltype(auto) i7 = true ? ::i : ::i;
+  same_type<decltype(i7),int&>();
+
+  same_type<decltype(g()),int&>();
+  same_type<decltype(h1()),int>();
+  same_type<decltype(h2()),int&>();
+  same_type<decltype(h2a()),int&>();
+  same_type<decltype(h3()),int>();
+  same_type<decltype(h4()),int&>();
+  same_type<decltype(h5(a)),int>();
+  same_type<decltype(h6(a)),int&>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn16.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn16.C
new file mode 100644 (file)
index 0000000..5caec52
--- /dev/null
@@ -0,0 +1,12 @@
+// { dg-options -std=c++1y }
+
+template<class,class> struct ST;
+template<class T> struct ST<T,T> {};
+
+int j;
+auto x3 = []()->auto&& { return j; }; // OK: return type is int&
+
+int main()
+{
+  ST<decltype(x3()),int&>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/auto-fn17.C b/gcc/testsuite/g++.dg/cpp1y/auto-fn17.C
new file mode 100644 (file)
index 0000000..8bc961e
--- /dev/null
@@ -0,0 +1,22 @@
+// { dg-options -std=c++1y }
+// { dg-do run }
+
+int c;
+int d;
+
+struct A
+{
+  A() { ++c; }
+  A(const A&) { ++c; }
+  ~A() { ++d; }
+};
+
+A g() { return A(); }
+decltype(auto) f() { return g(); }
+
+int main()
+{
+  f();
+  if (c < 1 || c != d)
+    __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/mangle1.C b/gcc/testsuite/g++.dg/cpp1y/mangle1.C
new file mode 100644 (file)
index 0000000..b593a48
--- /dev/null
@@ -0,0 +1,13 @@
+// Test that the parens don't show up in the mangling
+// { dg-options "-std=c++1y -Wno-return-local-addr" }
+// { dg-final { scan-assembler "_Z1gI1AEDTdtfp_1iET_" } }
+
+struct A { int i; };
+
+template <class T>
+auto g(T t)->decltype((t.i)) { return t.i; }
+
+int main()
+{
+  g(A());
+}
This page took 0.101504 seconds and 5 git commands to generate.