The Swift build scripts pass `-sdk /` to the Swift compiler when building the Swift stdlib and the overlays, and this affects the default include paths of Clang. We need to make sure that libstdc++ path detected by ClangImporter is the same path that will be used by Clang during compilation. To do that, let's pass `--sysroot` to the Clang driver when detecting the libstdc++ path.
To inject a modulemap into the libstdc++ directory, Swift needs to know the path of the libstdc++ installation. Previously it was assumed to be `/usr/include/c++/{version}`, however, this might not be the case. For example, on CentOS the stdlib is located at `/opt/rh/devtoolset-{version}/root/usr/include/c++/{version}`.
This change teaches Swift to extract the libstdc++ include paths from the Clang driver, and fixes C++ stdlib lookup on CentOS.
rdar://93341210
Previously the modulemap for the C++ stdlib on Linux was provided via `-fmodule-map-file=` Clang argument pointing to the modulemap file within the Swift toolchain. The modulemap file could not reference the stdlib headers directly, since the exact stdlib include directory varies across Linux versions (it generally looks like `/usr/include/c++/{gcc_version}`). So the modulemap file instead referenced a local header, which `#include <>`-ed the stdlib headers, relying on Clang include resolution.
Unfortunately this did not work properly in the presence of another C++ module which included the stdlib headers: sometimes decls from the stdlib were hijacked by the other module, and were not treated as a part of the stdlib by Clang. This caused compile errors in Swift.
This change uses LLVM VFS to inject the modulemap file into the libstdc++ directory. The modulemap file is now able to reference the stdlib headers directly, which fixes the issue.
Credits to Rintaro Ishizaki for proposing a similar idea for SwiftGlibc back in 2016.
LLVM has enabled opaque pointers by default. Disable while we migrate.
Note that individual tests can have opaque pointers enabled by using
`-Xcc -Xclang -Xcc -opaque-pointers`.
`InclusionDirective` was changed in llvm/llvm-project
d79ad2f1dbc2db63121620f55d6cfa915f2733ac to pass an
`Optional<FileEntryRef>` rather than a `FileEntry *`. Update overrides
in Swift to use the new API.
`ParseTopLevelDecl` was changed in llvm/llvm-project
ab28488efe6de6f8fa856a1dfd8c0320d41d7608 and now takes a
Sema::ModuleImportState output parameter rather than the previous
(defaulted) boolean.
If a namespace has redecls in different modules, Swift sometimes picked a redecl which is not visible from the requested module, and wrongly removed the namespace from lookup results.
This resulted in errors like this:
```
*** DESERIALIZATION FAILURE ***
Could not deserialize type for 'init(cxxString:)'
Caused by: top-level value not found (std)
Cross-reference to module '__ObjC'
... std
```
Temporarily disable the checks for mutable fields in a C++ struct. A better solution would be to use some heuristic to detect if a method mutates a mutable field, and allow the user to adjust mutability with the existing `nonmutating` annotation.
rdar://92621793
To fix a crash during deserialization, we need to store the mangled names of C++ class template instantiations in the lookup table.
For example, `std::string` will be serialized as `__CxxTemplateInstNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE`, and when another instance of the Swift compiler will later attempt to deserialize a decl referencing this instantiation, it will query the `SwiftLookupTable` for a decl with this name. If this instantiation is not referenced from the module that is currently being compiled, Swift will not instantiate `std::string` during typechecking, and the mangled name will be missing from `SwiftLookupTable`, leading to a deserialization failure. This happens when compiling with cross-module optimization enabled, and the current module does not reference `std::string`, but one of its dependencies does.
Previously, the clang importer marked all const methods as mutating whenever a C++ record had mutable fields. This change allows overriding this behavior by using the "nonmutating" swift_attr attribute.
Fixes SR-15907.
The `SWIFT_COMPILER_VERSION` define is used to stamp a vendor’s version number into a Swift compiler binary. It can be queried from Swift code using `#if _compiler_version` and from Clang by using a preprocessor definition called `__SWIFT_COMPILER_VERSION`. These are unsupported compiler-internal features used primarily by Apple Swift.
In Swift 1.0 through 5.5, Apple Swift used a scheme for `SWIFT_COMPILER_VERSION` where the major version matched the embedded clang (e.g. 1300 for Apple Clang 13.0.0) and the minor version was ignored. Starting in Swift 5.6, Apple Swift started using major and minor version numbers that matched the Swift.org version number. This makes them easier to understand, but it means that version 1300.0.x was followed by version 5.6.x. Not only did version numbers go backwards, but also the old logic to ignore minor versions was now a liability, because it meant you would not be able to target a change to 5.7.x compilers but not 5.6.x compilers.
This commit addresses the problem by:
* Modifying the existing `#if _compiler_version(string-literal)` feature so it transforms the major version into a major and minor that will compare correctly to new version numbers. For instance, “1300.*” is transformed into “1.300”, which will compare correctly to a “5.6” or “5.7” version even if it doesn’t really capture the fact that “1300” was a Swift 5.5 compiler. As a bonus, this allows you to use the feature to backwards-compatibly test new compilers using the existing feature: “5007.*” will be seen by compilers before 5.7 as an unknown future version, but will be seen by 5.7 compilers as targeting them.
* Modifying the `__SWIFT_COMPILER_VERSION` clang define similarly so that, to preprocessor conditions written for the old scheme, a 5.7 compiler will appear to have major version 5007.
* Adding a new variant of `#if _compiler_version` with the same syntax as `#if swift` and `#if compiler`—that is, taking a comparison operator and a bare set of dotted version numbers, rather than a string literal. Going forward, this will be how version checks are written once compatibility with compilers before this change is no longer a concern.
These changes are only lightly tested because tests have to work without any compiler version defined (the default in most configurations), but I’ve tested what I can.
Fixes rdar://89841295.
Do not attempt to serialize C++ builtin decls. This caused an assertion failure in `clang::ASTWriter::getDeclID` when building SwiftCompilerSources:
```
Assertion failed: (DeclIDs.find(D) != DeclIDs.end() && "Declaration not emitted!"), function getDeclID, file ASTWriter.cpp, line 5272.
Please submit a bug report (https://swift.org/contributing/#reporting-bugs) and include the project and the crash backtrace.
Stack dump:
0. <eof> parser at end of file
Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
0 swift-frontend 0x00000001123e21c7 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 39
1 swift-frontend 0x00000001123e10e8 llvm::sys::RunSignalHandlers() + 248
2 swift-frontend 0x00000001123e2810 SignalHandler(int) + 288
3 libsystem_platform.dylib 0x00007fff204a0d7d _sigtramp + 29
4 libsystem_platform.dylib 0x0000000000000008 _sigtramp + 18446603339974439592
5 libsystem_c.dylib 0x00007fff203b0406 abort + 125
6 libsystem_c.dylib 0x00007fff203af7d8 err + 0
7 swift-frontend 0x000000011345b983 clang::ASTWriter::getDeclID(clang::Decl const*) (.cold.1) + 35
8 swift-frontend 0x0000000110a584b2 clang::ASTWriter::getDeclID(clang::Decl const*) + 322
9 swift-frontend 0x000000010e36649c llvm::OnDiskChainedHashTableGenerator<(anonymous namespace)::BaseNameToEntitiesTableWriterInfo>::Emit(llvm::raw_ostream&, (anonymous namespace)::BaseNameToEntitiesTableWriterInfo&) + 1244
10 swift-frontend 0x000000010e364927 swift::SwiftLookupTableWriter::writeExtensionContents(clang::Sema&, llvm::BitstreamWriter&) + 1351
11 swift-frontend 0x0000000110a59b62 clang::ASTWriter::WriteModuleFileExtension(clang::Sema&, clang::ModuleFileExtensionWriter&) + 946
```
This change adds a module map for libstdc++, which allows it to be properly imported into Swift as a module. The module map is installed into `usr/lib/swift/linux/{arch}` similarly to `glibc.modulemap`, and is passed to Clang as `-fmodule-map-file`.
That means it is now possible to import std directly from Swift on Linux, when C++ interop is enabled.
The module map currently declares a single `std` module without splitting the headers into submodules. This is going to change in the near future.
rdar://87654514
As per SR-14137 this caches entries in ImportedDecls even when the
import failed.
Also have to mention I did this based on Thomas's PR #36747.
This should help us better handle complex templates and dependant types.