This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: C++ PATCH for c++/85032, rejects-valid with if constexpr in template
- From: Marek Polacek <polacek at redhat dot com>
- To: Jason Merrill <jason at redhat dot com>
- Cc: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 6 Apr 2018 14:17:59 -0400
- Subject: Re: C++ PATCH for c++/85032, rejects-valid with if constexpr in template
- References: <20180324105904.GA8748@redhat.com> <CADzB+2=wnxP=Fr11X3-pEgBs244ZoYNq69gvqektdNzSxxrhhA@mail.gmail.com>
On Mon, Mar 26, 2018 at 01:17:22PM -0400, Jason Merrill wrote:
> On Sat, Mar 24, 2018 at 6:59 AM, Marek Polacek <polacek@redhat.com> wrote:
> > Recently the code in finish_static_assert was changed to use
> > perform_implicit_conversion_flags followed by fold_non_dependent_expr. That
> > broke this test becase when in a template, p_i_c_f merely wraps the expr in
> > an IMPLICIT_CONV_EXPR. fold_non_dependent_expr should be able to fold it to
> > a constant but it gave up because is_nondependent_constant_expression returned
> > false. Jason suggested to fix this roughly like the following, i.e. consider
> > conversions from classes to literal types potentially constant.
> >
> > Bootstrapped/regtested on x86_64-linux, ok for trunk?
> >
> > 2018-03-24 Marek Polacek <polacek@redhat.com>
> >
> > PR c++/85032
> > * constexpr.c (potential_constant_expression_1): Consider conversions
> > from classes to literal types potentially constant.
> >
> > * g++.dg/cpp0x/pr51225.C: Adjust error message.
> > * g++.dg/cpp1z/constexpr-if17.C: New test.
> >
> > diff --git gcc/cp/constexpr.c gcc/cp/constexpr.c
> > index bebd9f5b5d0..c4b5afe90a2 100644
> > --- gcc/cp/constexpr.c
> > +++ gcc/cp/constexpr.c
> > @@ -5768,6 +5768,23 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
> > TREE_TYPE (t));
> > return false;
> > }
> > + /* This might be a conversion from a class to a literal type. Let's
> > + consider it potentially constant since the conversion might be
> > + a constexpr user-defined conversion. */
> > + else if (cxx_dialect >= cxx11
> > + && COMPLETE_TYPE_P (TREE_TYPE (t))
> > + && literal_type_p (TREE_TYPE (t))
>
> We probably need to allow dependent types here, too. And incomplete
> classes, which might turn out to be literal later.
Ok, I've allowed incomplete types, too. And I think the patch also allows
dependent types. Or did you mean using
&& (TREE_TYPE (t) == NULL_TREE
|| !COMPLETE_TYPE_P (TREE_TYPE (t))
|| literal_type_p (TREE_TYPE (t)))
? That doesn't seem to be needed.
Bootstrapped/regtested on x86_64-linux, ok for trunk?
2018-04-06 Marek Polacek <polacek@redhat.com>
PR c++/85032
* constexpr.c (potential_constant_expression_1): Consider conversions
from classes to literal types potentially constant.
* g++.dg/cpp0x/pr51225.C: Adjust error message.
* g++.dg/cpp1z/constexpr-if20.C: New test.
diff --git gcc/cp/constexpr.c gcc/cp/constexpr.c
index 3cc196b4d17..916060312f0 100644
--- gcc/cp/constexpr.c
+++ gcc/cp/constexpr.c
@@ -5777,6 +5777,23 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
TREE_TYPE (t));
return false;
}
+ /* This might be a conversion from a class to a (potentially) literal
+ type. Let's consider it potentially constant since the conversion
+ might be a constexpr user-defined conversion. */
+ else if (cxx_dialect >= cxx11
+ && (!COMPLETE_TYPE_P (TREE_TYPE (t))
+ || literal_type_p (TREE_TYPE (t)))
+ && TREE_OPERAND (t, 0))
+ {
+ tree type = TREE_TYPE (TREE_OPERAND (t, 0));
+ /* If this is a dependent type, it could end up being a class
+ with conversions. */
+ if (type == NULL_TREE || WILDCARD_TYPE_P (type))
+ return true;
+ /* Or a non-dependent class which has conversions. */
+ else if (CLASS_TYPE_P (type) && TYPE_HAS_CONVERSION (type))
+ return true;
+ }
return (RECUR (TREE_OPERAND (t, 0),
TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE));
diff --git gcc/testsuite/g++.dg/cpp0x/pr51225.C gcc/testsuite/g++.dg/cpp0x/pr51225.C
index f80bd0e778e..5b4e432f7ed 100644
--- gcc/testsuite/g++.dg/cpp0x/pr51225.C
+++ gcc/testsuite/g++.dg/cpp0x/pr51225.C
@@ -5,7 +5,7 @@ template<int> struct A {};
template<typename> void foo()
{
- A<int(x)> a; // { dg-error "not declared|invalid type" }
+ A<int(x)> a; // { dg-error "not declared|could not convert" }
}
template<typename> struct bar
diff --git gcc/testsuite/g++.dg/cpp1z/constexpr-if20.C gcc/testsuite/g++.dg/cpp1z/constexpr-if20.C
index e69de29bb2d..56e108be4ad 100644
--- gcc/testsuite/g++.dg/cpp1z/constexpr-if20.C
+++ gcc/testsuite/g++.dg/cpp1z/constexpr-if20.C
@@ -0,0 +1,22 @@
+// PR c++/85032
+// { dg-options -std=c++17 }
+
+struct A
+{
+ constexpr operator bool () { return true; }
+ int i;
+};
+
+A a;
+
+template <class T>
+void f()
+{
+ constexpr bool b = a;
+ static_assert (a);
+}
+
+int main()
+{
+ f<int>();
+}
Marek