https://gcc.gnu.org/g:26b50c5fed8b0373c2c6100b5a92d1109bb20783
commit r16-828-g26b50c5fed8b0373c2c6100b5a92d1109bb20783 Author: Jason Merrill <ja...@redhat.com> Date: Thu May 22 09:11:04 2025 -0400 c++: constexpr always_inline [PR120935] In cp_fold we do speculative constant evaluation of constexpr calls when inlining is enabled. Let's also do it for always_inline functions. PR c++/120935 gcc/cp/ChangeLog: * cp-gimplify.cc (cp_fold): Check always_inline. gcc/testsuite/ChangeLog: * g++.dg/opt/always_inline2.C: New test. * g++.dg/debug/dwarf2/pubnames-2.C: Suppress -fimplicit-constexpr. * g++.dg/debug/dwarf2/pubnames-3.C: Likewise. Diff: --- gcc/cp/cp-gimplify.cc | 4 +++- gcc/testsuite/g++.dg/debug/dwarf2/pubnames-2.C | 2 +- gcc/testsuite/g++.dg/debug/dwarf2/pubnames-3.C | 2 +- gcc/testsuite/g++.dg/opt/always_inline2.C | 28 ++++++++++++++++++++++++++ 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc index f7bd453bc5eb..03d5352977b2 100644 --- a/gcc/cp/cp-gimplify.cc +++ b/gcc/cp/cp-gimplify.cc @@ -3441,7 +3441,9 @@ cp_fold (tree x, fold_flags_t flags) Do constexpr expansion of expressions where the call itself is not constant, but the call followed by an INDIRECT_REF is. */ if (callee && DECL_DECLARED_CONSTEXPR_P (callee) - && !flag_no_inline) + && (!flag_no_inline + || lookup_attribute ("always_inline", + DECL_ATTRIBUTES (callee)))) { mce_value manifestly_const_eval = mce_unknown; if (flags & ff_mce_false) diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/pubnames-2.C b/gcc/testsuite/g++.dg/debug/dwarf2/pubnames-2.C index 1fb5004df401..96469d4d332f 100644 --- a/gcc/testsuite/g++.dg/debug/dwarf2/pubnames-2.C +++ b/gcc/testsuite/g++.dg/debug/dwarf2/pubnames-2.C @@ -1,6 +1,6 @@ // { dg-do compile { target c++11 } } // { dg-skip-if "" { powerpc-ibm-aix* } } -// { dg-options "-gpubnames -gdwarf-4 -fno-debug-types-section -dA -fno-inline" } +// { dg-options "-gpubnames -gdwarf-4 -fno-debug-types-section -dA -fno-inline -fno-implicit-constexpr" } // { dg-final { scan-assembler-times "\.section\[\t \]\[^\n\]*debug_pubnames" 1 } } // { dg-final { scan-assembler "\"\\(anonymous namespace\\)\\\\0\"+\[ \t\]+\[#;/|@!]+\[ \t\]+external name" } } // { dg-final { scan-assembler "\"one\\\\0\"+\[ \t\]+\[#;/|@!]+\[ \t\]+external name" } } diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/pubnames-3.C b/gcc/testsuite/g++.dg/debug/dwarf2/pubnames-3.C index 37e04fb6c972..f635803d45ac 100644 --- a/gcc/testsuite/g++.dg/debug/dwarf2/pubnames-3.C +++ b/gcc/testsuite/g++.dg/debug/dwarf2/pubnames-3.C @@ -1,6 +1,6 @@ // { dg-do compile { target c++11 } } // { dg-skip-if "" { powerpc-ibm-aix* } } -// { dg-options "-gpubnames -gdwarf-4 -fdebug-types-section -dA -fno-inline" } +// { dg-options "-gpubnames -gdwarf-4 -fdebug-types-section -dA -fno-inline -fno-implicit-constexpr" } // { dg-final { scan-assembler-times "\.section\[\t \]\[^\n\]*debug_pubnames" 1 } } // { dg-final { scan-assembler "\"\\(anonymous namespace\\)\\\\0\"+\[ \t\]+\[#;/|@!]+\[ \t\]+external name" } } // { dg-final { scan-assembler "\"one\\\\0\"+\[ \t\]+\[#;/|@!]+\[ \t\]+external name" } } diff --git a/gcc/testsuite/g++.dg/opt/always_inline2.C b/gcc/testsuite/g++.dg/opt/always_inline2.C new file mode 100644 index 000000000000..8cfdd67e36ce --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/always_inline2.C @@ -0,0 +1,28 @@ +// PR c++/120935 +// { dg-additional-options "-fdump-tree-optimized" } +// { dg-final { scan-tree-dump-not "goto" "optimized" } } +// { dg-do compile { target c++11 } } + +void x(int); + +[[gnu::always_inline]] constexpr bool +is_constant_evaluated() +{ return __builtin_is_constant_evaluated(); } + +struct Iter +{ + typedef int value_type; + + int& operator*() const; + Iter& operator++(); + bool operator!=(const Iter&) const; +}; + +void f(Iter first, Iter last) +{ + if (__is_trivial(Iter::value_type)) + if (!is_constant_evaluated()) + return; + for (; first != last; ++first) + x(*first); +}