Swift started to explicitly forbid the instantiation of C++ function
templates with arbitrary types in #77430, because many types cause the
Swift compiler to crash. However, those checks prevented them from being
instantiated with Swift closures (which were previously fine), causing
a regression.
This patch relaxes the convertTemplateArgument() function to also allow
converting Swift function types, and adds some tests to make sure doing
so is fine.
This patch also does some cleanup of existing tests checking the
instantiation of various types, and adds testing for C function pointers
and Obj-C blocks.
rdar://148124104
(cherry picked from commit 284de98744)
Instantiating C++ function templates with Swift types is not currently supported, but the Swift compiler attempts to do so. Sometimes this leads to a compiler crash; other times it leads to a runtime crash. This patch turns those crashes into compiler errors.
At the call site of a C++ function template, the Swift compiler must convert Swift types deduced by the Swift type checker back into Clang types, which are then used to instantiate the C++ function template. Prior to this patch, this conversion was performed by ClangTypeConverter::convert(), which converts unsupported Swift types. This patch factors out some reusable parts of convert() and uses them in a new ClangTypeConverter::convertTemplateArgument() method that only converts supported template argument types. In the future, this method can be elaborated to support instantiating C++ templates with more types.
rdar://112692940
This fixes a compiler crash when calling a templated C++ function with a parameter of type `ObjCBool` from Swift. The compiler now emits an error for this.
Previously the following would happen:
1. Swift starts to emit SILGen for a call expression `takeTAsConstRef(ObjCBool(true))`.
2. `takeTAsConstRef` is a templated C++ function, so Swift asks Clang to instantiate a `takeTAsConstRef` with a built-in Obj-C boolean type.
3. Swift gets an instantiated function template back that looks like this: `void takeTAsConstRef(_Bool t) { ... }`.
4. Swift's ClangImporter begins to import that instantiated function.
5. Since the parameter type is not spelled as `BOOL`, the parameter is not imported as `ObjCBool`. Instead, it's imported as regular Swift `Bool`.
6. Swift realizes that the types don't match (`ObjCBool` vs `Bool`), tries to apply any of the known implicit conversions, fails to do so, crashes.
rdar://130424969
The type bridging logic assumed that if a value of type `Swift.Bool` is passed to a Clang function as an argument, then the type of the parameter must be a Clang built-in type (usually `_Bool`). This is not always correct. For instance, the type might be a templated const reference.
rdar://125508505
Importing `type_traits` from libstdc++ currently causes a crash on Linux:
```
swift-ide-test: tools/clang/include/clang/AST/TypeNodes.inc:33: clang::TypeInfo clang::ASTContext::getTypeInfoImpl(const clang::Type *) const: Assertion `!T->isDependentType() && "should not see dependent types here"' failed.
PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace.
Stack dump:
0. Program arguments: /home/egorzh/Builds/swift/swift/bin/swift-ide-test -print-module -module-to-print=std -source-filename=x -enable-cxx-interop
1. /usr/lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/type_traits:1110:10: importing 'std::__do_is_implicitly_default_constructible_impl'
2. /usr/lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/type_traits:1116:22: importing 'std::__do_is_implicitly_default_constructible_impl::__test'
```
This change fixes the crash by bailing on such functions.
We already fixed this for "global" functions. This is a more generic
solution that works for "nested" functions as well. (Members or
functions in a namespace.)