[C++] PR c++/93324 - ICE with -Wall on constexpr if.

Message ID 20200119203448.957706-1-polacek@redhat.com
State New
Headers show
Series
  • [C++] PR c++/93324 - ICE with -Wall on constexpr if.
Related show

Commit Message

Marek Polacek Jan. 19, 2020, 8:34 p.m.
This is a crash with constexpr if, when trying to see if the call in
the if-statement is std::is_constant_evaluated.

cp_get_callee_fndecl_nofold can return NULL_TREE and fndecl_built_in_p
doesn't expect to get a null tree, so check FNDECL first.

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

	* semantics.c (is_std_constant_evaluated_p): Check fndecl.

	* g++.dg/cpp1z/constexpr-if33.C: New test.
---
 gcc/cp/semantics.c                          |  4 ++--
 gcc/testsuite/g++.dg/cpp1z/constexpr-if33.C | 16 ++++++++++++++++
 2 files changed, 18 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1z/constexpr-if33.C


base-commit: bcfc2227c556f2801a657ce3007374732baa8333
-- 
2.24.1

Comments

Jakub Jelinek Jan. 19, 2020, 9 p.m. | #1
On Sun, Jan 19, 2020 at 03:34:48PM -0500, Marek Polacek wrote:
> Bootstrapped/regtested on x86_64-linux, ok for trunk?

> 

> 	* semantics.c (is_std_constant_evaluated_p): Check fndecl.

> 

> 	* g++.dg/cpp1z/constexpr-if33.C: New test.

> ---

>  gcc/cp/semantics.c                          |  4 ++--

>  gcc/testsuite/g++.dg/cpp1z/constexpr-if33.C | 16 ++++++++++++++++

>  2 files changed, 18 insertions(+), 2 deletions(-)

>  create mode 100644 gcc/testsuite/g++.dg/cpp1z/constexpr-if33.C

> 

> diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c

> index 3669b247e34..9051a2863e0 100644

> --- a/gcc/cp/semantics.c

> +++ b/gcc/cp/semantics.c

> @@ -734,8 +734,8 @@ is_std_constant_evaluated_p (tree fn)

>      return false;

>  

>    tree fndecl = cp_get_callee_fndecl_nofold (fn);

> -  if (fndecl_built_in_p (fndecl, CP_BUILT_IN_IS_CONSTANT_EVALUATED,

> -			 BUILT_IN_FRONTEND))

> +  if (fndecl && fndecl_built_in_p (fndecl, CP_BUILT_IN_IS_CONSTANT_EVALUATED,

> +				   BUILT_IN_FRONTEND))

>      return true;

>  

>    if (!decl_in_std_namespace_p (fndecl))


Shouldn't it instead do
  if (fndecl == NULL_TREE)
    return false;
before the fndecl_built_in_p check?

While decl_in_std_namespace_p apparently will return false for NULL
argument, relying on that is werid.

	Jakub
Marek Polacek Jan. 19, 2020, 9:18 p.m. | #2
On Sun, Jan 19, 2020 at 10:00:42PM +0100, Jakub Jelinek wrote:
> On Sun, Jan 19, 2020 at 03:34:48PM -0500, Marek Polacek wrote:

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

> > 

> > 	* semantics.c (is_std_constant_evaluated_p): Check fndecl.

> > 

> > 	* g++.dg/cpp1z/constexpr-if33.C: New test.

> > ---

> >  gcc/cp/semantics.c                          |  4 ++--

> >  gcc/testsuite/g++.dg/cpp1z/constexpr-if33.C | 16 ++++++++++++++++

> >  2 files changed, 18 insertions(+), 2 deletions(-)

> >  create mode 100644 gcc/testsuite/g++.dg/cpp1z/constexpr-if33.C

> > 

> > diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c

> > index 3669b247e34..9051a2863e0 100644

> > --- a/gcc/cp/semantics.c

> > +++ b/gcc/cp/semantics.c

> > @@ -734,8 +734,8 @@ is_std_constant_evaluated_p (tree fn)

> >      return false;

> >  

