diff mbox series

C++ PATCH for c++/89420 - ICE with CAST_EXPR in explicit-specifier

Message ID 20190221233543.GH20014@redhat.com
State New
Headers show
Series C++ PATCH for c++/89420 - ICE with CAST_EXPR in explicit-specifier | expand

Commit Message

Marek Polacek Feb. 21, 2019, 11:35 p.m. UTC
We were ICEing because we called build_converted_constant_expr on an expression
that wasn't value-dependent, but it still contained template codes, and that
didn't work too well because check_narrowing calls maybe_constant_value.  The
fix is to instantiate the expression before converting it.  I guess let's also
use 'complain'.

Also, when calling value_dependent_expression_p, we don't have to check
processing_template_decl beforehand.

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

2019-02-21  Marek Polacek  <polacek@redhat.com>

	PR c++/89420 - ICE with CAST_EXPR in explicit-specifier.
	* decl.c (build_explicit_specifier): Don't check
	processing_template_decl.  Call instantiate_non_dependent_expr_sfinae
	before build_converted_constant_expr instead of calling
	instantiate_non_dependent_expr after it.

	* g++.dg/cpp2a/explicit14.C: New test.

Comments

Jason Merrill Feb. 22, 2019, 1:47 a.m. UTC | #1
On 2/21/19 1:35 PM, Marek Polacek wrote:
> We were ICEing because we called build_converted_constant_expr on an expression
> that wasn't value-dependent, but it still contained template codes, and that
> didn't work too well because check_narrowing calls maybe_constant_value.

Hmm, I'm concerned about convert_like_real from 
build_converted_constant_expr adding more template codes; you probably 
want a processing_template_decl_sentinel after the 
instantiate_non_dependent_expr.

Also, value_dependent_expression_p should probably be 
instantiation_dependent_expression_p.

Jason
Marek Polacek Feb. 22, 2019, 4:11 p.m. UTC | #2
On Thu, Feb 21, 2019 at 03:47:44PM -1000, Jason Merrill wrote:
> On 2/21/19 1:35 PM, Marek Polacek wrote:
> > We were ICEing because we called build_converted_constant_expr on an expression
> > that wasn't value-dependent, but it still contained template codes, and that
> > didn't work too well because check_narrowing calls maybe_constant_value.
> 
> Hmm, I'm concerned about convert_like_real from
> build_converted_constant_expr adding more template codes; you probably want
> a processing_template_decl_sentinel after the
> instantiate_non_dependent_expr.

OK, that's a good trick.

> Also, value_dependent_expression_p should probably be
> instantiation_dependent_expression_p.

I think I used value_* because that's what build_noexcept_spec had.  Also
value_dependent_expression_p calls type_dependent_expression_p.  But I've
changed it anyway.  Thanks,

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

2019-02-22  Marek Polacek  <polacek@redhat.com>

	PR c++/89420 - ICE with CAST_EXPR in explicit-specifier.
	* decl.c (build_explicit_specifier): Don't check
	processing_template_decl.  Call instantiation_dependent_expression_p
	instead of value_dependent_expression_p.  Call
	instantiate_non_dependent_expr_sfinae before
	build_converted_constant_expr instead of calling
	instantiate_non_dependent_expr after it.  Add
	processing_template_decl_sentinel.

	* g++.dg/cpp2a/explicit14.C: New test.

diff --git gcc/cp/decl.c gcc/cp/decl.c
index 612afbacd27..c5b5bd3ce08 100644
--- gcc/cp/decl.c
+++ gcc/cp/decl.c
@@ -16687,12 +16687,14 @@ require_deduced_type (tree decl, tsubst_flags_t complain)
 tree
 build_explicit_specifier (tree expr, tsubst_flags_t complain)
 {
-  if (processing_template_decl && value_dependent_expression_p (expr))
+  if (instantiation_dependent_expression_p (expr))
     /* Wait for instantiation, tsubst_function_decl will handle it.  */
     return expr;
 
+  expr = instantiate_non_dependent_expr_sfinae (expr, complain);
+  /* Don't let convert_like_real create more template codes.  */
+  processing_template_decl_sentinel s;
   expr = build_converted_constant_expr (boolean_type_node, expr, complain);
-  expr = instantiate_non_dependent_expr (expr);
   expr = cxx_constant_value (expr);
   return expr;
 }
diff --git gcc/testsuite/g++.dg/cpp2a/explicit14.C gcc/testsuite/g++.dg/cpp2a/explicit14.C
new file mode 100644
index 00000000000..9c3acc32ac4
--- /dev/null
+++ gcc/testsuite/g++.dg/cpp2a/explicit14.C
@@ -0,0 +1,11 @@
+// PR c++/89420
+// { dg-do compile { target c++2a } }
+
+template<typename>
+struct S {
+  explicit(int(1)) S(int);
+  explicit(int{1}) S(int, int);
+};
+
+S<int> s(1);
+S<int> s2(1, 2);
Jason Merrill Feb. 22, 2019, 7:19 p.m. UTC | #3
OK, thanks.

