Skip to content

clang -std=c++26 std::format complains non constant expression for a constant expression #239965

Open

Description

@goblinhack

Seems like this should work with std::format

#include <format>

int main() {
  auto s1 = std::format(std::runtime_format("{:<{}}"), "x", 1); // ok
  auto s2 = std::format("{{}}", "x", 1); // ok
  auto s3 = std::format("{:<{}}", "x", 1); // fails
  return 0;
}

throws:

<source>:6:25: error: call to consteval function 'std::basic_format_string<char, const char (&)[2], int>::basic_format_string<char[7]>' is not a constant expression
    6 |   auto s3 = std::format("{:<{}}", "x", 1); // fails
      |                         ^
/opt/compiler-explorer/arm64/gcc-15.2.0/aarch64-unknown-linux-gnu/lib/gcc/aarch64-unknown-linux-gnu/15.2.0/../../../../aarch64-unknown-linux-gnu/include/c++/15.2.0/format:346:4: note: undefined function '__check_dynamic_spec<int, unsigned int, long long, unsigned long long>' cannot be used in a constant expression
  346 |           __check_dynamic_spec<int, unsigned, long long,
      |           ^
/opt/compiler-explorer/arm64/gcc-15.2.0/aarch64-unknown-linux-gnu/lib/gcc/aarch64-unknown-linux-gnu/15.2.0/../../../../aarch64-unknown-linux-gnu/include/c++/15.2.0/format:685:6: note: in call to '__pc.check_dynamic_spec_integral(1)'
  685 |             __pc.check_dynamic_spec_integral(__val);
      |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/arm64/gcc-15.2.0/aarch64-unknown-linux-gnu/lib/gcc/aarch64-unknown-linux-gnu/15.2.0/../../../../aarch64-unknown-linux-gnu/include/c++/15.2.0/format:701:16: note: in call to '_S_parse_width_or_precision(&"{:<{}}"[4], &"{:<{}}"[6], __spec._M_width, __arg_id, __scanner._Scanner::_M_pc)'
  701 |         auto __next = _S_parse_width_or_precision(__first, __last, _M_width,
      |                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  702 |                                                   __arg_id, __pc);
      |                                                   ~~~~~~~~~~~~~~~
/opt/compiler-explorer/arm64/gcc-15.2.0/aarch64-unknown-linux-gnu/lib/gcc/aarch64-unknown-linux-gnu/15.2.0/../../../../aarch64-unknown-linux-gnu/include/c++/15.2.0/format:1301:12: note: in call to '__spec._M_parse_width(&"{:<{}}"[3], &"{:<{}}"[6], __scanner._Scanner::_M_pc)'
 1301 |         __first = __spec._M_parse_width(__first, __last, __pc);
      |                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/arm64/gcc-15.2.0/aarch64-unknown-linux-gnu/lib/gcc/aarch64-unknown-linux-gnu/15.2.0/../../../../aarch64-unknown-linux-gnu/include/c++/15.2.0/format:2532:16: note: in call to 'this->_M_f.parse(__scanner._Scanner::_M_pc)'
 2532 |       { return _M_f.parse(__pc); }
      |                ^~~~~~~~~~~~~~~~
/opt/compiler-explorer/arm64/gcc-15.2.0/aarch64-unknown-linux-gnu/lib/gcc/aarch64-unknown-linux-gnu/15.2.0/../../../../aarch64-unknown-linux-gnu/include/c++/15.2.0/format:4662:31: note: in call to '__f.parse(__scanner._Scanner::_M_pc)'
 4662 |               this->_M_pc.advance_to(__f.parse(this->_M_pc));
      |                                      ^~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/arm64/gcc-15.2.0/aarch64-unknown-linux-gnu/lib/gcc/aarch64-unknown-linux-gnu/15.2.0/../../../../aarch64-unknown-linux-gnu/include/c++/15.2.0/format:4648:3: note: in call to 'this->_M_parse_format_spec<char[2], int>(0)'
 4648 |                 _M_parse_format_spec<_Args...>(__id);
      |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/arm64/gcc-15.2.0/aarch64-unknown-linux-gnu/lib/gcc/aarch64-unknown-linux-gnu/15.2.0/../../../../aarch64-unknown-linux-gnu/include/c++/15.2.0/format:4556:2: note: in call to 'this->_M_format_arg(0)'
 4556 |         _M_format_arg(__id);
      |         ^~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/arm64/gcc-15.2.0/aarch64-unknown-linux-gnu/lib/gcc/aarch64-unknown-linux-gnu/15.2.0/../../../../aarch64-unknown-linux-gnu/include/c++/15.2.0/format:4504:7: note: in call to 'this->_M_on_replacement_field()'
 4504 |                     _M_on_replacement_field();
      |                     ^~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/arm64/gcc-15.2.0/aarch64-unknown-linux-gnu/lib/gcc/aarch64-unknown-linux-gnu/15.2.0/../../../../aarch64-unknown-linux-gnu/include/c++/15.2.0/format:4810:2: note: in call to '__scanner._M_scan()'
 4810 |         __scanner._M_scan();
      |         ^~~~~~~~~~~~~~~~~~~
