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.
+}