This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH for c++/85032, rejects-valid with if constexpr in template


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))
+	       && 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-if17.C gcc/testsuite/g++.dg/cpp1z/constexpr-if17.C
index e69de29bb2d..56e108be4ad 100644
--- gcc/testsuite/g++.dg/cpp1z/constexpr-if17.C
+++ gcc/testsuite/g++.dg/cpp1z/constexpr-if17.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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]