Jason

On Fri, Feb 22, 2019 at 6:11 AM Marek Polacek <polacek@redhat.com> wrote:
>
> On Thu, Feb 21, 2019 at 03:47:44PM -1000, Jason Merrill wrote:
> > On 2/21/19 1:35 PM, Marek Polacek wrote:
> > > We were ICEing because we called build_converted_constant_expr on an expression
> > > that wasn't value-dependent, but it still contained template codes, and that
> > > didn't work too well because check_narrowing calls maybe_constant_value.
> >
> > Hmm, I'm concerned about convert_like_real from
> > build_converted_constant_expr adding more template codes; you probably want
> > a processing_template_decl_sentinel after the
> > instantiate_non_dependent_expr.
>
> OK, that's a good trick.
>
> > Also, value_dependent_expression_p should probably be
> > instantiation_dependent_expression_p.
>
> I think I used value_* because that's what build_noexcept_spec had.  Also
> value_dependent_expression_p calls type_dependent_expression_p.  But I've
> changed it anyway.  Thanks,
>
> Bootstrapped/regtested on x86_64-linux, ok for trunk?
>
> 2019-02-22  Marek Polacek  <polacek@redhat.com>
>
>         PR c++/89420 - ICE with CAST_EXPR in explicit-specifier.
>         * decl.c (build_explicit_specifier): Don't check
>         processing_template_decl.  Call instantiation_dependent_expression_p
>         instead of value_dependent_expression_p.  Call
>         instantiate_non_dependent_expr_sfinae before
>         build_converted_constant_expr instead of calling
>         instantiate_non_dependent_expr after it.  Add
>         processing_template_decl_sentinel.
>
>         * g++.dg/cpp2a/explicit14.C: New test.
>
> diff --git gcc/cp/decl.c gcc/cp/decl.c
> index 612afbacd27..c5b5bd3ce08 100644
> --- gcc/cp/decl.c
> +++ gcc/cp/decl.c
> @@ -16687,12 +16687,14 @@ require_deduced_type (tree decl, tsubst_flags_t complain)
>  tree
>  build_explicit_specifier (tree expr, tsubst_flags_t complain)
>  {
> -  if (processing_template_decl && value_dependent_expression_p (expr))
> +  if (instantiation_dependent_expression_p (expr))
>      /* Wait for instantiation, tsubst_function_decl will handle it.  */
>      return expr;
>
> +  expr = instantiate_non_dependent_expr_sfinae (expr, complain);
> +  /* Don't let convert_like_real create more template codes.  */
> +  processing_template_decl_sentinel s;
>    expr = build_converted_constant_expr (boolean_type_node, expr, complain);
> -  expr = instantiate_non_dependent_expr (expr);
>    expr = cxx_constant_value (expr);
>    return expr;
>  }
> diff --git gcc/testsuite/g++.dg/cpp2a/explicit14.C gcc/testsuite/g++.dg/cpp2a/explicit14.C
> new file mode 100644
> index 00000000000..9c3acc32ac4
> --- /dev/null
> +++ gcc/testsuite/g++.dg/cpp2a/explicit14.C
> @@ -0,0 +1,11 @@
> +// PR c++/89420
> +// { dg-do compile { target c++2a } }
> +
> +template<typename>
> +struct S {
> +  explicit(int(1)) S(int);
> +  explicit(int{1}) S(int, int);
> +};
> +
> +S<int> s(1);
> +S<int> s2(1, 2);
diff mbox series

Patch

diff --git gcc/cp/decl.c gcc/cp/decl.c
index 612afbacd27..83e2b3efa44 100644
--- gcc/cp/decl.c
+++ gcc/cp/decl.c
@@ -16687,12 +16687,12 @@  require_deduced_type (tree decl, tsubst_flags_t complain)
 tree
 build_explicit_specifier (tree expr, tsubst_flags_t complain)
 {
-  if (processing_template_decl && value_dependent_expression_p (expr))
+  if (value_dependent_expression_p (expr))
     /* Wait for instantiation, tsubst_function_decl will handle it.  */
     return expr;
 
+  expr = instantiate_non_dependent_expr_sfinae (expr, complain);
   expr = build_converted_constant_expr (boolean_type_node, expr, complain);
-  expr = instantiate_non_dependent_expr (expr);
   expr = cxx_constant_value (expr);
   return expr;
 }
diff --git gcc/testsuite/g++.dg/cpp2a/explicit14.C gcc/testsuite/g++.dg/cpp2a/explicit14.C
new file mode 100644
index 00000000000..9c3acc32ac4
--- /dev/null
+++ gcc/testsuite/g++.dg/cpp2a/explicit14.C
@@ -0,0 +1,11 @@ 
+// PR c++/89420
+// { dg-do compile { target c++2a } }
+
+template<typename>
+struct S {
+  explicit(int(1)) S(int);
+  explicit(int{1}) S(int, int);
+};
+
+S<int> s(1);
+S<int> s2(1, 2);