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
@@ -122,19 +123,22 @@ const clang::ASTContext &clangCtx) {
122123
123124} // end anonymous namespace
124125
125- const clang::Type *ClangTypeConverter::getFunctionType (
126- ArrayRef<AnyFunctionType::Param> params, Type resultTy,
127- AnyFunctionType::Representation repr) {
128-
129- auto resultClangTy = convert (resultTy);
126+ template <bool templateArgument>
127+ const clang::Type *
128+ ClangTypeConverter::getFunctionType (ArrayRef<AnyFunctionType::Param> params,
129+ Type resultTy,
130+ AnyFunctionType::Representation repr) {
131+ auto resultClangTy =
132+ templateArgument ? convertTemplateArgument (resultTy) : convert (resultTy);
130133 if (resultClangTy.isNull ())
131134 return nullptr ;
132135
133136 SmallVector<clang::FunctionProtoType::ExtParameterInfo, 4 > extParamInfos;
134137 SmallVector<clang::QualType, 4 > paramsClangTy;
135138 bool someParamIsConsumed = false ;
136139 for (auto p : params) {
137- auto pc = convert (p.getPlainType ());
140+ auto pc = templateArgument ? convertTemplateArgument (p.getPlainType ())
141+ : convert (p.getPlainType ());
138142 if (pc.isNull ())
139143 return nullptr ;
140144 clang::FunctionProtoType::ExtParameterInfo extParamInfo;
@@ -165,16 +169,21 @@ const clang::Type *ClangTypeConverter::getFunctionType(
165169 llvm_unreachable (" invalid representation" );
166170}
167171
172+ template <bool templateArgument>
168173const clang::Type *
169174ClangTypeConverter::getFunctionType (ArrayRef<SILParameterInfo> params,
170175 std::optional<SILResultInfo> result,
171176 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 ;
177+ clang::QualType resultClangTy = ClangASTContext.VoidTy ;
178+ if (result) {
179+ // Using the interface type is sufficient as type parameters get mapped to
180+ // `id`, since ObjC lightweight generics use type erasure.
181+ //
182+ // (See also: SE-0057)
183+ auto interfaceType = result->getInterfaceType ();
184+ resultClangTy = templateArgument ? convertTemplateArgument (interfaceType)
185+ : convert (interfaceType);
186+ }
178187
179188 if (resultClangTy.isNull ())
180189 return nullptr ;
@@ -183,7 +192,8 @@ ClangTypeConverter::getFunctionType(ArrayRef<SILParameterInfo> params,
183192 SmallVector<clang::QualType, 4 > paramsClangTy;
184193 bool someParamIsConsumed = false ;
185194 for (auto &p : params) {
186- auto pc = convert (p.getInterfaceType ());
195+ auto pc = templateArgument ? convertTemplateArgument (p.getInterfaceType ())
196+ : convert (p.getInterfaceType ());
187197 if (pc.isNull ())
188198 return nullptr ;
189199 clang::FunctionProtoType::ExtParameterInfo extParamInfo;
@@ -565,18 +575,18 @@ ClangTypeConverter::visitBoundGenericType(BoundGenericType *type) {
565575 }
566576
567577 if (auto kind = classifyPointer (type))
568- return convertPointerType (argType, kind. value () ,
569- /* templateArgument= */ false );
578+ return convertPointerType< /* templateArgument= */ false > (argType,
579+ kind. value () );
570580
571581 if (auto width = classifySIMD (type))
572- return convertSIMDType (argType, width.value (), /* templateArgument= */ false );
582+ return convertSIMDType< /* templateArgument= */ false > (argType, width.value ());
573583
574584 return clang::QualType ();
575585}
576586
587+ template <bool templateArgument>
577588clang::QualType ClangTypeConverter::convertSIMDType (CanType scalarType,
578- unsigned width,
579- bool templateArgument) {
589+ unsigned width) {
580590 clang::QualType scalarTy = templateArgument
581591 ? convertTemplateArgument (scalarType)
582592 : convert (scalarType);
@@ -588,9 +598,9 @@ clang::QualType ClangTypeConverter::convertSIMDType(CanType scalarType,
588598 return vectorTy;
589599}
590600
601+ template <bool templateArgument>
591602clang::QualType ClangTypeConverter::convertPointerType (CanType pointeeType,
592- PointerKind kind,
593- bool templateArgument) {
603+ PointerKind kind) {
594604 switch (kind) {
595605 case PointerKind::Unmanaged:
596606 return templateArgument ? clang::QualType () : convert (pointeeType);
@@ -651,6 +661,7 @@ clang::QualType ClangTypeConverter::visitEnumType(EnumType *type) {
651661 return convert (type->getDecl ()->getRawType ());
652662}
653663
664+ template <bool templateArgument>
654665clang::QualType ClangTypeConverter::visitFunctionType (FunctionType *type) {
655666 const clang::Type *clangTy = nullptr ;
656667 auto repr = type->getRepresentation ();
@@ -665,12 +676,15 @@ clang::QualType ClangTypeConverter::visitFunctionType(FunctionType *type) {
665676 auto newRepr = (repr == FunctionTypeRepresentation::Swift
666677 ? FunctionTypeRepresentation::Block
667678 : repr);
668- clangTy = getFunctionType (type->getParams (), type->getResult (), newRepr);
679+ clangTy = getFunctionType<templateArgument>(type->getParams (),
680+ type->getResult (), newRepr);
669681 }
670682 return clang::QualType (clangTy, 0 );
671683}
672684
673- clang::QualType ClangTypeConverter::visitSILFunctionType (SILFunctionType *type) {
685+ template <bool templateArgument>
686+ clang::QualType
687+ ClangTypeConverter::visitSILFunctionType (SILFunctionType *type) {
674688 const clang::Type *clangTy = nullptr ;
675689 auto repr = type->getRepresentation ();
676690 bool useClangTypes = type->getASTContext ().LangOpts .UseClangFunctionTypes ;
@@ -688,7 +702,8 @@ clang::QualType ClangTypeConverter::visitSILFunctionType(SILFunctionType *type)
688702 auto optionalResult = results.empty ()
689703 ? std::nullopt
690704 : std::optional<SILResultInfo>(results[0 ]);
691- clangTy = getFunctionType (type->getParameters (), optionalResult, newRepr);
705+ clangTy = getFunctionType<templateArgument>(type->getParameters (),
706+ optionalResult, newRepr);
692707 }
693708 return clang::QualType (clangTy, 0 );
694709}
@@ -933,6 +948,13 @@ clang::QualType ClangTypeConverter::convertTemplateArgument(Type type) {
933948 if (auto floatType = type->getAs <BuiltinFloatType>())
934949 return withCache ([&]() { return visitBuiltinFloatType (floatType); });
935950
951+ if (auto tupleType = type->getAs <TupleType>()) {
952+ // We do not call visitTupleType() because we cannot yet handle tuples with
953+ // a non-zero number of elements.
954+ if (tupleType->getNumElements () == 0 )
955+ return ClangASTContext.VoidTy ;
956+ }
957+
936958 if (auto structType = type->getAs <StructType>()) {
937959 // Swift structs are not supported in general, but some foreign types are
938960 // imported as Swift structs. We reverse that mapping here.
@@ -953,8 +975,6 @@ clang::QualType ClangTypeConverter::convertTemplateArgument(Type type) {
953975 return withCache ([&]() { return reverseBuiltinTypeMapping (structType); });
954976 }
955977
956- // TODO: function pointers are not yet supported, but they should be.
957-
958978 if (auto boundGenericType = type->getAs <BoundGenericType>()) {
959979 if (boundGenericType->getGenericArgs ().size () != 1 )
960980 // Must've got something other than a T?, *Pointer<T>, or SIMD*<T>
@@ -968,8 +988,8 @@ clang::QualType ClangTypeConverter::convertTemplateArgument(Type type) {
968988 auto pointeeType = argType->getAs <BoundGenericType>()
969989 ->getGenericArgs ()[0 ]
970990 ->getCanonicalType ();
971- return convertPointerType (pointeeType, kind. value () ,
972- /* templateArgument= */ true );
991+ return convertPointerType< /* templateArgument= */ true > (pointeeType,
992+ kind. value () );
973993 });
974994
975995 // Arbitrary optional types are not (yet) supported
@@ -978,19 +998,31 @@ clang::QualType ClangTypeConverter::convertTemplateArgument(Type type) {
978998
979999 if (auto kind = classifyPointer (boundGenericType))
9801000 return withCache ([&]() {
981- return convertPointerType (argType, kind. value () ,
982- /* templateArgument= */ true );
1001+ return convertPointerType< /* templateArgument= */ true > (argType,
1002+ kind. value () );
9831003 });
9841004
9851005 if (auto width = classifySIMD (boundGenericType))
9861006 return withCache ([&]() {
987- return convertSIMDType (argType, width. value () ,
988- /* templateArgument= */ true );
1007+ return convertSIMDType< /* templateArgument= */ true > (argType,
1008+ width. value () );
9891009 });
9901010
9911011 return clang::QualType ();
9921012 }
9931013
1014+ if (auto functionType = type->getAs <FunctionType>()) {
1015+ return withCache ([&]() {
1016+ return visitFunctionType</* templateArgument=*/ true >(functionType);
1017+ });
1018+ }
1019+
1020+ if (auto functionType = type->getAs <SILFunctionType>()) {
1021+ return withCache ([&]() {
1022+ return visitSILFunctionType</* templateArgument=*/ true >(functionType);
1023+ });
1024+ }
1025+
9941026 // Most types cannot be used to instantiate C++ function templates; give up.
9951027 return clang::QualType ();
9961028}
0 commit comments