When r265789 changed instantiation_dependent_r in such a way that
TEMPLATE_PARM_INDEXes are instantiation-dependent only when their
types are dependent, it broke this test.  The test uses a combination
of SFINAE and narrow conversions to detect if an expression is constexpr.
"p" is a template parameter whose type is not dependent, so now it's not
considered instantiation-dependent.

The problem is that when finish_decltype_type sees something that isn't
instantiation_dependent_uneval_expression_p, it just looks at the type
of the expression and lets it go.  But it misses a narrowing conversion in

  decltype(int{(p(), 0U)})

which is narrowing or not depending on if p() is constant.  To figure that
out we need to create a DECLTYPE_TYPE so that we actually instantiate the
expression.

The question is what, specifically, should we check in
instantiation_dependent_r.  I went with checking if a compound literal has
something value dependent, then we need to instantion so as not to lose
a possible narrowing conversion.

In a non-SFINAE context we don't give any narrowing warnings, that's a bug
I have another patch for, but it's not dependent on this patch.  Though I
can imagine there's a patch fixing both these cases.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2019-01-17  Marek Polacek  <pola...@redhat.com>

        PR c++/88815 - narrowing conversion lost in decltype.
        * pt.c (instantiation_dependent_r): Consider a compound literal
        with a value-dependent expression dependent.

        * g++.dg/cpp0x/constexpr-decltype3.C: New test.

diff --git gcc/cp/pt.c gcc/cp/pt.c
index e4f76478f54..d0f5dbeec8e 100644
--- gcc/cp/pt.c
+++ gcc/cp/pt.c
@@ -25800,6 +25800,14 @@ instantiation_dependent_r (tree *tp, int 
*walk_subtrees,
        return *tp;
       break;
 
+    case CONSTRUCTOR:
+      /* A compound literal with a value-dependent expression
+        might contain narrowing conversion.  */
+      if (TREE_HAS_CONSTRUCTOR (*tp)
+         && value_dependent_expression_p (*tp))
+       return *tp;
+      break;
+
     default:
       break;
     }
diff --git gcc/testsuite/g++.dg/cpp0x/constexpr-decltype3.C 
gcc/testsuite/g++.dg/cpp0x/constexpr-decltype3.C
new file mode 100644
index 00000000000..fd05366de50
--- /dev/null
+++ gcc/testsuite/g++.dg/cpp0x/constexpr-decltype3.C
@@ -0,0 +1,25 @@
+// PR c++/88815
+// { dg-do compile { target c++11 } }
+
+struct true_type {
+    constexpr operator bool() const { return true; }
+};
+
+struct false_type {
+    constexpr operator bool() const { return false; }
+};
+
+template<int (*p)()>
+true_type is_constexpr_impl(decltype(int{(p(), 0U)}));
+
+template<int (*p)()>
+false_type is_constexpr_impl(...);
+
+template<int (*p)()>
+using is_constexpr = decltype(is_constexpr_impl<p>(0));
+
+constexpr int f() { return 0; }
+int g() { return 0; }
+
+static_assert(is_constexpr<f>(), "");
+static_assert(!is_constexpr<g>(), "");

Reply via email to