Commit 1137001c by Patrick Palka

re PR c++/69736 ("error: too few arguments to function" in c++14 but not c++11)

Fix PR c++/69736

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.

From-SVN: r233691
parent a8b233b7
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
......
......@@ -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);
......
......@@ -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);
}
......
......@@ -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)
......
......@@ -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
......
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
......
// 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)();
}
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment