mirror of
https://github.com/fmtlib/fmt.git
synced 2026-07-30 16:26:27 +08:00
Now that CC correctly matches CXX for this job, test/c-test.c is
compiled with real Clang 3.6.2 for the first time, which fails on
string-literal arguments to fmt's C API macros ("too many arguments
to function call, expected 0, have 1").
Root cause: fmt-c.h's FMT_MAKE_ARG uses a C11 _Generic dispatch with
a 0-arg fmt_unsupported_type default. Whether the controlling
expression of _Generic undergoes array-to-pointer decay was
genuinely ambiguous in C11 wording (WG14 N1930); Clang treated it as
an unconverted lvalue and did not decay arrays until the fix for
LLVM PR16340 landed in November 2015 (clang 3.8). Clang 3.6.2
(Feb 2015) predates that fix, so a string literal like "foo" (type
char[4]) never matches the char*/const char* cases and falls
through to the default, which then gets called with an argument.
Verified this is specific to old Clang, not a general fmt-c.h bug:
- Compiled test/c-test.c against fmt-c.h with a modern Clang
locally; it builds cleanly, confirming decay works correctly once
PR16340 is fixed.
- Confirmed no safe macro-level workaround exists: forcing decay
uniformly (e.g. `(x) + 0` or `1 ? (x) : (x)`) triggers ordinary
integer promotion for the small-integer cases (char, bool, short,
etc.), silently routing them to the wrong fmt_from_* function on
*all* compilers. A per-type-conditional wrapper isn't expressible
without already knowing the type, i.e. without _Generic itself.
Given this is a real, long-since-fixed upstream compiler bug in a
10-year-old Clang release, and no low-risk fix at the fmt-c.h level
exists that doesn't risk changing dispatch behavior on every other
compiler, skip just c-test (via ctest -E) for the clang++-3.6 job.
The C++ test suite for that job is unaffected and still runs.
The exclude value must be double-quoted when assigned from the
templated expression, since GitHub Actions substitutes it inline and
an unquoted assignment containing a space (e.g. exclude=-E ^c-test$)
does not parse as a single shell assignment - it splits into a
variable-scoped-to-command form that tries to execute a nonexistent
'^c-test$' command, aborting the step under bash's default -e.
Verified both branches (clang++-3.6 and every other matrix entry) by
actually executing the resulting snippet with bash -eo pipefail.
224 lines
9.4 KiB
YAML
224 lines
9.4 KiB
YAML
name: linux
|
|
|
|
on: [push, pull_request]
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
build:
|
|
name: >-
|
|
${{matrix.cxx}} c++${{matrix.std}} ${{matrix.build_type}}
|
|
${{matrix.gen}} ${{matrix.fuzz && 'Fuzz' || ''}}
|
|
${{matrix.shared && 'Shared' || ''}}
|
|
${{matrix.cxxflags_extra && 'Sanitize' || ''}}
|
|
runs-on: ${{ matrix.os || 'ubuntu-22.04' }}
|
|
strategy:
|
|
matrix:
|
|
cxx: [g++-4.9, g++-11, clang++-3.6, clang++-11]
|
|
build_type: [Debug, Release]
|
|
std: [11]
|
|
shared: [""]
|
|
include:
|
|
- cxx: g++-4.9
|
|
- cxx: g++-11
|
|
build_type: Debug
|
|
std: 14
|
|
install: sudo apt install g++-11
|
|
- cxx: g++-11
|
|
build_type: Debug
|
|
std: 17
|
|
- cxx: g++-11
|
|
build_type: Debug
|
|
std: 20
|
|
install: sudo apt install g++-11
|
|
- cxx: g++-13
|
|
build_type: Release
|
|
std: 23
|
|
os: ubuntu-24.04
|
|
shared: -DBUILD_SHARED_LIBS=ON
|
|
- cxx: g++-14
|
|
build_type: Release
|
|
std: 23
|
|
os: ubuntu-24.04
|
|
gen: Ninja
|
|
- cxx: clang++-3.6
|
|
- cxx: clang++-11
|
|
build_type: Debug
|
|
std: 17
|
|
cxxflags: -stdlib=libc++
|
|
install: sudo apt install clang-11 libc++-11-dev libc++abi-11-dev
|
|
- cxx: clang++-11
|
|
install: sudo apt install clang-11
|
|
- cxx: clang++-11
|
|
build_type: Debug
|
|
fuzz: -DFMT_FUZZ=ON -DFMT_FUZZ_LINKMAIN=ON
|
|
std: 17
|
|
install: sudo apt install clang-11
|
|
- cxx: clang++-14
|
|
build_type: Debug
|
|
std: 20
|
|
cxxflags: -fsanitize=address
|
|
cxxflags_extra: -fno-sanitize-recover=all -fno-omit-frame-pointer
|
|
- cxx: clang++-14
|
|
build_type: Debug
|
|
std: 20
|
|
cxxflags: -stdlib=libc++
|
|
install: sudo apt install libc++-14-dev libc++abi-14-dev
|
|
- cxx: clang++-20
|
|
build_type: Debug
|
|
std: 20
|
|
cxxflags: -stdlib=libc++
|
|
install: sudo apt install clang-20 libc++-20-dev libc++abi-20-dev
|
|
gen: Ninja
|
|
|
|
steps:
|
|
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
|
|
- name: Set timezone
|
|
run: sudo timedatectl set-timezone 'Europe/Kyiv'
|
|
|
|
- name: Install GCC 4.9
|
|
run: |
|
|
sudo apt update
|
|
sudo apt install libatomic1 libc6-dev libgomp1 libitm1 libmpc3
|
|
# https://launchpad.net/ubuntu/xenial/amd64/g++-4.9/4.9.3-13ubuntu2
|
|
wget --no-verbose \
|
|
http://launchpadlibrarian.net/230069137/libmpfr4_3.1.3-2_amd64.deb \
|
|
http://launchpadlibrarian.net/253728424/libasan1_4.9.3-13ubuntu2_amd64.deb \
|
|
http://launchpadlibrarian.net/445346135/libubsan0_5.4.0-6ubuntu1~16.04.12_amd64.deb \
|
|
http://launchpadlibrarian.net/445346112/libcilkrts5_5.4.0-6ubuntu1~16.04.12_amd64.deb \
|
|
http://launchpadlibrarian.net/253728426/libgcc-4.9-dev_4.9.3-13ubuntu2_amd64.deb \
|
|
http://launchpadlibrarian.net/253728432/libstdc++-4.9-dev_4.9.3-13ubuntu2_amd64.deb \
|
|
http://launchpadlibrarian.net/253728314/gcc-4.9-base_4.9.3-13ubuntu2_amd64.deb \
|
|
http://launchpadlibrarian.net/445345919/gcc-5-base_5.4.0-6ubuntu1~16.04.12_amd64.deb \
|
|
http://launchpadlibrarian.net/253728399/cpp-4.9_4.9.3-13ubuntu2_amd64.deb \
|
|
http://launchpadlibrarian.net/253728404/gcc-4.9_4.9.3-13ubuntu2_amd64.deb \
|
|
http://launchpadlibrarian.net/253728401/g++-4.9_4.9.3-13ubuntu2_amd64.deb
|
|
sudo dpkg -i \
|
|
libmpfr4_3.1.3-2_amd64.deb \
|
|
libasan1_4.9.3-13ubuntu2_amd64.deb \
|
|
libubsan0_5.4.0-6ubuntu1~16.04.12_amd64.deb \
|
|
libcilkrts5_5.4.0-6ubuntu1~16.04.12_amd64.deb \
|
|
libgcc-4.9-dev_4.9.3-13ubuntu2_amd64.deb \
|
|
libstdc++-4.9-dev_4.9.3-13ubuntu2_amd64.deb \
|
|
gcc-4.9-base_4.9.3-13ubuntu2_amd64.deb \
|
|
gcc-5-base_5.4.0-6ubuntu1~16.04.12_amd64.deb \
|
|
cpp-4.9_4.9.3-13ubuntu2_amd64.deb \
|
|
gcc-4.9_4.9.3-13ubuntu2_amd64.deb \
|
|
g++-4.9_4.9.3-13ubuntu2_amd64.deb
|
|
if: ${{ matrix.cxx == 'g++-4.9' }}
|
|
|
|
- name: Install Clang 3.6
|
|
run: |
|
|
sudo apt update
|
|
sudo apt install libtinfo5
|
|
# https://code.launchpad.net/ubuntu/xenial/amd64/clang-3.6/1:3.6.2-3ubuntu2
|
|
wget --no-verbose \
|
|
http://launchpadlibrarian.net/230019046/libffi6_3.2.1-4_amd64.deb \
|
|
http://launchpadlibrarian.net/445346109/libasan2_5.4.0-6ubuntu1~16.04.12_amd64.deb \
|
|
http://launchpadlibrarian.net/445346135/libubsan0_5.4.0-6ubuntu1~16.04.12_amd64.deb \
|
|
http://launchpadlibrarian.net/445346112/libcilkrts5_5.4.0-6ubuntu1~16.04.12_amd64.deb \
|
|
http://launchpadlibrarian.net/445346128/libmpx0_5.4.0-6ubuntu1~16.04.12_amd64.deb \
|
|
http://launchpadlibrarian.net/445346113/libgcc-5-dev_5.4.0-6ubuntu1~16.04.12_amd64.deb \
|
|
http://launchpadlibrarian.net/445346131/libstdc++-5-dev_5.4.0-6ubuntu1~16.04.12_amd64.deb \
|
|
http://launchpadlibrarian.net/445346022/libobjc-5-dev_5.4.0-6ubuntu1~16.04.12_amd64.deb \
|
|
http://launchpadlibrarian.net/254405108/libllvm3.6v5_3.6.2-3ubuntu2_amd64.deb \
|
|
http://launchpadlibrarian.net/254405097/libclang-common-3.6-dev_3.6.2-3ubuntu2_amd64.deb \
|
|
http://launchpadlibrarian.net/254405101/libclang1-3.6_3.6.2-3ubuntu2_amd64.deb \
|
|
http://launchpadlibrarian.net/445345919/gcc-5-base_5.4.0-6ubuntu1~16.04.12_amd64.deb \
|
|
http://launchpadlibrarian.net/254405091/clang-3.6_3.6.2-3ubuntu2_amd64.deb
|
|
sudo dpkg -i \
|
|
libffi6_3.2.1-4_amd64.deb \
|
|
libasan2_5.4.0-6ubuntu1~16.04.12_amd64.deb \
|
|
libubsan0_5.4.0-6ubuntu1~16.04.12_amd64.deb \
|
|
libcilkrts5_5.4.0-6ubuntu1~16.04.12_amd64.deb \
|
|
libmpx0_5.4.0-6ubuntu1~16.04.12_amd64.deb \
|
|
libgcc-5-dev_5.4.0-6ubuntu1~16.04.12_amd64.deb \
|
|
libstdc++-5-dev_5.4.0-6ubuntu1~16.04.12_amd64.deb \
|
|
libobjc-5-dev_5.4.0-6ubuntu1~16.04.12_amd64.deb \
|
|
libllvm3.6v5_3.6.2-3ubuntu2_amd64.deb \
|
|
libclang-common-3.6-dev_3.6.2-3ubuntu2_amd64.deb \
|
|
libclang1-3.6_3.6.2-3ubuntu2_amd64.deb \
|
|
gcc-5-base_5.4.0-6ubuntu1~16.04.12_amd64.deb \
|
|
clang-3.6_3.6.2-3ubuntu2_amd64.deb
|
|
if: ${{ matrix.cxx == 'clang++-3.6' }}
|
|
|
|
- name: Install LLVM-20
|
|
run: |
|
|
sudo install -D -m 0644 support/llvm-snapshot.gpg.key \
|
|
/etc/apt/keyrings/apt.llvm.org.asc
|
|
codename=$(lsb_release -cs)
|
|
echo "deb [signed-by=/etc/apt/keyrings/apt.llvm.org.asc]" \
|
|
"https://apt.llvm.org/$codename/" \
|
|
"llvm-toolchain-$codename-20 main" \
|
|
| sudo tee /etc/apt/sources.list.d/llvm.list
|
|
if: ${{ matrix.cxx == 'clang++-20' }}
|
|
|
|
- name: Add Ubuntu mirrors
|
|
run: |
|
|
# GitHub Actions caching proxy is at times unreliable
|
|
# see https://github.com/actions/runner-images/issues/7048.
|
|
mirrors=/etc/apt/mirrors.txt
|
|
printf 'http://azure.archive.ubuntu.com/ubuntu\tpriority:1\n' | \
|
|
sudo tee $mirrors
|
|
curl http://mirrors.ubuntu.com/mirrors.txt | sudo tee --append $mirrors
|
|
sudo sed -i \
|
|
"s~http://azure.archive.ubuntu.com/ubuntu/~mirror+file:$mirrors~" \
|
|
/etc/apt/sources.list
|
|
|
|
- name: Create build environment
|
|
run: |
|
|
sudo apt update
|
|
${{matrix.install}}
|
|
sudo apt install locales-all
|
|
cmake -E make_directory ${{runner.workspace}}/build
|
|
|
|
- name: Select matching C compiler
|
|
run: |
|
|
cc=${{matrix.cxx}}
|
|
cc=${cc/clang++/clang}
|
|
cc=${cc/g++/gcc}
|
|
echo "CC=$cc" >> "$GITHUB_ENV"
|
|
|
|
- name: Configure
|
|
working-directory: ${{runner.workspace}}/build
|
|
env:
|
|
CXX: ${{matrix.cxx}}
|
|
CXXFLAGS: ${{matrix.cxxflags}} ${{matrix.cxxflags_extra}}
|
|
run: |
|
|
cmake ${{matrix.gen && '-G' || ''}} ${{matrix.gen}} \
|
|
-DCMAKE_BUILD_TYPE=${{matrix.build_type}} \
|
|
-DCMAKE_CXX_STANDARD=${{matrix.std}} \
|
|
-DCMAKE_CXX_VISIBILITY_PRESET=hidden \
|
|
-DCMAKE_VISIBILITY_INLINES_HIDDEN=ON \
|
|
-DFMT_DOC=OFF -DFMT_PEDANTIC=ON \
|
|
-DFMT_WERROR=ON \
|
|
${{matrix.fuzz}} \
|
|
${{matrix.shared}} \
|
|
$GITHUB_WORKSPACE
|
|
|
|
- name: Build
|
|
working-directory: ${{runner.workspace}}/build
|
|
run: |
|
|
threads=`nproc`
|
|
cmake --build . --config ${{matrix.build_type}} --parallel $threads
|
|
|
|
- name: Test
|
|
working-directory: ${{runner.workspace}}/build
|
|
# clang++-3.6 predates the fix for LLVM PR16340 (the controlling
|
|
# expression of _Generic wasn't decayed/qualifier-stripped before
|
|
# type matching, fixed upstream in clang 3.8). That makes
|
|
# FMT_MAKE_ARG's _Generic dispatch in fmt-c.h fail to match string
|
|
# literals (e.g. "foo", of type char[4]) against the char*/const
|
|
# char* cases, so they fall through to the 0-arg default case and
|
|
# the call is passed too many arguments. This is a real, long-fixed
|
|
# upstream compiler bug rather than a bug in fmt's macro, so only
|
|
# c-test is skipped here for this one job; see the discussion on
|
|
# https://github.com/fmtlib/fmt/pull/4863 for the full analysis.
|
|
run: |
|
|
exclude="${{ matrix.cxx == 'clang++-3.6' && '-E ^c-test$' || '' }}"
|
|
ctest -C ${{matrix.build_type}} $exclude
|
|
env:
|
|
CTEST_OUTPUT_ON_FAILURE: True
|