llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: None (Tsche) <details> <summary>Changes</summary> Currently clang limits the number of constant evaluation steps to 1'048'576 (or 2^20) by default. This default comes from [[implimits]/1.39](https://eel.is/c++draft/implimits#<!-- -->1.39). This limit is easily reached - for example in libc++ tests we override this default in many places: <details> <summary>overrides in libc++ tests</summary> | Step Limit | Test | |----------------|--------| | 2000000 | libcxx/test/std/algorithms/alg.modifying.operations/alg.move/move.pass.cpp | | 2000000 | libcxx/test/std/algorithms/alg.nonmodifying/alg.contains/ranges.contains_subrange.pass.cpp | | 2000000 | libcxx/test/std/containers/sequences/vector/vector.modifiers/append_range.pass.cpp | | 2000000 | libcxx/test/std/containers/sequences/vector/vector.modifiers/assign_range.pass.cpp | | 2000000 | libcxx/test/std/containers/sequences/vector/vector.modifiers/insert_range.pass.cpp | | 2000000 | libcxx/test/std/containers/sequences/vector.bool/append_range.pass.cpp | | 2000000 | libcxx/test/std/containers/sequences/vector.bool/assign_range.pass.cpp | | 2000000 | libcxx/test/std/containers/sequences/vector.bool/insert_range.pass.cpp | | 2000000 | libcxx/test/std/numerics/complex.number/complex.ops/complex_divide_complex.pass.cpp | | 2000000 | libcxx/test/std/numerics/complex.number/complex.ops/complex_times_complex.pass.cpp | | 2000000 | libcxx/test/std/utilities/template.bitset/bitset.members/op_and_eq.pass.cpp | | 3000000 | libcxx/test/std/containers/sequences/forwardlist/forwardlist.ops/splice_after_range.pass.cpp | | 9000000 | libcxx/test/libcxx/input.output/iostream.format/print.fun/transcoding.pass.cpp | | 9000000 | libcxx/test/std/containers/sequences/vector/vector.modifiers/emplace.pass.cpp | | 9000000 | libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string.string_view.pass.cpp | | 10000000 | libcxx/test/std/strings/basic.string/string.modifiers/string_replace/replace_with_range.pass.cpp | | 12712420 | libcxx/test/std/utilities/charconv/charconv.from.chars/integral.roundtrip.pass.cpp | | 12712420 | libcxx/test/std/utilities/charconv/charconv.to.chars/integral.pass.cpp | | 12712420 | libcxx/test/std/utilities/template.bitset/bitset.members/left_shift.pass.cpp | | 15000000 | libcxx/test/std/utilities/template.bitset/bitset.members/left_shift_eq.pass.cpp | | 15000000 | libcxx/test/std/utilities/template.bitset/bitset.members/op_or_eq.pass.cpp | | 15000000 | libcxx/test/std/utilities/template.bitset/bitset.members/right_shift_eq.pass.cpp | | 20000000 | libcxx/test/std/algorithms/alg.nonmodifying/alg.count/count.pass.cpp | | 20000000 | libcxx/test/std/algorithms/alg.nonmodifying/alg.count/ranges.count.pass.cpp | | 20000000 | libcxx/test/std/algorithms/alg.nonmodifying/alg.find/find.pass.cpp | | 20000000 | libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find.pass.cpp | | 20000000 | libcxx/test/std/containers/sequences/forwardlist/forwardlist.modifiers/insert_range_after.pass.cpp | | 50000000 | libcxx/test/std/algorithms/alg.nonmodifying/mismatch/mismatch.pass.cpp | | 200000000 | libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort_comp.pass.cpp | | 200000000 | libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp | </details> In libc++ tests that override both `-fconstexpr-steps` and GCC's `-fconstexpr-ops-limit`, we see a factor of 0.25 applied in most cases: <details> <summary>overrides in libc++ tests</summary> | Factor | `-fconstexpr-steps` | `-fconstexpr-ops-limit` | Test | |--------|---------------------|-------------------------|------| | 0.14 | 10000000 | 70000000 | libcxx/test/std/strings/basic.string/string.modifiers/string_replace/replace_with_range.pass.cpp | | 0.25 | 20000000 | 80000000 | libcxx/test/std/algorithms/alg.nonmodifying/alg.count/count.pass.cpp | | 0.25 | 20000000 | 80000000 | libcxx/test/std/algorithms/alg.nonmodifying/alg.count/ranges.count.pass.cpp | | 0.25 | 20000000 | 80000000 | libcxx/test/std/algorithms/alg.nonmodifying/alg.find/find.pass.cpp | | 0.25 | 20000000 | 80000000 | libcxx/test/std/algorithms/alg.nonmodifying/alg.find/ranges.find.pass.cpp | | 0.25 | 12712420 | 50000000 | libcxx/test/std/utilities/charconv/charconv.to.chars/integral.pass.cpp | | 0.5 | 50000000 | 100000000 | libcxx/test/std/algorithms/alg.nonmodifying/mismatch/mismatch.pass.cpp | | 1 | 200000000 | 200000000 | libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort_comp.pass.cpp | | 1 | 200000000 | 200000000 | libcxx/test/std/algorithms/alg.sorting/alg.sort/stable.sort/stable_sort.pass.cpp | </details> So, assuming `0.25` as a conversion factor, this would require increasing the limit to at least 8'388'608 to match gcc's default of 33'554'432. With heavy metaprogramming features like reflection still on track for C++26, I believe it is reasonable to increase this limit. For instance, recursively walking all namespaces and performing a set of checks for every reflected member of that namespace immediately hits this limit for the global namespace - which roughly yields 3000 member reflections even without descending. This patch increases the default limit to 20'000'000. With this default all but the last 3 tests in the first table would not have to override the default. I think this is a more reasonable default - on my machine 20 million steps take roughly 10 seconds. --- Full diff: https://github.com/llvm/llvm-project/pull/143785.diff 3 Files Affected: - (modified) clang/docs/UsersManual.rst (+1-1) - (modified) clang/include/clang/Basic/LangOptions.def (+1-1) - (modified) clang/include/clang/Driver/Options.td (+1-1) ``````````diff diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index 62844f7e6a2fa..c948ba218c219 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -3992,7 +3992,7 @@ Controlling implementation limits Sets the limit for the number of full-expressions evaluated in a single constant expression evaluation. This also controls the maximum size of array and dynamic array allocation that can be constant evaluated. - The default is 1048576. + The default is 20000000. .. option:: -ftemplate-depth=N diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 789761c1f3647..ba3c8dac8b35d 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -415,7 +415,7 @@ BENIGN_LANGOPT(InstantiationDepth, 32, 1024, "maximum template instantiation depth") BENIGN_LANGOPT(ConstexprCallDepth, 32, 512, "maximum constexpr call depth") -BENIGN_LANGOPT(ConstexprStepLimit, 32, 1048576, +BENIGN_LANGOPT(ConstexprStepLimit, 32, 20000000, "maximum constexpr evaluation steps") BENIGN_LANGOPT(EnableNewConstInterp, 1, 0, "enable the experimental new constant interpreter") diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 152df89118a6a..4886e7b0a45e0 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2002,7 +2002,7 @@ def fconstexpr_depth_EQ : Joined<["-"], "fconstexpr-depth=">, Group<f_Group>, def fconstexpr_steps_EQ : Joined<["-"], "fconstexpr-steps=">, Group<f_Group>, Visibility<[ClangOption, CC1Option]>, HelpText<"Set the maximum number of steps in constexpr function evaluation">, - MarshallingInfoInt<LangOpts<"ConstexprStepLimit">, "1048576">; + MarshallingInfoInt<LangOpts<"ConstexprStepLimit">, "20000000">; def fexperimental_new_constant_interpreter : Flag<["-"], "fexperimental-new-constant-interpreter">, Group<f_Group>, HelpText<"Enable the experimental new constant interpreter">, Visibility<[ClangOption, CC1Option]>, `````````` </details> https://github.com/llvm/llvm-project/pull/143785 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits