Hi!

This is the implementation of __builtin_early_constant_p builtin which
is at all optimization levels quite similar to __builtin_constant_p
at -O0, except that the FE folding might be slightly different between -O0
and -O1+.  In any case, the builtin is folded to 0 already during the FEs
if the argument can't be proven constant or non-constant, like with
__builtin_constant_p at -O0.
The users can use it for stuff where __builtin_constant_p doesn't really
work (e.g. the kernel ilog2 case), for e.g. C macro constexpr-like
programming.

Is this ok for stage1, or do you find it not useful at all?

In any case, bootstrapped/regtested on x86_64-linux and i686-linux.

2018-03-07  Jakub Jelinek  <ja...@redhat.com>

        PR c++/78420
        * builtins.def (BUILT_IN_EARLY_CONSTANT_P): New built-in.
        * builtins.h (force_folding_builtin_constant_p): Change from bool to
        int.
        * builtins.c (force_folding_builtin_constant_p): Likewise.
        (expand_builtin): Handle BUILT_IN_EARLY_CONSTANT_P like
        BUILT_IN_CONSTANT_P.
        (fold_builtin_constant_p): Check force_folding_builtin_constant_p > 0
        instead of force_folding_builtin_constant_p.
        (fold_builtin_1) <case BUILT_IN_CONSTANT_P>: Don't return
        integer_zero_node if force_folding_builtin_constant_p < 0.
        <case BUILT_IN_EARLY_CONSTANT_P>: New case.
        (is_simple_builtin): Handle BUILT_IN_EARLY_CONSTANT_P like
        BUILT_IN_CONSTANT_P.
        * doc/extend.texi (__builtin_early_constant_p): Document.
c-family/
        * c-common.c (check_builtin_function_arguments): Handle
        BUILT_IN_EARLY_CONSTANT_P like BUILT_IN_CONSTANT_P.
c/
        * c-parser.c (c_parser_get_builtin_args): Adjust for
        force_folding_builtin_constant_p now being int rather than bool.
cp/
        * cp-tree.h (DECL_IS_BUILTIN_CONSTANT_P): Handle
        BUILT_IN_EARLY_CONSTANT_P like BUILT_IN_CONSTANT_P.
        * call.c (magic_varargs_p): Likewise.
        * tree.c (builtin_valid_in_constant_expr_p): Likewise.
        * constexpr.c (cxx_eval_builtin_function_call): Likewise.
        Adjust for force_folding_builtin_constant_p now being int rather than
        bool.
        * cp-gimplify.c: Include builtins.h.
        (cp_fold): For __builtin*_constant_p adjust temporarily
        force_folding_builtin_constant_p rather than optimize.
testsuite/
        * g++.dg/delayedfold/builtin-constant4.C: New test.
        * g++.dg/delayedfold/builtin-constant3.C: New test.
        * g++.dg/ext/builtin14.C: New test.
        * g++.dg/ext/builtin12.C: New test.
        * g++.dg/ext/builtin13.C: New test.
        * g++.dg/cpp1y/constexpr-78420.C: New test.
        * g++.dg/cpp0x/constexpr-builtin5.C: New test.
        * g++.dg/cpp0x/constexpr-builtin4.C: New test.
        * gcc.dg/torture/pr78420.c: New test.

--- gcc/builtins.def.jj 2018-01-03 10:19:55.103533949 +0100
+++ gcc/builtins.def    2018-03-07 15:55:20.756617250 +0100
@@ -857,6 +857,7 @@ DEF_EXT_LIB_BUILTIN    (BUILT_IN_DCGETTE
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_DGETTEXT, "dgettext", 
BT_FN_STRING_CONST_STRING_CONST_STRING, ATTR_FORMAT_ARG_2)
 DEF_GCC_BUILTIN        (BUILT_IN_DWARF_CFA, "dwarf_cfa", BT_FN_PTR, ATTR_NULL)
 DEF_GCC_BUILTIN        (BUILT_IN_DWARF_SP_COLUMN, "dwarf_sp_column", 
BT_FN_UINT, ATTR_NULL)
+DEF_GCC_BUILTIN        (BUILT_IN_EARLY_CONSTANT_P, "early_constant_p", 
BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_EH_RETURN, "eh_return", 
BT_FN_VOID_PTRMODE_PTR, ATTR_NORETURN_NOTHROW_LEAF_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_EH_RETURN_DATA_REGNO, "eh_return_data_regno", 
BT_FN_INT_INT, ATTR_LEAF_LIST)
 DEF_EXT_LIB_BUILTIN        (BUILT_IN_EXECL, "execl", 
BT_FN_INT_CONST_STRING_CONST_STRING_VAR, ATTR_SENTINEL_NOTHROW_LIST)
--- gcc/builtins.h.jj   2018-01-04 00:43:16.103702766 +0100
+++ gcc/builtins.h      2018-03-07 16:31:54.898348803 +0100
@@ -46,8 +46,10 @@ extern struct target_builtins *this_targ
 #define this_target_builtins (&default_target_builtins)
 #endif
 
