Another issue raised in 49813 is that morally_constexpr_builtin_function_p was rejecting __builtin_isinf because it has a variadic signature. I'm changing potential_constant_expression_1 to just allow any built-in function in a constexpr function; if it doesn't expand to a constant, we'll deal with that when we actually expand it.

Tested x86_64-pc-linux-gnu, applying to trunk.

commit e2a2b30a8008b9f2d21e19bb2fd73776dbf89576
Author: Jason Merrill <ja...@redhat.com>
Date:   Mon Aug 1 11:49:09 2011 -0400

    	PR c++/49813
    	* semantics.c (potential_constant_expression_1): Allow any builtin.
    	(morally_constexpr_builtin_function_p): Remove.

diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index c44c0ef..47b714f 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -7523,32 +7523,6 @@ check_automatic_or_tls (tree ref)
 }
 #endif
 
-/* Return true if the DECL designates a builtin function that is
-   morally constexpr, in the sense that its parameter types and
-   return type are literal types and the compiler is allowed to
-   fold its invocations.  */
-
-static bool
-morally_constexpr_builtin_function_p (tree decl)
-{
-  tree funtype = TREE_TYPE (decl);
-  tree t;
-
-  if (!is_builtin_fn (decl))
-    return false;
-  if (!literal_type_p (TREE_TYPE (funtype)))
-    return false;
-  for (t = TYPE_ARG_TYPES (funtype); t != NULL ; t = TREE_CHAIN (t))
-    {
-      if (t == void_list_node)
-        return true;
-      if (!literal_type_p (TREE_VALUE (t)))
-        return false;
-    }
-  /* We assume no varargs builtins are suitable.  */
-  return t != NULL;
-}
-
 /* Return true if T denotes a potentially constant expression.  Issue
    diagnostic as appropriate under control of FLAGS.  If WANT_RVAL is true,
    an lvalue-rvalue conversion is implied.
@@ -7656,7 +7630,9 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
 		if (builtin_valid_in_constant_expr_p (fun))
 		  return true;
 		if (!DECL_DECLARED_CONSTEXPR_P (fun)
-		    && !morally_constexpr_builtin_function_p (fun))
+		    /* Allow any built-in function; if the expansion
+		       isn't constant, we'll deal with that then.  */
+		    && !is_builtin_fn (fun))
 		  {
 		    if (flags & tf_error)
 		      {
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-builtin1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-builtin1.C
new file mode 100644
index 0000000..b3f5576
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-builtin1.C
@@ -0,0 +1,25 @@
+// PR c++/49813
+// { dg-options -std=c++0x }
+
+inline constexpr bool
+isinf(long double __x)
+{ return __builtin_isinf(__x); }
+
+inline constexpr bool
+isinf(double __x)
+{ return __builtin_isinf(__x); }
+
+inline constexpr bool
+isnan(long double __x)
+{ return __builtin_isnan(__x); }
+
+int main()
+{
+  constexpr long double num1 = __builtin_isinf(1.l); // Ok.
+
+  constexpr long double num2 = isinf(1.l);           // Error.
+
+  constexpr double      num3 = isinf(1.);            // Ok.
+
+  constexpr long double num4 = isnan(1.l);           // Ok.
+}

Reply via email to