On Tue, 23 Feb 2016, Patrick Palka wrote:

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.


Actually, this patch is also wrong since we later reject the function
call (fn1)() when we attempt to instantiate the enclosing template function
fn2<>.  Example:

    template <typename T>
    void fn2(T a)
    {
      (fn1)();
    }

    void foo ()
    {
      fn2<bool> (true);
    }

This happens because when processing_template_decl, in finish_call_expr we
build a non-dependent CALL_EXPR using the obfuscated orig_fn.  Then during
instantiation, when tsubst_copy_and_build rebuilds this INDIRECT_REF (which is
the orig_fn) it does not copy the REF_PARENTHESIZED_P flag to the newly built
INDIRECT_REF.  So in the subsequent call to finish_call_expr FN is no longer
considered to be a parenthesized ref so maybe_undo_parenthesized_ref becomes a
no-op.

So this can be fixed either by

1. making tsubst_copy_and_build retain the REF_PARENTHESIZED_P flag when
processing an INDIRECT_REF, or by

2. moving the call to maybe_undo_parenthesized_ref in finish_call_expr before
the assignment of orig_fn so that orig_fn will be un-obfuscated as well, or by

3. making tsubst_copy_and_build call maybe_undo_parenthesized_ref when
processing a CALL_EXPR.

I don't know which solution is better.

Reply via email to