-/* Non-zero if __builtin_constant_p should be folded right away.  */
-extern bool force_folding_builtin_constant_p;
+/* 1 if __builtin_{,early_}constant_p should be folded right away,
+   -1 if __builtin_{,early_}constant_p should not be folded to 0 when
+   fold_builtin_constant_p returned NULL.  */
+extern int force_folding_builtin_constant_p;
 
 extern bool is_builtin_fn (tree);
 extern bool called_as_built_in (tree);
--- gcc/builtins.c.jj   2018-02-19 20:35:54.418015330 +0100
+++ gcc/builtins.c      2018-03-07 16:32:12.326353626 +0100
@@ -91,8 +91,10 @@ const char * built_in_names[(int) END_BU
    initialized to NULL_TREE.  */
 builtin_info_type builtin_info[(int)END_BUILTINS];
 
-/* Non-zero if __builtin_constant_p should be folded right away.  */
-bool force_folding_builtin_constant_p;
+/* 1 if __builtin_{,early_}constant_p should be folded right away,
+   -1 if __builtin_{,early_}constant_p should not be folded to 0 when
+   fold_builtin_constant_p returned NULL.  */
+int force_folding_builtin_constant_p;
 
 static rtx c_readstr (const char *, scalar_int_mode);
 static int target_char_cast (tree, char *);
@@ -6872,6 +6874,7 @@ expand_builtin (tree exp, rtx target, rt
       return expand_builtin_classify_type (exp);
 
     case BUILT_IN_CONSTANT_P:
+    case BUILT_IN_EARLY_CONSTANT_P:
       return const0_rtx;
 
     case BUILT_IN_FRAME_ADDRESS:
@@ -7932,7 +7935,7 @@ fold_builtin_constant_p (tree arg)
       || POINTER_TYPE_P (TREE_TYPE (arg))
       || cfun == 0
       || folding_initializer
-      || force_folding_builtin_constant_p)
+      || force_folding_builtin_constant_p > 0)
     return integer_zero_node;
 
   return NULL_TREE;
@@ -8966,12 +8969,21 @@ fold_builtin_1 (location_t loc, tree fnd
        /* Gimplification will pull the CALL_EXPR for the builtin out of
           an if condition.  When not optimizing, we'll not CSE it back.
           To avoid link error types of regressions, return false now.  */
-       if (!val && !optimize)
+       if (!val && !optimize && force_folding_builtin_constant_p >= 0)
          val = integer_zero_node;
 
        return val;
       }
 
+    case BUILT_IN_EARLY_CONSTANT_P:
+      /* Like __builtin_constant_p, but always behave like that builtin
+        behaves at -O0.  */
+      if (tree val = fold_builtin_constant_p (arg0))
+       return val;
+      if (force_folding_builtin_constant_p >= 0)
+       return integer_zero_node;
+      return NULL_TREE;
+
     case BUILT_IN_CLASSIFY_TYPE:
       return fold_builtin_classify_type (arg0);
 
@@ -10576,6 +10588,7 @@ is_simple_builtin (tree decl)
       {
        /* Builtins that expand to constants.  */
       case BUILT_IN_CONSTANT_P:
+      case BUILT_IN_EARLY_CONSTANT_P:
       case BUILT_IN_EXPECT:
       case BUILT_IN_OBJECT_SIZE:
       case BUILT_IN_UNREACHABLE:
--- gcc/doc/extend.texi.jj      2018-02-22 22:25:53.312995803 +0100
+++ gcc/doc/extend.texi 2018-03-07 18:16:36.870891566 +0100
@@ -11924,6 +11924,17 @@ built-in in this case, because it has no
 optimization.
 @end deftypefn
 
+@deftypefn {Built-in Function} int __builtin_early_constant_p (@var{exp})
+This built-in function is like @code{__builtin_constant_p} when used in
+static initializers or C++ @code{constexpr} contexts, in other contexts
+it acts similarly to @code{__builtin_constant_p} at @option{-O0}, in that
+if the argument after folding is proven a constant, it returns 1, otherwise
+it returns 0.  If the argument needs function inlining and/or constant
+propagation, or other inter-statement optimizations in order to be proven
+constant, @code{__builtin_early_constant_p} will return 0 while
+@code{__builtin_constant_p} might still return 1.
+@end deftypefn
+
 @deftypefn {Built-in Function} long __builtin_expect (long @var{exp}, long 
@var{c})
 @opindex fprofile-arcs
 You may use @code{__builtin_expect} to provide the compiler with
--- gcc/c/c-parser.c.jj 2018-03-06 21:56:59.043571905 +0100
+++ gcc/c/c-parser.c    2018-03-07 16:33:47.927380098 +0100
@@ -7449,7 +7449,7 @@ c_parser_get_builtin_args (c_parser *par
   location_t loc = c_parser_peek_token (parser)->location;
   vec<c_expr_t, va_gc> *cexpr_list;
   c_expr_t expr;
-  bool saved_force_folding_builtin_constant_p;
+  int saved_force_folding_builtin_constant_p;
 
   *ret_cexpr_list = NULL;
   if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
@@ -7469,7 +7469,8 @@ c_parser_get_builtin_args (c_parser *par
 
   saved_force_folding_builtin_constant_p
     = force_folding_builtin_constant_p;
-  force_folding_builtin_constant_p |= choose_expr_p;
+  if (choose_expr_p)
+    force_folding_builtin_constant_p = 1;
   expr = c_parser_expr_no_commas (parser, NULL);
   force_folding_builtin_constant_p
     = saved_force_folding_builtin_constant_p;
@@ -9160,7 +9161,9 @@ c_parser_postfix_expression_after_primar
          if (TREE_CODE (expr.value) == INTEGER_CST
              && TREE_CODE (orig_expr.value) == FUNCTION_DECL
              && DECL_BUILT_IN_CLASS (orig_expr.value) == BUILT_IN_NORMAL
-             && DECL_FUNCTION_CODE (orig_expr.value) == BUILT_IN_CONSTANT_P)
+             && (DECL_FUNCTION_CODE (orig_expr.value) == BUILT_IN_CONSTANT_P
+                 || (DECL_FUNCTION_CODE (orig_expr.value)
+                     == BUILT_IN_EARLY_CONSTANT_P)))
            expr.original_code = C_MAYBE_CONST_EXPR;
          expr.original_type = NULL;
          if (exprlist)
--- gcc/c-family/c-common.c.jj  2018-01-17 22:00:12.041228270 +0100
+++ gcc/c-family/c-common.c     2018-03-07 15:58:18.350661272 +0100
@@ -5790,6 +5790,7 @@ check_builtin_function_arguments (locati
       }
 
     case BUILT_IN_CONSTANT_P:
+    case BUILT_IN_EARLY_CONSTANT_P:
       return builtin_function_validate_nargs (loc, fndecl, nargs, 1);
 
     case BUILT_IN_ISFINITE:
--- gcc/cp/cp-tree.h.jj 2018-03-02 00:15:54.099781049 +0100
+++ gcc/cp/cp-tree.h    2018-03-07 16:00:32.795694600 +0100
@@ -2846,11 +2846,13 @@ struct GTY(()) lang_decl {
 #define DECL_HAS_IN_CHARGE_PARM_P(NODE) \
   (LANG_DECL_FN_CHECK (NODE)->has_in_charge_parm_p)
 
-/* Nonzero if DECL is a declaration of __builtin_constant_p.  */
+/* Nonzero if DECL is a declaration of __builtin_{,early_}constant_p.  */
 #define DECL_IS_BUILTIN_CONSTANT_P(NODE)               \
  (TREE_CODE (NODE) == FUNCTION_DECL                    \
   && DECL_BUILT_IN_CLASS (NODE) == BUILT_IN_NORMAL     \
-  && DECL_FUNCTION_CODE (NODE) == BUILT_IN_CONSTANT_P)
+  && (DECL_FUNCTION_CODE (NODE) == BUILT_IN_CONSTANT_P \
+      || (DECL_FUNCTION_CODE (NODE)                    \
+         == BUILT_IN_EARLY_CONSTANT_P)))
 
 /* Nonzero for _DECL means that this decl appears in (or will appear
    in) as a member in a RECORD_TYPE or UNION_TYPE node.  It is also for
--- gcc/cp/constexpr.c.jj       2018-03-07 10:11:42.758757442 +0100
+++ gcc/cp/constexpr.c  2018-03-07 16:35:25.906407232 +0100
@@ -1168,8 +1168,10 @@ cxx_eval_builtin_function_call (const co
   tree new_call;
   int i;
 
-  /* Don't fold __builtin_constant_p within a constexpr function.  */
-  bool bi_const_p = (DECL_FUNCTION_CODE (fun) == BUILT_IN_CONSTANT_P);
+  /* Don't fold __builtin_{,early_}constant_p within a constexpr function.  */
+  bool bi_const_p
+    = (DECL_FUNCTION_CODE (fun) == BUILT_IN_CONSTANT_P
+       || DECL_FUNCTION_CODE (fun) == BUILT_IN_EARLY_CONSTANT_P);
 
   if (bi_const_p
       && current_function_decl
@@ -1179,8 +1181,8 @@ cxx_eval_builtin_function_call (const co
       return t;
     }
 
-  /* Be permissive for arguments to built-ins; __builtin_constant_p should
-     return constant false for a non-constant argument.  */
+  /* Be permissive for arguments to built-ins; __builtin_{,early_}constant_p
+     should return constant false for a non-constant argument.  */
   constexpr_ctx new_ctx = *ctx;
   new_ctx.quiet = true;
   bool dummy1 = false, dummy2 = false;
@@ -1189,13 +1191,13 @@ cxx_eval_builtin_function_call (const co
       args[i] = cxx_eval_constant_expression (&new_ctx, CALL_EXPR_ARG (t, i),
                                              false, &dummy1, &dummy2);
       if (bi_const_p)
-       /* For __built_in_constant_p, fold all expressions with constant values
-          even if they aren't C++ constant-expressions.  */
+       /* For __built_in_{,early_}constant_p, fold all expressions with
+          constant values even if they aren't C++ constant-expressions.  */
        args[i] = cp_fully_fold (args[i]);
     }
 
-  bool save_ffbcp = force_folding_builtin_constant_p;
-  force_folding_builtin_constant_p = true;
+  int save_ffbcp = force_folding_builtin_constant_p;
+  force_folding_builtin_constant_p = 1;
   new_call = fold_builtin_call_array (EXPR_LOCATION (t), TREE_TYPE (t),
                                      CALL_EXPR_FN (t), nargs, args);
   force_folding_builtin_constant_p = save_ffbcp;
--- gcc/cp/call.c.jj    2018-03-06 08:01:37.880883501 +0100
+++ gcc/cp/call.c       2018-03-07 15:58:38.457666266 +0100
@@ -7455,6 +7455,7 @@ magic_varargs_p (tree fn)
       {
       case BUILT_IN_CLASSIFY_TYPE:
       case BUILT_IN_CONSTANT_P:
+      case BUILT_IN_EARLY_CONSTANT_P:
       case BUILT_IN_NEXT_ARG:
       case BUILT_IN_VA_START:
        return 1;
--- gcc/cp/cp-gimplify.c.jj     2018-03-02 12:24:10.918325074 +0100
+++ gcc/cp/cp-gimplify.c        2018-03-07 17:20:36.524970697 +0100
@@ -34,6 +34,7 @@ along with GCC; see the file COPYING3.
 #include "stringpool.h"
 #include "attribs.h"
 #include "asan.h"
+#include "builtins.h"
 
 /* Forward declarations.  */
 
@@ -2374,17 +2375,18 @@ cp_fold (tree x)
 
     case CALL_EXPR:
       {
-       int i, m, sv = optimize, nw = sv, changed = 0;
+       int i, m, sv = force_folding_builtin_constant_p, nw = sv, changed = 0;
        tree callee = get_callee_fndecl (x);
 
        /* Some built-in function calls will be evaluated at compile-time in
-          fold ().  Set optimize to 1 when folding __builtin_constant_p inside
-          a constexpr function so that fold_builtin_1 doesn't fold it to 0.  */
-       if (callee && DECL_BUILT_IN (callee) && !optimize
+          fold ().  Set force_folding_builtin_constant_p to -1 when folding
+          __builtin_{,early_}constant_p inside a constexpr function so that
+          fold_builtin_1 doesn't fold it to 0.  */
+       if (callee && DECL_BUILT_IN (callee)
            && DECL_IS_BUILTIN_CONSTANT_P (callee)
            && current_function_decl
            && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
-         nw = 1;
+         nw = -1;
 
        x = copy_node (x);
 
@@ -2406,9 +2408,9 @@ cp_fold (tree x)
        if (x == error_mark_node)
          break;
 
-       optimize = nw;
+       force_folding_builtin_constant_p = nw;
        r = fold (x);
-       optimize = sv;
+       force_folding_builtin_constant_p = sv;
 
        if (TREE_CODE (r) != CALL_EXPR)
          {
@@ -2416,7 +2418,7 @@ cp_fold (tree x)
            break;
          }
 
-       optimize = nw;
+       force_folding_builtin_constant_p = nw;
 
        /* Invoke maybe_constant_value for functions declared
           constexpr and not called with AGGR_INIT_EXPRs.
@@ -2426,7 +2428,7 @@ cp_fold (tree x)
        if (callee && DECL_DECLARED_CONSTEXPR_P (callee)
            && !flag_no_inline)
          r = maybe_constant_value (x);
-       optimize = sv;
+       force_folding_builtin_constant_p = sv;
 
         if (TREE_CODE (r) != CALL_EXPR)
          {
--- gcc/cp/tree.c.jj    2018-03-07 10:11:41.477753951 +0100
+++ gcc/cp/tree.c       2018-03-07 16:01:09.987703817 +0100
@@ -417,6 +417,7 @@ builtin_valid_in_constant_expr_p (const_
       /* These have constant results even if their operands are
         non-constant.  */
     case BUILT_IN_CONSTANT_P:
+    case BUILT_IN_EARLY_CONSTANT_P:
     case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
       return true;
     default:
--- gcc/testsuite/g++.dg/delayedfold/builtin-constant3.C.jj     2018-03-07 
16:55:48.747733809 +0100
+++ gcc/testsuite/g++.dg/delayedfold/builtin-constant3.C        2018-03-07 
16:56:42.519747846 +0100
@@ -0,0 +1,8 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2" }
+
+#define SA(X) static_assert ((X),#X)
+
+int i;
+
+SA(__builtin_early_constant_p (i == 42 && false));
--- gcc/testsuite/g++.dg/delayedfold/builtin-constant4.C.jj     2018-03-07 
16:55:54.807735391 +0100
+++ gcc/testsuite/g++.dg/delayedfold/builtin-constant4.C        2018-03-07 
16:56:51.663750235 +0100
@@ -0,0 +1,14 @@
+// { dg-do run }
+// { dg-options "-O2" }
+
+int i;
+
+#define CV(X) (__builtin_early_constant_p (X) ? (X) : -1)
+
+int ar[] = { CV (i == 42 && false) };
+
+int main()
+{
+  if (ar[0] != 0)
+    __builtin_abort();
+}
--- gcc/testsuite/g++.dg/ext/builtin12.C.jj     2018-03-07 16:53:48.015702300 
+0100
+++ gcc/testsuite/g++.dg/ext/builtin12.C        2018-03-07 16:54:11.079708323 
+0100
@@ -0,0 +1,14 @@
+// PR c++/19628
+// Verify that __builtin_early_constant_p may appear in a constant-expression.
+
+// { dg-do run }
+
+int main()
+{
+  switch (3) {
+  case (__builtin_early_constant_p(7) ? 3 : 8):
+    return 0;
+  default:
+    return 1;
+  }
+}
--- gcc/testsuite/g++.dg/ext/builtin13.C.jj     2018-03-07 16:53:50.842703039 
+0100
+++ gcc/testsuite/g++.dg/ext/builtin13.C        2018-03-07 16:54:20.441710763 
+0100
@@ -0,0 +1,16 @@
+// PR c++/19628
+// Verify that __builtin_early_constant_p may appear in a constant-expression.
+
+// { dg-do compile }
+
+template <int I>
+int f(int x[__builtin_early_constant_p(I)])
+{
+  return x[0];
+}
+
+int g()
+{
+  int a[1] = { 7 };
+  return f<32>(a);
+}
--- gcc/testsuite/g++.dg/ext/builtin14.C.jj     2018-03-07 16:53:54.348703950 
+0100
+++ gcc/testsuite/g++.dg/ext/builtin14.C        2018-03-07 16:54:27.073712490 
+0100
@@ -0,0 +1,3 @@
+// PR c++/21619
+// { dg-options "" }
+int f[__builtin_early_constant_p(&"Hello"[0])?1:-1];
--- gcc/testsuite/g++.dg/cpp1y/constexpr-78420.C.jj     2018-03-07 
17:03:06.464825167 +0100
+++ gcc/testsuite/g++.dg/cpp1y/constexpr-78420.C        2018-03-07 
17:09:10.426865686 +0100
@@ -0,0 +1,36 @@
+// PR c++/78420
+// { dg-do run { target c++14 } }
+// { dg-options "-O2" }
+
+constexpr int
+foo (const int *a, const int *b)
+{
+  if (__builtin_early_constant_p (a < b))
+    return a < b;
+  return -1;
+}
+
+int ar[3], i;
+static_assert (foo (&ar[1], &ar[2]) == 1);
+static_assert (foo (&ar[2], &ar[1]) == 0);
+static_assert (foo (&ar[0], &i) == -1);
+
+int
+main ()
+{
+  int *p = &ar[1];
+  int *q = &ar[2];
+  if (foo (p, q) != -1)
+    __builtin_abort ();
+  constexpr int r = foo (&ar[1], &ar[2]);
+  if (r != 1)
+    __builtin_abort ();
+  if (!__builtin_early_constant_p (1))
+    __builtin_abort ();
+  const int two = 2;
+  if (!__builtin_early_constant_p (two))
+    __builtin_abort ();
+  int three = 3;
+  if (__builtin_early_constant_p (three))
+    __builtin_abort ();
+}
--- gcc/testsuite/g++.dg/cpp0x/constexpr-builtin4.C.jj  2018-03-07 
16:50:24.222649109 +0100
+++ gcc/testsuite/g++.dg/cpp0x/constexpr-builtin4.C     2018-03-07 
16:50:49.049655592 +0100
@@ -0,0 +1,5 @@
+// PR c++/54021
+// { dg-do compile { target c++11 } }
+
+#define __builtin_constant_p __builtin_early_constant_p
+#include "constexpr-builtin2.C"
--- gcc/testsuite/g++.dg/cpp0x/constexpr-builtin5.C.jj  2018-03-07 
16:50:56.574657555 +0100
+++ gcc/testsuite/g++.dg/cpp0x/constexpr-builtin5.C     2018-03-07 
16:51:20.688663849 +0100
@@ -0,0 +1,6 @@
+// PR c++/65656
+// { dg-options "-std=c++11 -O" }
+
+int main(int argc, char *argv[]) {
+  constexpr bool x = __builtin_early_constant_p(argc);
+}
--- gcc/testsuite/gcc.dg/torture/pr78420.c.jj   2018-03-07 17:15:27.305907637 
+0100
+++ gcc/testsuite/gcc.dg/torture/pr78420.c      2018-03-07 17:51:03.862453805 
+0100
@@ -0,0 +1,29 @@
+/* PR c++/78420 */
+/* { dg-do run } */
+
+int a = __builtin_early_constant_p (1);
+const int b = 2;
+int c = __builtin_early_constant_p (b);
+int d = __builtin_early_constant_p (b + 1);
+int e;
+int f = __builtin_early_constant_p (e);
+
+int
+main ()
+{
+  const int g = 3;
+  if (a != 1 || b != 2 || c || d || e || f)
+    __builtin_abort ();
+  int h = 3;
+  if (!__builtin_early_constant_p (7)
+#ifdef __OPTIMIZE__
+      || !__builtin_early_constant_p (g)
+      || !__builtin_early_constant_p (g + 1)
+#else
+      || __builtin_early_constant_p (g)
+      || __builtin_early_constant_p (g + 1)
+#endif
+      || __builtin_early_constant_p (h))
+    __builtin_abort ();
+  return 0;
+}

        Jakub

Reply via email to