> >    tree fndecl = cp_get_callee_fndecl_nofold (fn);

> > -  if (fndecl_built_in_p (fndecl, CP_BUILT_IN_IS_CONSTANT_EVALUATED,

> > -			 BUILT_IN_FRONTEND))

> > +  if (fndecl && fndecl_built_in_p (fndecl, CP_BUILT_IN_IS_CONSTANT_EVALUATED,

> > +				   BUILT_IN_FRONTEND))

> >      return true;

> >  

> >    if (!decl_in_std_namespace_p (fndecl))

> 

> Shouldn't it instead do

>   if (fndecl == NULL_TREE)

>     return false;

> before the fndecl_built_in_p check?

> 

> While decl_in_std_namespace_p apparently will return false for NULL

> argument, relying on that is werid.


Can do that, too.

-- >8 --
This is a crash with constexpr if, when trying to see if the call in
the if-statement is std::is_constant_evaluated.

cp_get_callee_fndecl_nofold can return NULL_TREE and fndecl_built_in_p
doesn't expect to get a null tree, so check FNDECL first.

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

	* semantics.c (is_std_constant_evaluated_p): Check fndecl.

	* g++.dg/cpp1z/constexpr-if33.C: New test.
---
 gcc/cp/semantics.c                          |  3 +++
 gcc/testsuite/g++.dg/cpp1z/constexpr-if33.C | 16 ++++++++++++++++
 2 files changed, 19 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp1z/constexpr-if33.C

diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 3669b247e34..3b88f1520bc 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -734,6 +734,9 @@ is_std_constant_evaluated_p (tree fn)
     return false;
 
   tree fndecl = cp_get_callee_fndecl_nofold (fn);
+  if (fndecl == NULL_TREE)
+    return false;
+
   if (fndecl_built_in_p (fndecl, CP_BUILT_IN_IS_CONSTANT_EVALUATED,
 			 BUILT_IN_FRONTEND))
     return true;
diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-if33.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-if33.C
new file mode 100644
index 00000000000..e5ef659932b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-if33.C
@@ -0,0 +1,16 @@
+// PR c++/93324 - ICE with -Wall on constexpr if.
+// { dg-do compile { target c++17 } }
+// { dg-options "-Wall" }
+
+struct {
+  template <int>
+  static constexpr bool a() { return 0; }
+} e;
+
+template <typename>
+void d()
+{
+  auto c(e);
+  using b = decltype(c);
+  if constexpr (b::a<2>());
+}

base-commit: bcfc2227c556f2801a657ce3007374732baa8333
-- 
2.24.1
Jason Merrill Jan. 22, 2020, 1:59 a.m. | #3
On 1/19/20 4:18 PM, Marek Polacek wrote:
> On Sun, Jan 19, 2020 at 10:00:42PM +0100, Jakub Jelinek wrote:

>> On Sun, Jan 19, 2020 at 03:34:48PM -0500, Marek Polacek wrote:

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

>>>

>>> 	* semantics.c (is_std_constant_evaluated_p): Check fndecl.

>>>

>>> 	* g++.dg/cpp1z/constexpr-if33.C: New test.

>>> ---

>>>   gcc/cp/semantics.c                          |  4 ++--

>>>   gcc/testsuite/g++.dg/cpp1z/constexpr-if33.C | 16 ++++++++++++++++

>>>   2 files changed, 18 insertions(+), 2 deletions(-)

>>>   create mode 100644 gcc/testsuite/g++.dg/cpp1z/constexpr-if33.C

>>>

>>> diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c

>>> index 3669b247e34..9051a2863e0 100644

>>> --- a/gcc/cp/semantics.c

>>> +++ b/gcc/cp/semantics.c

>>> @@ -734,8 +734,8 @@ is_std_constant_evaluated_p (tree fn)

>>>       return false;

>>>   

>>>     tree fndecl = cp_get_callee_fndecl_nofold (fn);

>>> -  if (fndecl_built_in_p (fndecl, CP_BUILT_IN_IS_CONSTANT_EVALUATED,

>>> -			 BUILT_IN_FRONTEND))

