Skip to content

Fix cppstd_flag for clang-cl driver in C++23 / C++26 / gnu++ modes#19965

Open
HYUEHFJKhfjklkej wants to merge 1 commit into
conan-io:develop2from
HYUEHFJKhfjklkej:fix/19887-clang-cl-cppstd
Open

Fix cppstd_flag for clang-cl driver in C++23 / C++26 / gnu++ modes#19965
HYUEHFJKhfjklkej wants to merge 1 commit into
conan-io:develop2from
HYUEHFJKhfjklkej:fix/19887-clang-cl-cppstd

Conversation

@HYUEHFJKhfjklkej
Copy link
Copy Markdown

Summary

clang-cl mimics cl.exe's /std: flag. The driver accepts only a
small set of values:

clang-cl version /std: accepts
< 22 c++14, c++17, c++20, c++latest (+ c11/c17)
≥ 22 the above plus c++23preview

The previous mechanical flag.replace("=", ":") translation in
cppstd_flag produced /std: values that clang-cl rejects with
"argument unused during compilation" for:

  • compiler.cppstd=23 on any clang-cl version (/std:c++23 is not a
    valid token);
  • compiler.cppstd=26 (no /std: form exists yet);
  • the pre-standard markers emitted by _cppstd_clang for older clangs:
    c++1y, c++1z, c++2a, c++2b;
  • every gnu++ extension (gnu++14, gnu++17, ...).

Fix

Replace the blanket = -> : translation with a small helper that:

  • emits /std:c++14, /std:c++17, /std:c++20 when clang-cl accepts
    the value directly;
  • emits /std:c++23preview only on clang-cl ≥ 22 (the version that
    introduced the alias for -std=c++23);
  • routes everything else through -clang:-std=... so the inner clang
    frontend receives the original GCC-style flag — the documented escape
    hatch for unsupported /std: values.

closes #19887

Test plan

The clang-cl branch in cppstd_flag was previously not covered by unit
tests. This PR adds explicit coverage:

test_clang_cl_cppstd_flags
  /std:c++14 /std:c++17 /std:c++20            (clang 17)
  -clang:-std=c++23                           (clang 17 / 21)
  /std:c++23preview                           (clang 22)
  -clang:-std=c++26                           (clang 17 and 22)
  -clang:-std=gnu++17 -clang:-std=gnu++23     (gnu++ extensions)
  -clang:-std=c++2a                           (pre-standard marker)
Suite Result
pytest test/unittests/client/build/cpp_std_flags_test.py 12 passed
pytest test/unittests/tools/ test/unittests/client/build/ 786 passed, 8 skipped (pre-existing)

Reference for the clang-cl /std: values:
https://blog.conan.io/2022/10/13/Different-flavors-Clang-compiler-Windows.html

Reference for the -clang: passthrough:
https://clang.llvm.org/docs/UsersManual.html#the-clang-cl-driver

`clang-cl` mimics `cl.exe`'s `/std:` flag. The accepted values are a
fixed subset (`c++14`, `c++17`, `c++20`, `c++latest`, plus
`c++23preview` from clang-cl 22). For anything else — `c++23` on older
clang-cl, `c++26`, the pre-standard markers (`c++1y`, `c++2a`, `c++2b`)
and the `gnu++` extensions — the previous mechanical
`flag.replace("=", ":")` produced a `/std:` value that clang-cl rejects
with "argument unused during compilation".

Replace the blanket `=` -> `:` translation with a small helper that:

  * emits `/std:c++14`, `/std:c++17`, `/std:c++20` when clang-cl accepts
    them directly;
  * emits `/std:c++23preview` only on clang-cl 22+ (the version that
    introduced the alias);
  * routes everything else through `-clang:-std=...` so the inner clang
    frontend receives the original GCC-style flag — the documented
    escape hatch for unsupported `/std:` values.

The previous code path was not unit-tested; this change adds explicit
coverage for the clang-cl driver, including the C++23 reproduction
from the bug report.

closes conan-io#19887
@memsharded
Copy link
Copy Markdown
Member

This behavior was still not approved. Ticket #19887 is labeled as "look-into" which means this is still something that the team need to consider and decide how we want to handle it. It is not that clear that the desired direction is this one, so better wait until the team checks it. Thanks.

@memsharded memsharded self-assigned this May 10, 2026
Copy link
Copy Markdown
Member

@memsharded memsharded left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good, just one clarification, but I think it can be moved forward for next 2.29

if value in ("c++14", "c++17", "c++20"):
return f"/std:{value}"
if value == "c++23" and clang_version >= "22":
return "/std:c++23preview"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As commented in #19887 (comment), I am willing to move this forward, but it would be good to align with CMake in the behavior. Is there any disadvantage to keep the -clang:-std=c++23 syntax for this combination?

@memsharded memsharded added this to the 2.29.0 milestone May 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug] cppstd_flag() is wrong for clang-cl in C++23 mode

2 participants