PR62024 reports that we can't use __atomic_always_lock_free in
a static assert, as the FEs say it's not a constant expression.  Yet the
docs say that the result of __atomic_always_lock_free is a compile time
constant.
We can fix this pretty easily.  While fold folds __atomic_always_lock_free
to a constant, that constant is wrapped in NOP_EXPR - and static assert
code is unhappy.
I think we can just STRIP_TYPE_NOPS - we don't expect an lvalue in the
static assert code.  This is done in both C and C++ FEs.  What do you think?
In C, we'd still pedwarn on such code, and in C++ we'd still reject
non-constexpr functions that are not builtin functions.

The tests require sync_char_short target in a hope they aren't run
on targets where the static assert would actually trigger.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2014-08-25  Marek Polacek  <pola...@redhat.com>

        PR c/62024
c/
        * c-parser.c (c_parser_static_assert_declaration_no_semi): Strip no-op
        conversions.
cp/
        * semantics.c (finish_static_assert): Strip no-op conversions.
testsuite/
        * g++.dg/cpp0x/pr62024.C: New test.
        * gcc.dg/pr62024.c: New test.

diff --git gcc/c/c-parser.c gcc/c/c-parser.c
index d634bb1..fc7bbaf 100644
--- gcc/c/c-parser.c
+++ gcc/c/c-parser.c
@@ -2058,6 +2058,8 @@ c_parser_static_assert_declaration_no_semi (c_parser 
*parser)
   if (TREE_CODE (value) != INTEGER_CST)
     {
       value = c_fully_fold (value, false, NULL);
+      /* Strip no-op conversions.  */
+      STRIP_TYPE_NOPS (value);
       if (TREE_CODE (value) == INTEGER_CST)
        pedwarn (value_loc, OPT_Wpedantic, "expression in static assertion "
                 "is not an integer constant expression");
diff --git gcc/cp/semantics.c gcc/cp/semantics.c
index a54011f..b87d3ba 100644
--- gcc/cp/semantics.c
+++ gcc/cp/semantics.c
@@ -6870,6 +6870,9 @@ finish_static_assert (tree condition, tree message, 
location_t location,
   condition = cp_convert (boolean_type_node, condition, tf_warning_or_error);
   condition = maybe_constant_value (condition);
 
+  /* Strip no-op conversions.  */
+  STRIP_TYPE_NOPS (condition);
+
   if (TREE_CODE (condition) == INTEGER_CST && !integer_zerop (condition))
     /* Do nothing; the condition is satisfied. */
     ;
diff --git gcc/testsuite/g++.dg/cpp0x/pr62024.C 
gcc/testsuite/g++.dg/cpp0x/pr62024.C
index e69de29..5f0640a 100644
--- gcc/testsuite/g++.dg/cpp0x/pr62024.C
+++ gcc/testsuite/g++.dg/cpp0x/pr62024.C
@@ -0,0 +1,7 @@
+// PR c/62024
+// { dg-do compile { target c++11 } }
+// { dg-require-effective-target sync_char_short }
+
+int *p;
+static_assert (__atomic_always_lock_free (1, p), "");
+static_assert (__atomic_always_lock_free (1, 0), "");
diff --git gcc/testsuite/gcc.dg/pr62024.c gcc/testsuite/gcc.dg/pr62024.c
index e69de29..79a0b79 100644
--- gcc/testsuite/gcc.dg/pr62024.c
+++ gcc/testsuite/gcc.dg/pr62024.c
@@ -0,0 +1,8 @@
+/* PR c/62024 */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu11 -Wpedantic" } */
+/* { dg-require-effective-target sync_char_short } */
+
+int *p;
+_Static_assert (__atomic_always_lock_free (1, p), ""); /* { dg-warning "is not 
an integer constant" } */
+_Static_assert (__atomic_always_lock_free (1, 0), ""); /* { dg-warning "is not 
an integer constant" } */

        Marek

Reply via email to