>>> +  if (fndecl && fndecl_built_in_p (fndecl, CP_BUILT_IN_IS_CONSTANT_EVALUATED,

>>> +				   BUILT_IN_FRONTEND))

>>>       return true;

>>>   

>>>     if (!decl_in_std_namespace_p (fndecl))

>>

>> Shouldn't it instead do

>>    if (fndecl == NULL_TREE)

>>      return false;

>> before the fndecl_built_in_p check?

>>

>> While decl_in_std_namespace_p apparently will return false for NULL

>> argument, relying on that is werid.

> 

> Can do that, too.

> 

> -- >8 --

> This is a crash with constexpr if, when trying to see if the call in

> the if-statement is std::is_constant_evaluated.

> 

> cp_get_callee_fndecl_nofold can return NULL_TREE and fndecl_built_in_p

> doesn't expect to get a null tree, so check FNDECL first.

> 

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


OK.

> 	* semantics.c (is_std_constant_evaluated_p): Check fndecl.

> 

> 	* g++.dg/cpp1z/constexpr-if33.C: New test.

> ---

>   gcc/cp/semantics.c                          |  3 +++

>   gcc/testsuite/g++.dg/cpp1z/constexpr-if33.C | 16 ++++++++++++++++

>   2 files changed, 19 insertions(+)

>   create mode 100644 gcc/testsuite/g++.dg/cpp1z/constexpr-if33.C

> 

> diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c

> index 3669b247e34..3b88f1520bc 100644

> --- a/gcc/cp/semantics.c

> +++ b/gcc/cp/semantics.c

> @@ -734,6 +734,9 @@ is_std_constant_evaluated_p (tree fn)

>       return false;

>   

>     tree fndecl = cp_get_callee_fndecl_nofold (fn);

> +  if (fndecl == NULL_TREE)

> +    return false;

> +

>     if (fndecl_built_in_p (fndecl, CP_BUILT_IN_IS_CONSTANT_EVALUATED,

>   			 BUILT_IN_FRONTEND))

>       return true;

> diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-if33.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-if33.C

> new file mode 100644

> index 00000000000..e5ef659932b

> --- /dev/null

> +++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-if33.C

> @@ -0,0 +1,16 @@

> +// PR c++/93324 - ICE with -Wall on constexpr if.

> +// { dg-do compile { target c++17 } }

> +// { dg-options "-Wall" }

> +

> +struct {

> +  template <int>

> +  static constexpr bool a() { return 0; }

> +} e;

> +

> +template <typename>

> +void d()

> +{

> +  auto c(e);

> +  using b = decltype(c);

> +  if constexpr (b::a<2>());

> +}

> 

> base-commit: bcfc2227c556f2801a657ce3007374732baa8333

>

Patch

diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 3669b247e34..9051a2863e0 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -734,8 +734,8 @@  is_std_constant_evaluated_p (tree fn)
     return false;
 
   tree fndecl = cp_get_callee_fndecl_nofold (fn);
-  if (fndecl_built_in_p (fndecl, CP_BUILT_IN_IS_CONSTANT_EVALUATED,
-			 BUILT_IN_FRONTEND))
+  if (fndecl && fndecl_built_in_p (fndecl, CP_BUILT_IN_IS_CONSTANT_EVALUATED,
+				   BUILT_IN_FRONTEND))
     return true;
 
   if (!decl_in_std_namespace_p (fndecl))
diff --git a/gcc/testsuite/g++.dg/cpp1z/constexpr-if33.C b/gcc/testsuite/g++.dg/cpp1z/constexpr-if33.C
new file mode 100644
index 00000000000..e5ef659932b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/constexpr-if33.C
@@ -0,0 +1,16 @@ 
+// PR c++/93324 - ICE with -Wall on constexpr if.
+// { dg-do compile { target c++17 } }
+// { dg-options "-Wall" }
+
+struct {
+  template <int>
+  static constexpr bool a() { return 0; }
+} e;
+
+template <typename>
+void d()
+{
+  auto c(e);
+  using b = decltype(c);
+  if constexpr (b::a<2>());
+}