4040#include " clang/Basic/TargetInfo.h"
4141#include " clang/Sema/Sema.h"
4242
43+ #include " llvm/ADT/STLExtras.h"
4344#include " llvm/ADT/StringSwitch.h"
4445#include " llvm/Support/Compiler.h"
4546
@@ -124,17 +125,18 @@ const clang::ASTContext &clangCtx) {
124125
125126const clang::Type *ClangTypeConverter::getFunctionType (
126127 ArrayRef<AnyFunctionType::Param> params, Type resultTy,
127- AnyFunctionType::Representation repr) {
128-
129- auto resultClangTy = convert (resultTy);
128+ AnyFunctionType::Representation repr, bool templateArgument ) {
129+ auto resultClangTy =
130+ templateArgument ? convertTemplateArgument (resultTy) : convert (resultTy);
130131 if (resultClangTy.isNull ())
131132 return nullptr ;
132133
133134 SmallVector<clang::FunctionProtoType::ExtParameterInfo, 4 > extParamInfos;
134135 SmallVector<clang::QualType, 4 > paramsClangTy;
135136 bool someParamIsConsumed = false ;
136137 for (auto p : params) {
137- auto pc = convert (p.getPlainType ());
138+ auto pc = templateArgument ? convertTemplateArgument (p.getPlainType ())
139+ : convert (p.getPlainType ());
138140 if (pc.isNull ())
139141 return nullptr ;
140142 clang::FunctionProtoType::ExtParameterInfo extParamInfo;
@@ -165,16 +167,19 @@ const clang::Type *ClangTypeConverter::getFunctionType(
165167 llvm_unreachable (" invalid representation" );
166168}
167169
168- const clang::Type *
169- ClangTypeConverter::getFunctionType (ArrayRef<SILParameterInfo> params,
170- std::optional<SILResultInfo> result,
171- SILFunctionType::Representation repr) {
172-
173- // Using the interface type is sufficient as type parameters get mapped to
174- // `id`, since ObjC lightweight generics use type erasure. (See also: SE-0057)
175- auto resultClangTy = result.has_value ()
176- ? convert (result.value ().getInterfaceType ())
177- : ClangASTContext.VoidTy ;
170+ const clang::Type *ClangTypeConverter::getFunctionType (
171+ ArrayRef<SILParameterInfo> params, std::optional<SILResultInfo> result,
172+ SILFunctionType::Representation repr, bool templateArgument) {
173+ clang::QualType resultClangTy = ClangASTContext.VoidTy ;
174+ if (result) {
175+ // Using the interface type is sufficient as type parameters get mapped to
176+ // `id`, since ObjC lightweight generics use type erasure.
177+ //
178+ // (See also: SE-0057)
179+ auto interfaceType = result->getInterfaceType ();
180+ resultClangTy = templateArgument ? convertTemplateArgument (interfaceType)
181+ : convert (interfaceType);
182+ }
178183
179184 if (resultClangTy.isNull ())
180185 return nullptr ;
@@ -183,7 +188,8 @@ ClangTypeConverter::getFunctionType(ArrayRef<SILParameterInfo> params,
183188 SmallVector<clang::QualType, 4 > paramsClangTy;
184189 bool someParamIsConsumed = false ;
185190 for (auto &p : params) {
186- auto pc = convert (p.getInterfaceType ());
191+ auto pc = templateArgument ? convertTemplateArgument (p.getInterfaceType ())
192+ : convert (p.getInterfaceType ());
187193 if (pc.isNull ())
188194 return nullptr ;
189195 clang::FunctionProtoType::ExtParameterInfo extParamInfo;
@@ -651,7 +657,8 @@ clang::QualType ClangTypeConverter::visitEnumType(EnumType *type) {
651657 return convert (type->getDecl ()->getRawType ());
652658}
653659
654- clang::QualType ClangTypeConverter::visitFunctionType (FunctionType *type) {
660+ clang::QualType ClangTypeConverter::visitFunctionType (FunctionType *type,
661+ bool templateArgument) {
655662 const clang::Type *clangTy = nullptr ;
656663 auto repr = type->getRepresentation ();
657664 bool useClangTypes = type->getASTContext ().LangOpts .UseClangFunctionTypes ;
@@ -665,12 +672,15 @@ clang::QualType ClangTypeConverter::visitFunctionType(FunctionType *type) {
665672 auto newRepr = (repr == FunctionTypeRepresentation::Swift
666673 ? FunctionTypeRepresentation::Block
667674 : repr);
668- clangTy = getFunctionType (type->getParams (), type->getResult (), newRepr);
675+ clangTy = getFunctionType (type->getParams (), type->getResult (), newRepr,
676+ templateArgument);
669677 }
670678 return clang::QualType (clangTy, 0 );
671679}
672680
673- clang::QualType ClangTypeConverter::visitSILFunctionType (SILFunctionType *type) {
681+ clang::QualType
682+ ClangTypeConverter::visitSILFunctionType (SILFunctionType *type,
683+ bool templateArgument) {
674684 const clang::Type *clangTy = nullptr ;
675685 auto repr = type->getRepresentation ();
676686 bool useClangTypes = type->getASTContext ().LangOpts .UseClangFunctionTypes ;
@@ -688,7 +698,8 @@ clang::QualType ClangTypeConverter::visitSILFunctionType(SILFunctionType *type)
688698 auto optionalResult = results.empty ()
689699 ? std::nullopt
690700 : std::optional<SILResultInfo>(results[0 ]);
691- clangTy = getFunctionType (type->getParameters (), optionalResult, newRepr);
701+ clangTy = getFunctionType (type->getParameters (), optionalResult, newRepr,
702+ templateArgument);
692703 }
693704 return clang::QualType (clangTy, 0 );
694705}
@@ -933,6 +944,13 @@ clang::QualType ClangTypeConverter::convertTemplateArgument(Type type) {
933944 if (auto floatType = type->getAs <BuiltinFloatType>())
934945 return withCache ([&]() { return visitBuiltinFloatType (floatType); });
935946
947+ if (auto tupleType = type->getAs <TupleType>()) {
948+ // We do not call visitTupleType() because we cannot yet handle tuples with
949+ // a non-zero number of elements.
950+ if (tupleType->getNumElements () == 0 )
951+ return ClangASTContext.VoidTy ;
952+ }
953+
936954 if (auto structType = type->getAs <StructType>()) {
937955 // Swift structs are not supported in general, but some foreign types are
938956 // imported as Swift structs. We reverse that mapping here.
@@ -953,8 +971,6 @@ clang::QualType ClangTypeConverter::convertTemplateArgument(Type type) {
953971 return withCache ([&]() { return reverseBuiltinTypeMapping (structType); });
954972 }
955973
956- // TODO: function pointers are not yet supported, but they should be.
957-
958974 if (auto boundGenericType = type->getAs <BoundGenericType>()) {
959975 if (boundGenericType->getGenericArgs ().size () != 1 )
960976 // Must've got something other than a T?, *Pointer<T>, or SIMD*<T>
@@ -991,6 +1007,18 @@ clang::QualType ClangTypeConverter::convertTemplateArgument(Type type) {
9911007 return clang::QualType ();
9921008 }
9931009
1010+ if (auto functionType = type->getAs <FunctionType>()) {
1011+ return withCache ([&]() {
1012+ return visitFunctionType (functionType, /* templateArgument=*/ true );
1013+ });
1014+ }
1015+
1016+ if (auto functionType = type->getAs <SILFunctionType>()) {
1017+ return withCache ([&]() {
1018+ return visitSILFunctionType (functionType, /* templateArgument=*/ true );
1019+ });
1020+ }
1021+
9941022 // Most types cannot be used to instantiate C++ function templates; give up.
9951023 return clang::QualType ();
9961024}
0 commit comments