On Tue, 23 Feb 2016, Marek Polacek wrote:
On Tue, Feb 23, 2016 at 09:58:41AM -0500, Patrick Palka wrote:
finish_call_expr thinks that a call to a function which has been
obfuscated by force_paren_expr is a call to an unknown function. This
eventually leads us to not make use of the function's default arguments
when processing the argument list. So a function call like f() may
compile and yet (f)() may not, if f has defaulted arguments.
This patch fixes this inconsistency by making finish_call_expr undo the
obfuscation performed by force_paren_expr.
Thanks for the fix.
new file mode 100644
index 0000000..12462be
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/paren2.C
@@ -0,0 +1,25 @@
+// PR c++/69736
+
I'd expect
// { dg-do compile { target c++14 } }
here.
Okay.
+void fn1(bool = true)
+{
+ (fn1)();
+}
+
+template <typename>
+void fn2()
+{
+ (fn1)();
+}
The test seems to fail here though because of
testsuite/g++.dg/cpp1y/paren2.C:11:9: error: too few arguments to function
Why's that?
Oops... The call to maybe_undo_parenthesized_ref managed to mysteriously
move itself to the wrong place. It should be called before the
processing_template_decl logic, before FN gets wrapped in a
NON_DEPENDENT_EXPR.
Here's the updated patch, which I'm going to retest just in case.
-- >8 --
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.
gcc/testsuite/ChangeLog:
PR c++/69736
* g++.dg/cpp1y/paren2.C: New test.
---
gcc/cp/cp-tree.h | 3 ++-
gcc/cp/semantics.c | 28 ++++++++++++++++++++++++++++
gcc/cp/typeck.c | 12 +-----------
gcc/testsuite/g++.dg/cpp1y/paren2.C | 26 ++++++++++++++++++++++++++
4 files changed, 57 insertions(+), 12 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp1y/paren2.C
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 3c23a83a..88c6367 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 38c7516..e5ecf48 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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
@@ -2265,6 +2289,10 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool
disallow_virtual,
orig_fn = fn;
+ /* If FN is 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);
+
if (processing_template_decl)
{
/* If the call expression is dependent, build a CALL_EXPR node
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index d7ce327..3da6ea1 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -8929,17 +8929,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
diff --git a/gcc/testsuite/g++.dg/cpp1y/paren2.C
b/gcc/testsuite/g++.dg/cpp1y/paren2.C
new file mode 100644
index 0000000..56736b5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/paren2.C
@@ -0,0 +1,26 @@
+// PR c++/69736
+// { dg-do compile { target c++14 } }
+
+void fn1(bool = true)
+{
+ (fn1)();
+}
+
+template <typename>
+void fn2()
+{
+ (fn1)();
+}
+
+struct X
+{
+ static void fn3(bool = true)
+ {
+ (X::fn3)();
+ }
+
+ void fn4(bool = true)
+ {
+ (X::fn4)();
+ }
+};
--
2.7.1.348.gb763790