<source>:6:25: note: in call to 'basic_format_string<char[7]>("{:<{}}")'
    6 |   auto s3 = std::format("{:<{}}", "x", 1); // fails
      |                         ^~~~~~~~
/opt/compiler-explorer/arm64/gcc-15.2.0/aarch64-unknown-linux-gnu/lib/gcc/aarch64-unknown-linux-gnu/15.2.0/../../../../aarch64-unknown-linux-gnu/include/c++/15.2.0/format:397:2: note: declared here
  397 |         __check_dynamic_spec(size_t __id) noexcept;
      |         ^
1 error generated.
Compiler returned: 1

Activity

  1. added
    clang:frontendLanguage frontend issues, e.g. anything involving "Sema"
    and removed
    clangClang issues not falling into any other category
    on Nov 7, 2026
  2. llvmorg-github-actions commented on Nov 7, 2026

    @llvmorg-github-actions

    @llvm/issue-subscribers-clang-frontend

    Author: GoblinHack (goblinhack)

    Details Seems like this should work with std::format
    #include &lt;format&gt;
    
    int main() {
      auto s1 = std::format(std::runtime_format("{:&lt;{}}"), "x", 1); // ok
      auto s2 = std::format("{{}}", "x", 1); // ok
      auto s3 = std::format("{:&lt;{}}", "x", 1); // fails
      return 0;
    }
    
    

    throws:

    &lt;source&gt;:6:25: error: call to consteval function 'std::basic_format_string&lt;char, const char (&amp;)[2], int&gt;::basic_format_string&lt;char[7]&gt;' is not a constant expression
        6 |   auto s3 = std::format("{:&lt;{}}", "x", 1); // fails
          |                         ^
    /opt/compiler-explorer/arm64/gcc-15.2.0/aarch64-unknown-linux-gnu/lib/gcc/aarch64-unknown-linux-gnu/15.2.0/../../../../aarch64-unknown-linux-gnu/include/c++/15.2.0/format:346:4: note: undefined function '__check_dynamic_spec&lt;int, unsigned int, long long, unsigned long long&gt;' cannot be used in a constant expression
      346 |           __check_dynamic_spec&lt;int, unsigned, long long,
          |           ^
    /opt/compiler-explorer/arm64/gcc-15.2.0/aarch64-unknown-linux-gnu/lib/gcc/aarch64-unknown-linux-gnu/15.2.0/../../../../aarch64-unknown-linux-gnu/include/c++/15.2.0/format:685:6: note: in call to '__pc.check_dynamic_spec_integral(1)'
      685 |             __pc.check_dynamic_spec_integral(__val);
          |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /opt/compiler-explorer/arm64/gcc-15.2.0/aarch64-unknown-linux-gnu/lib/gcc/aarch64-unknown-linux-gnu/15.2.0/../../../../aarch64-unknown-linux-gnu/include/c++/15.2.0/format:701:16: note: in call to '_S_parse_width_or_precision(&amp;"{:&lt;{}}"[4], &amp;"{:&lt;{}}"[6], __spec._M_width, __arg_id, __scanner._Scanner::_M_pc)'
      701 |         auto __next = _S_parse_width_or_precision(__first, __last, _M_width,
          |                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      702 |                                                   __arg_id, __pc);
          |                                                   ~~~~~~~~~~~~~~~
    /opt/compiler-explorer/arm64/gcc-15.2.0/aarch64-unknown-linux-gnu/lib/gcc/aarch64-unknown-linux-gnu/15.2.0/../../../../aarch64-unknown-linux-gnu/include/c++/15.2.0/format:1301:12: note: in call to '__spec._M_parse_width(&amp;"{:&lt;{}}"[3], &amp;"{:&lt;{}}"[6], __scanner._Scanner::_M_pc)'
     1301 |         __first = __spec._M_parse_width(__first, __last, __pc);
          |                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /opt/compiler-explorer/arm64/gcc-15.2.0/aarch64-unknown-linux-gnu/lib/gcc/aarch64-unknown-linux-gnu/15.2.0/../../../../aarch64-unknown-linux-gnu/include/c++/15.2.0/format:2532:16: note: in call to 'this-&gt;_M_f.parse(__scanner._Scanner::_M_pc)'
     2532 |       { return _M_f.parse(__pc); }
          |                ^~~~~~~~~~~~~~~~
    /opt/compiler-explorer/arm64/gcc-15.2.0/aarch64-unknown-linux-gnu/lib/gcc/aarch64-unknown-linux-gnu/15.2.0/../../../../aarch64-unknown-linux-gnu/include/c++/15.2.0/format:4662:31: note: in call to '__f.parse(__scanner._Scanner::_M_pc)'
     4662 |               this-&gt;_M_pc.advance_to(__f.parse(this-&gt;_M_pc));
          |                                      ^~~~~~~~~~~~~~~~~~~~~~
    /opt/compiler-explorer/arm64/gcc-15.2.0/aarch64-unknown-linux-gnu/lib/gcc/aarch64-unknown-linux-gnu/15.2.0/../../../../aarch64-unknown-linux-gnu/include/c++/15.2.0/format:4648:3: note: in call to 'this-&gt;_M_parse_format_spec&lt;char[2], int&gt;(0)'
     4648 |                 _M_parse_format_spec&lt;_Args...&gt;(__id);
          |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /opt/compiler-explorer/arm64/gcc-15.2.0/aarch64-unknown-linux-gnu/lib/gcc/aarch64-unknown-linux-gnu/15.2.0/../../../../aarch64-unknown-linux-gnu/include/c++/15.2.0/format:4556:2: note: in call to 'this-&gt;_M_format_arg(0)'
     4556 |         _M_format_arg(__id);
          |         ^~~~~~~~~~~~~~~~~~~
    /opt/compiler-explorer/arm64/gcc-15.2.0/aarch64-unknown-linux-gnu/lib/gcc/aarch64-unknown-linux-gnu/15.2.0/../../../../aarch64-unknown-linux-gnu/include/c++/15.2.0/format:4504:7: note: in call to 'this-&gt;_M_on_replacement_field()'
     4504 |                     _M_on_replacement_field();
          |                     ^~~~~~~~~~~~~~~~~~~~~~~~~
    /opt/compiler-explorer/arm64/gcc-15.2.0/aarch64-unknown-linux-gnu/lib/gcc/aarch64-unknown-linux-gnu/15.2.0/../../../../aarch64-unknown-linux-gnu/include/c++/15.2.0/format:4810:2: note: in call to '__scanner._M_scan()'
     4810 |         __scanner._M_scan();
          |         ^~~~~~~~~~~~~~~~~~~
    &lt;source&gt;:6:25: note: in call to 'basic_format_string&lt;char[7]&gt;("{:&lt;{}}")'
        6 |   auto s3 = std::format("{:&lt;{}}", "x", 1); // fails
          |                         ^~~~~~~~
    /opt/compiler-explorer/arm64/gcc-15.2.0/aarch64-unknown-linux-gnu/lib/gcc/aarch64-unknown-linux-gnu/15.2.0/../../../../aarch64-unknown-linux-gnu/include/c++/15.2.0/format:397:2: note: declared here
      397 |         __check_dynamic_spec(size_t __id) noexcept;
          |         ^
    1 error generated.
    Compiler returned: 1
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    c++26clang:frontendLanguage frontend issues, e.g. anything involving "Sema"

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions