Why does clang -E - of a header file may have different exit status?

I see different exit status of clang. Does anybody know why? Should
clang be consistent on this aspect no matter what the header file is?

$ clang -E - <<< '#include <bfd.h>' | head -n 1
# 1 "<stdin>"
$ declare -p PIPESTATUS
declare -a PIPESTATUS=([0]="141" [1]="0")
$ clang -E - <<< '#include <stdio.h>' | head -n 1
# 1 "<stdin>"
$ declare -p PIPESTATUS
declare -a PIPESTATUS=([0]="0" [1]="0")
$ clang --version
Debian clang version 11.0.1-2
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

gcc's exit status is consistent in this case.

$ gcc -E - <<< '#include <stdio.h>' | head -n 1
# 1 "<stdin>"
$ declare -p PIPESTATUS
declare -a PIPESTATUS=([0]="2" [1]="0")
$ gcc -E - <<< '#include <bfd.h>' | head -n 1
# 1 "<stdin>"
$ declare -p PIPESTATUS
declare -a PIPESTATUS=([0]="2" [1]="0")
$ gcc --version
gcc (Debian 10.2.1-6) 10.2.1 20210110
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

I mean, looks like clang exits non-zero when trying to preprocess your
bfd.h? Does clang print any errors? Maybe try reducing down the
contents of bfd.h to see what's critical about the contents of that
file that causes the non-zero exit?

I mean, looks like clang exits non-zero when trying to preprocess your
bfd.h? Does clang print any errors?

There are no error messages.

$ clang -E - <<< '#include <bfd.h>' > /dev/null
$ echo "$?"
0

Maybe try reducing down the
contents of bfd.h to see what's critical about the contents of that
file that causes the non-zero exit?

Could you try to install binutils-dev on a debian lineage linux? bfd.h
is from that package. The thing that does not make sense is that gcc
is consistent but clang is not.

$ kill -l 141
PIPE

This happens because clang failed to fully write the preprocessed output because the head command is no longer accepting more input. This is not specific to clang, it happens with many other utilities as well. Once the head command is no longer accepting more input, it's pointless for clang to continue writing output, so it's sent a signal to stop.

Depending on the contents of the header file, the signal to stop may be sent before or after clang has already fully written its output. If it has fully written the output already, then clang will not notice any error and exit successfully. This matches GCC, except that you need different header files to show this with GCC. Try a tiny header file such as <stdbool.h> instead.

Cheers,
Harald van Dijk

I see different exit status of clang. Does anybody know why? Should
clang be consistent on this aspect no matter what the header file is?

$ clang -E - <<< '#include <bfd.h>' | head -n 1
# 1 "<stdin>"
$ declare -p PIPESTATUS
declare -a PIPESTATUS=([0]="141" [1]="0")

$ kill -l 141
PIPE

This happens because clang failed to fully write the preprocessed output because the head command is no longer accepting more input. This is not specific to clang, it happens with many other utilities as well. Once the head command is no longer accepting more input, it's pointless for clang to continue writing output, so it's sent a signal to stop.

Depending on the contents of the header file, the signal to stop may be sent before or after clang has already fully written its output. If it

This was so poorly worded that it became wrong. It should be: depending on the contents of the header file, head may stop accepting input before or after clang has already fully written its output. If it stops accepting input afterwards, clang will not be sent any signal to stop.