From 13c32c1984f5857ccce2aeb00ce34343e5a26954 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 13 Apr 2022 15:43:34 +0200 Subject: [PATCH] c++: Treat alignas align_expr and aligned attribute's operand as manifestly constant evaluation [PR105233] 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). 2022-04-13 Jakub Jelinek 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 | 9 ++++++++- gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated13.C | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated13.C diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc index e10331f..d2b2920 100644 --- a/gcc/cp/decl2.cc +++ b/gcc/cp/decl2.cc @@ -1534,12 +1534,19 @@ cp_check_const_attributes (tree attributes) 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); } } } diff --git a/gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated13.C b/gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated13.C new file mode 100644 index 0000000..4a8af29 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/is-constant-evaluated13.C @@ -0,0 +1,19 @@ +// PR c++/105233 +// { dg-do compile { target c++14 } } + +template +constexpr T +foo (T x) noexcept +{ + bool a = __builtin_is_constant_evaluated (); + T b = 4 * alignof (int); + return x < b ? b : x; +} + +template +struct A { T a, b, c; }; + +template +struct alignas (foo (sizeof (A))) B { A d; }; + +B e; -- 2.7.4