This is an archive of the discontinued LLVM Phabricator instance.

[libc++] Only include_next C library headers when they exist
ClosedPublic

Authored by ldionne on Oct 25 2022, 7:13 AM.

Details

Summary

Some platforms don't provide all C library headers. In practice, libc++
only requires a few C library headers to exist, and only a few functions
on those headers. Missing functions that libc++ doesn't need for its own
implementation are handled properly by the using_if_exists attribute,
however a missing header is currently a hard error when we try to
do #include_next.

This patch should make libc++ more flexible on platforms that do not
provide C headers that libc++ doesn't actually require for its own
implementation. The only downside is that it may move some errors from
the #include_next point to later in the compilation if we actually try
to use something that isn't provided, which could be somewhat confusing.
However, these errors should be caught by folks trying to port libc++
over to a new platform (when running the libc++ test suite), not by end
users.

NOTE: This is a reapplicaton of 226409, which was reverted in 674729813 because it broke the build. The issue has now been fixed with https://reviews.llvm.org/D138062.

Diff Detail

Event Timeline

ldionne created this revision.Oct 25 2022, 7:13 AM
Herald added a project: Restricted Project. · View Herald TranscriptOct 25 2022, 7:13 AM
ldionne requested review of this revision.Oct 25 2022, 7:13 AM
Herald added a project: Restricted Project. · View Herald TranscriptOct 25 2022, 7:13 AM
Herald added a reviewer: Restricted Project. · View Herald Transcript
philnik accepted this revision.Oct 25 2022, 8:45 AM
philnik added a subscriber: philnik.

In essence LGTM. As another PR, could we maybe add a minimal set of C headers that are required to build and test libc++ with LIBCXX_ENABLE_LOCALIZATION=Off, LIBCXX_ENABLE_UNICODE=Off, etc? That would allow us to track what we require the C implementation to provide and we can actually test against a minimal C library. If you think that's a good idea I'd be happy to work on that.

libcxx/include/complex.h
28–31
This revision is now accepted and ready to land.Oct 25 2022, 8:45 AM

In essence LGTM. As another PR, could we maybe add a minimal set of C headers that are required to build and test libc++ with LIBCXX_ENABLE_LOCALIZATION=Off, LIBCXX_ENABLE_UNICODE=Off, etc? That would allow us to track what we require the C implementation to provide and we can actually test against a minimal C library. If you think that's a good idea I'd be happy to work on that.

Yes, I think that would make sense, but I think it's also a non-negligible amount of work. You're thinking about making that part of the test suite, right?

ldionne updated this revision to Diff 475483.Nov 15 2022, 7:57 AM

Address review comments and rebase.

This revision was landed with ongoing or failed builds.Nov 15 2022, 7:58 AM
This revision was automatically updated to reflect the committed changes.
thakis added a subscriber: thakis.Nov 15 2022, 8:25 AM

It it possible that this caused this check-clang failure: http://45.33.8.238/macm1/48659/step_7.txt ?

It it possible that this caused this check-clang failure: http://45.33.8.238/macm1/48659/step_7.txt ?

git bisect says it's indeed this commit.

In essence LGTM. As another PR, could we maybe add a minimal set of C headers that are required to build and test libc++ with LIBCXX_ENABLE_LOCALIZATION=Off, LIBCXX_ENABLE_UNICODE=Off, etc? That would allow us to track what we require the C implementation to provide and we can actually test against a minimal C library. If you think that's a good idea I'd be happy to work on that.

Yes, I think that would make sense, but I think it's also a non-negligible amount of work. You're thinking about making that part of the test suite, right?

Yes, that would be the idea. My idea was to write custom headers and use the actual implementation from llvm-libc. I think that should be quite manageable.

It it possible that this caused this check-clang failure: http://45.33.8.238/macm1/48659/step_7.txt ?

How does that bot configure the build with CMake?

It it possible that this caused this check-clang failure: http://45.33.8.238/macm1/48659/step_7.txt ?

How does that bot configure the build with CMake?

@thakis To make sure you see this.

It it possible that this caused this check-clang failure: http://45.33.8.238/macm1/48659/step_7.txt ?

How does that bot configure the build with CMake?

@thakis To make sure you see this.

It doesn't. But from the error message, it looks like it shouldn't matter (?)

My reading of the error output is that this test tests the error message that occurs if the c++ headers aren't present. Previously we'd say "file not found", but now we say "reference to unresolved using declaration" due to not including some C header.

Maybe I misunderstood what's happening though.

It doesn't. But from the error message, it looks like it shouldn't matter (?)

My reading of the error output is that this test tests the error message that occurs if the c++ headers aren't present. Previously we'd say "file not found", but now we say "reference to unresolved using declaration" due to not including some C header.

Maybe I misunderstood what's happening though.

Well that build picked up the latest libc++ headers, so I guess it's at least doing a bootstrapping build and then using check-clang? I don't even know if Clang will use the just-built libc++ for testing when doing a bootstrapping build.

Well that build picked up the latest libc++ headers, so I guess it's at least doing a bootstrapping build and then using check-clang? I don't even know if Clang will use the just-built libc++ for testing when doing a bootstrapping build.

That bot "installs" libc++ headers to buildir/include/c++/v1 and puts clang in builddir/bin/clang, and clang looks for includes at ../../includes relative to it. But I think that's the normal directory layout when doing a make install with the cmake build too (?)

Here's how to repro this failure with the cmake build (can probably repro with a shorter cmake invocation too):

cd my-build-dir
/Applications/CMake.app/Contents/bin/cmake -GNinja -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_ASSERTIONS=ON -DLLVM_ENABLE_PROJECTS='clang;lld' -DLLVM_ENABLE_RUNTIMES='compiler-rt;libcxx' -DLLVM_APPEND_VC_REV=NO -DLLVM_TARGETS_TO_BUILD='X86;ARM;AArch64' ../llvm-project/llvm

ninja clang
ninja cxx
ninja FileCheck count not     

bin/llvm-lit ../llvm-project/clang/test/Driver/nostdincxx.cpp -vv
This revision is now accepted and ready to land.Nov 15 2022, 2:07 PM
ldionne updated this revision to Diff 475573.Nov 15 2022, 2:11 PM
ldionne edited the summary of this revision. (Show Details)

Rebase and reopen.

@thakis I'm going to land this tomorrow if the Clang change sticks.

I just noticed that this leads to atrocious diagnostics:

% cat hello.cc
#include <stdio.h>
int main() { printf("hello\n"); }

% out/gn/bin/clang -c hello.cc      
hello.cc:2:14: error: use of undeclared identifier 'printf'

???

This works:

% out/gn/bin/clang -c hello.cc -isysroot $(xcrun -show-sdk-path)

The reason is that stdio.h picks up libc++'s stdio.h, which then only include_next's the actual stdio.h if it exists.

This seems suboptimal (?)

I just noticed that this leads to atrocious diagnostics:

% cat hello.cc
#include <stdio.h>
int main() { printf("hello\n"); }

% out/gn/bin/clang -c hello.cc      
hello.cc:2:14: error: use of undeclared identifier 'printf'

???

This works:

% out/gn/bin/clang -c hello.cc -isysroot $(xcrun -show-sdk-path)

The reason is that stdio.h picks up libc++'s stdio.h, which then only include_next's the actual stdio.h if it exists.

This seems suboptimal (?)

Yes, I've noticed that before, but I don't see a solution to this other than getting rid of libc++'s stdio.h header entirely (and same for other C compatibility headers). This is a tradeoff between diagnostics quality and libc++'s ability to work on top of freestanding implementations without much work.