diff mbox series

[C++] Fix std::is_constant_evaluated() in non-type template parameters (PR c++/88977)

Message ID 20190208231853.GH2135@tucnak
State New
Headers show
Series [C++] Fix std::is_constant_evaluated() in non-type template parameters (PR c++/88977) | expand

Commit Message

Jakub Jelinek Feb. 8, 2019, 11:18 p.m. UTC
Hi!

Non-type template arguments are constant-expression in the grammar and thus
manifestly constant-evaluated.
For e.g. class templates, convert_nontype_argument is called with
tf_warning_or_error and so while we called in the below spots
maybe_constant_value without manifestly_const_eval=true, there is a
      if (TREE_CODE (expr) != INTEGER_CST
          && !value_dependent_expression_p (expr))
        {
          if (complain & tf_error)
            {
              int errs = errorcount, warns = warningcount + werrorcount;
              if (!require_potential_constant_expression (expr))
                expr = error_mark_node;
              else
                expr = cxx_constant_value (expr);
later on and cxx_constant_value will do the manifestly_const_eval=true.
On the testcase below with function template, complain is tf_none and
so we only call that maybe_constant_value and not cxx_constant_value.

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
trunk?

2019-02-08  Jakub Jelinek  <jakub@redhat.com>

	PR c++/88977
	* pt.c (convert_nontype_argument): Pass true as manifestly_const_eval
	to maybe_constant_value calls.

	* g++.dg/cpp2a/is-constant-evaluated7.C: New test.


	Jakub

Comments

Jason Merrill Feb. 11, 2019, 7:55 p.m. UTC | #1
On 2/8/19 6:18 PM, Jakub Jelinek wrote:
> Hi!
> 
> Non-type template arguments are constant-expression in the grammar and thus
> manifestly constant-evaluated.
> For e.g. class templates, convert_nontype_argument is called with
> tf_warning_or_error and so while we called in the below spots
> maybe_constant_value without manifestly_const_eval=true, there is a
>        if (TREE_CODE (expr) != INTEGER_CST
>            && !value_dependent_expression_p (expr))
>          {
>            if (complain & tf_error)
>              {
>                int errs = errorcount, warns = warningcount + werrorcount;
>                if (!require_potential_constant_expression (expr))
>                  expr = error_mark_node;
>                else
>                  expr = cxx_constant_value (expr);
> later on and cxx_constant_value will do the manifestly_const_eval=true.
> On the testcase below with function template, complain is tf_none and
> so we only call that maybe_constant_value and not cxx_constant_value.
> 
> Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
> trunk?

OK.
diff mbox series

Patch

--- gcc/cp/pt.c.jj	2019-02-05 10:04:19.038028029 +0100
+++ gcc/cp/pt.c	2019-02-08 09:46:23.370257199 +0100
@@ -6821,12 +6821,14 @@  convert_nontype_argument (tree type, tre
 	    /* Make sure we return NULL_TREE only if we have really issued
 	       an error, as described above.  */
 	    return (complain & tf_error) ? NULL_TREE : error_mark_node;
-	  expr = maybe_constant_value (expr);
+	  expr = maybe_constant_value (expr, NULL_TREE,
+				       /*manifestly_const_eval=*/true);
 	  expr = convert_from_reference (expr);
 	}
       else if (TYPE_PTR_OR_PTRMEM_P (type))
 	{
-	  tree folded = maybe_constant_value (expr);
+	  tree folded = maybe_constant_value (expr, NULL_TREE,
+					      /*manifestly_const_eval=*/true);
 	  if (TYPE_PTR_P (type) ? integer_zerop (folded)
 	      : null_member_pointer_value_p (folded))
 	    expr = folded;
--- gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated7.C.jj	2019-02-08 09:53:47.255935430 +0100
+++ gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated7.C	2019-02-08 09:49:45.159957823 +0100
@@ -0,0 +1,18 @@ 
+// P0595R2
+// PR c++/88977
+// { dg-do compile { target c++11 } }
+
+namespace std {
+  constexpr inline bool
+  is_constant_evaluated () noexcept
+  {
+    return __builtin_is_constant_evaluated ();
+  }
+}
+
+template<bool B> constexpr bool foo () { return B; }
+
+constexpr bool x = foo<std::is_constant_evaluated ()> ();
+constexpr bool y = foo<__builtin_is_constant_evaluated ()> ();
+static_assert (x, "");
+static_assert (y, "");