Fix PR c++/69736
authorppalka <ppalka@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 25 Feb 2016 01:14:27 +0000 (01:14 +0000)
committerppalka <ppalka@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 25 Feb 2016 01:14:27 +0000 (01:14 +0000)
gcc/cp/ChangeLog:

PR c++/69736
* cp-tree.h (REF_PARENTHESIZED_P): Adjust documentation.
(maybe_undo_parenthesized_ref): Declare.
* semantics.c (maybe_undo_parenthesized_ref): Split out from
check_return_expr.
(finish_call_expr): Use it.
* typeck.c (check_return_expr): Use it.
* pt.c (tsubst_copy_and_build) [INDIRECT_REF]: Retain the
REF_PARENTHESIZED_P flag.

gcc/testsuite/ChangeLog:

PR c++/69736
* g++.dg/cpp1y/paren2.C: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@233691 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp1y/paren2.C [new file with mode: 0644]

index 28a3168..3ae4daf 100644 (file)
@@ -1,3 +1,15 @@
+2016-02-25  Patrick Palka  <ppalka@gcc.gnu.org>
+
+       PR c++/69736
+       * cp-tree.h (REF_PARENTHESIZED_P): Adjust documentation.
+       (maybe_undo_parenthesized_ref): Declare.
+       * semantics.c (maybe_undo_parenthesized_ref): Split out from
+       check_return_expr.
+       (finish_call_expr): Use it.
+       * typeck.c (check_return_expr): Use it.
+       * pt.c (tsubst_copy_and_build) [INDIRECT_REF]: Retain the
+       REF_PARENTHESIZED_P flag.
+
 2016-02-24  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/69922
index 3c23a83..88c6367 100644 (file)
@@ -3393,7 +3393,7 @@ extern void decl_shadowed_for_var_insert (tree, tree);
   TREE_LANG_FLAG_0 (STRING_CST_CHECK (NODE))
 
 /* Indicates whether a COMPONENT_REF has been parenthesized, or an
-   INDIRECT_REF comes from parenthesizing a VAR_DECL.  Currently only set
+   INDIRECT_REF comes from parenthesizing a _DECL.  Currently only set
    some of the time in C++14 mode.  */
 
 #define REF_PARENTHESIZED_P(NODE) \
@@ -6361,6 +6361,7 @@ extern tree finish_label_stmt                     (tree);
 extern void finish_label_decl                  (tree);
 extern cp_expr finish_parenthesized_expr       (cp_expr);
 extern tree force_paren_expr                   (tree);
+extern tree maybe_undo_parenthesized_ref       (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 e9cdf6e..cd3eb67 100644 (file)
@@ -15961,6 +15961,10 @@ tsubst_copy_and_build (tree t,
        else
          r = build_x_indirect_ref (input_location, r, RO_UNARY_STAR,
                                    complain|decltype_flag);
+
+       if (TREE_CODE (r) == INDIRECT_REF)
+         REF_PARENTHESIZED_P (r) = REF_PARENTHESIZED_P (t);
+
        RETURN (r);
       }
 
index c15b160..fad233a 100644 (file)
@@ -1673,6 +1673,30 @@ force_paren_expr (tree expr)
   return expr;
 }
 
+/* If T is an id-expression obfuscated by force_paren_expr, undo the
+   obfuscation and return the underlying id-expression.  Otherwise
+   return T.  */
+
+tree
+maybe_undo_parenthesized_ref (tree t)
+{
+  if (cxx_dialect >= cxx14
+      && INDIRECT_REF_P (t)
+      && REF_PARENTHESIZED_P (t))
+    {
+      t = TREE_OPERAND (t, 0);
+      while (TREE_CODE (t) == NON_LVALUE_EXPR
+            || TREE_CODE (t) == NOP_EXPR)
+       t = TREE_OPERAND (t, 0);
+
+      gcc_assert (TREE_CODE (t) == ADDR_EXPR
+                 || TREE_CODE (t) == STATIC_CAST_EXPR);
+      t = TREE_OPERAND (t, 0);
+    }
+
+  return t;
+}
+
 /* Finish a parenthesized expression EXPR.  */
 
 cp_expr
@@ -2256,6 +2280,10 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual,
 
   gcc_assert (!TYPE_P (fn));
 
+  /* If FN may be a FUNCTION_DECL obfuscated by force_paren_expr, undo
+     it so that we can tell this is a call to a known function.  */
+  fn = maybe_undo_parenthesized_ref (fn);
+
   orig_fn = fn;
 
   if (processing_template_decl)
index 5e62220..5145879 100644 (file)
@@ -8917,17 +8917,7 @@ check_return_expr (tree retval, bool *no_warning)
 
       /* If we had an id-expression obfuscated by force_paren_expr, we need
         to undo it so we can try to treat it as an rvalue below.  */
-      if (cxx_dialect >= cxx14
-         && INDIRECT_REF_P (retval)
-         && REF_PARENTHESIZED_P (retval))
-       {
-         retval = TREE_OPERAND (retval, 0);
-         while (TREE_CODE (retval) == NON_LVALUE_EXPR
-                || TREE_CODE (retval) == NOP_EXPR)
-           retval = TREE_OPERAND (retval, 0);
-         gcc_assert (TREE_CODE (retval) == ADDR_EXPR);
-         retval = TREE_OPERAND (retval, 0);
-       }
+      retval = maybe_undo_parenthesized_ref (retval);
 
       /* Under C++11 [12.8/32 class.copy], a returned lvalue is sometimes
         treated as an rvalue for the purposes of overload resolution to
index 712121f..5583807 100644 (file)
@@ -1,3 +1,8 @@
+2016-02-25  Patrick Palka  <ppalka@gcc.gnu.org>
+
+       PR c++/69736
+       * g++.dg/cpp1y/paren2.C: New test.
+
 2016-02-24  Martin Sebor  <msebor@redhat.com>
 
        PR c/51147
diff --git a/gcc/testsuite/g++.dg/cpp1y/paren2.C b/gcc/testsuite/g++.dg/cpp1y/paren2.C
new file mode 100644 (file)
index 0000000..b4a721f
--- /dev/null
@@ -0,0 +1,31 @@
+// PR c++/69736
+// { dg-do compile { target c++14 } }
+
+void fn1(bool = true)
+{
+  (fn1)();
+}
+
+template <typename T>
+void fn2(T a = true)
+{
+  (fn1)();
+}
+
+void foo ()
+{
+  (fn2<bool>)();
+}
+
+struct X
+{
+  static void fn3(bool = true)
+  {
+    (X::fn3)();
+  }
+
+  void fn4(bool = true)
+  {
+    (X::fn4)();
+  }
+};