Hi!

The following testcase fails, because we only constant evaluate the
alignas argument as non-manifestly constant-evaluated and as
__builtin_is_constant_evaluated appears, we make it non-constant
(the reason is that we often try to evaluate some expression without
manifestly_const_eval perhaps even multiple times before actually
evaluating it with manifestly_const_eval (e.g. when folding for warnings
and in many other places), and we don't want __builtin_is_constant_evaluated
to evaluate to false in those cases, because we could get a different
result from when we actually evaluate it with manifestly_const_eval
set).
Now, for alignas the standard seems to be clear, it says the
argument is constant-expression, which means we should
manifestly-constant-eval it.
Attributes are a fuzzy area, they are extensions and various attributes
take e.g. identifiers, or string literals etc. as arguments.

Either we can just treat alignas as manifestly-const-eval, for that
we'd need some way how to differentiate between alignas and gnu::aligned
or aligned attribute.

Another possibility is what the patch below implements, treat
both alignas and gnu::aligned and aligned attribute's argument as
manifestly-const-eval and not do that for other attributes.

Another is to go through all attributes and figure out for which
such treatment is useful (e.g. those that expect INTEGER_CST as argument),
and either add a new column in the attribute table or have another table
in the C++ FE to find out which attribute needs that.

Another is do that for all the attribute arguments that are EXPR_P
and see what breaks (bet that it could be quite risky this late in
GCC 12 cycle and especially for backporting).

The following version has been successfully bootstrapped/regtested on
x86_64-linux and i686-linux, ok for trunk?

2022-04-13  Jakub Jelinek  <ja...@redhat.com>

        PR c++/105233
        * decl2.cc (cp_check_const_attributes): For aligned attribute
        pass manifestly_const_eval=true to fold_non_dependent_expr.

        * g++.dg/cpp2a/is-constant-evaluated13.C: New test.

--- gcc/cp/decl2.cc.jj  2022-04-11 10:39:13.871306246 +0200
+++ gcc/cp/decl2.cc     2022-04-12 15:30:26.954879574 +0200
@@ -1534,12 +1534,19 @@ cp_check_const_attributes (tree attribut
   for (attr = attributes; attr; attr = TREE_CHAIN (attr))
     {
       tree arg;
+      /* As we implement alignas using gnu::aligned attribute and
+        alignas argument is a constant expression, force manifestly
+        constant evaluation of aligned attribute argument.  */
+      bool manifestly_const_eval
+       = is_attribute_p ("aligned", get_attribute_name (attr));
       for (arg = TREE_VALUE (attr); arg && TREE_CODE (arg) == TREE_LIST;
           arg = TREE_CHAIN (arg))
        {
          tree expr = TREE_VALUE (arg);
          if (EXPR_P (expr))
-           TREE_VALUE (arg) = fold_non_dependent_expr (expr);
+           TREE_VALUE (arg)
+             = fold_non_dependent_expr (expr, tf_warning_or_error,
+                                        manifestly_const_eval);
        }
     }
 }
--- gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated13.C.jj     2022-04-12 
15:39:37.566204222 +0200
+++ gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated13.C        2022-04-12 
15:40:11.524730927 +0200
@@ -0,0 +1,19 @@
+// PR c++/105233
+// { dg-do compile { target c++14 } }
+
+template <typename T>
+constexpr T
+foo (T x) noexcept
+{
+  bool a = __builtin_is_constant_evaluated ();
+  T b = 4 * alignof (int);
+  return x < b ? b : x;
+}
+
+template <typename T>
+struct A { T a, b, c; };
+
+template <typename T>
+struct alignas (foo (sizeof (A<T>))) B { A<T> d; };
+
+B<int> e;

        Jakub

Reply via email to