40
40
#include " clang/Basic/TargetInfo.h"
41
41
#include " clang/Sema/Sema.h"
42
42
43
+ #include " llvm/ADT/STLExtras.h"
43
44
#include " llvm/ADT/StringSwitch.h"
44
45
#include " llvm/Support/Compiler.h"
45
46
@@ -122,19 +123,22 @@ const clang::ASTContext &clangCtx) {
122
123
123
124
} // end anonymous namespace
124
125
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);
130
133
if (resultClangTy.isNull ())
131
134
return nullptr ;
132
135
133
136
SmallVector<clang::FunctionProtoType::ExtParameterInfo, 4 > extParamInfos;
134
137
SmallVector<clang::QualType, 4 > paramsClangTy;
135
138
bool someParamIsConsumed = false ;
136
139
for (auto p : params) {
137
- auto pc = convert (p.getPlainType ());
140
+ auto pc = templateArgument ? convertTemplateArgument (p.getPlainType ())
141
+ : convert (p.getPlainType ());
138
142
if (pc.isNull ())
139
143
return nullptr ;
140
144
clang::FunctionProtoType::ExtParameterInfo extParamInfo;
@@ -165,16 +169,21 @@ const clang::Type *ClangTypeConverter::getFunctionType(
165
169
llvm_unreachable (" invalid representation" );
166
170
}
167
171
172
+ template <bool templateArgument>
168
173
const clang::Type *
169
174
ClangTypeConverter::getFunctionType (ArrayRef<SILParameterInfo> params,
170
175
std::optional<SILResultInfo> result,
171
176
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
+ }
178
187
179
188
if (resultClangTy.isNull ())
180
189
return nullptr ;
@@ -183,7 +192,8 @@ ClangTypeConverter::getFunctionType(ArrayRef<SILParameterInfo> params,
183
192
SmallVector<clang::QualType, 4 > paramsClangTy;
184
193
bool someParamIsConsumed = false ;
185
194
for (auto &p : params) {
186
- auto pc = convert (p.getInterfaceType ());
195
+ auto pc = templateArgument ? convertTemplateArgument (p.getInterfaceType ())
196
+ : convert (p.getInterfaceType ());
187
197
if (pc.isNull ())
188
198
return nullptr ;
189
199
clang::FunctionProtoType::ExtParameterInfo extParamInfo;
@@ -565,18 +575,18 @@ ClangTypeConverter::visitBoundGenericType(BoundGenericType *type) {
565
575
}
566
576
567
577
if (auto kind = classifyPointer (type))
568
- return convertPointerType (argType, kind. value () ,
569
- /* templateArgument= */ false );
578
+ return convertPointerType< /* templateArgument= */ false > (argType,
579
+ kind. value () );
570
580
571
581
if (auto width = classifySIMD (type))
572
- return convertSIMDType (argType, width.value (), /* templateArgument= */ false );
582
+ return convertSIMDType< /* templateArgument= */ false > (argType, width.value ());
573
583
574
584
return clang::QualType ();
575
585
}
576
586
587
+ template <bool templateArgument>
577
588
clang::QualType ClangTypeConverter::convertSIMDType (CanType scalarType,
578
- unsigned width,
579
- bool templateArgument) {
589
+ unsigned width) {
580
590
clang::QualType scalarTy = templateArgument
581
591
? convertTemplateArgument (scalarType)
582
592
: convert (scalarType);
@@ -588,9 +598,9 @@ clang::QualType ClangTypeConverter::convertSIMDType(CanType scalarType,
588
598
return vectorTy;
589
599
}
590
600
601
+ template <bool templateArgument>
591
602
clang::QualType ClangTypeConverter::convertPointerType (CanType pointeeType,
592
- PointerKind kind,
593
- bool templateArgument) {
603
+ PointerKind kind) {
594
604
switch (kind) {
595
605
case PointerKind::Unmanaged:
596
606
return templateArgument ? clang::QualType () : convert (pointeeType);
@@ -651,6 +661,7 @@ clang::QualType ClangTypeConverter::visitEnumType(EnumType *type) {
651
661
return convert (type->getDecl ()->getRawType ());
652
662
}
653
663
664
+ template <bool templateArgument>
654
665
clang::QualType ClangTypeConverter::visitFunctionType (FunctionType *type) {
655
666
const clang::Type *clangTy = nullptr ;
656
667
auto repr = type->getRepresentation ();
@@ -665,12 +676,15 @@ clang::QualType ClangTypeConverter::visitFunctionType(FunctionType *type) {
665
676
auto newRepr = (repr == FunctionTypeRepresentation::Swift
666
677
? FunctionTypeRepresentation::Block
667
678
: repr);
668
- clangTy = getFunctionType (type->getParams (), type->getResult (), newRepr);
679
+ clangTy = getFunctionType<templateArgument>(type->getParams (),
680
+ type->getResult (), newRepr);
669
681
}
670
682
return clang::QualType (clangTy, 0 );
671
683
}
672
684
673
- clang::QualType ClangTypeConverter::visitSILFunctionType (SILFunctionType *type) {
685
+ template <bool templateArgument>
686
+ clang::QualType
687
+ ClangTypeConverter::visitSILFunctionType (SILFunctionType *type) {
674
688
const clang::Type *clangTy = nullptr ;
675
689
auto repr = type->getRepresentation ();
676
690
bool useClangTypes = type->getASTContext ().LangOpts .UseClangFunctionTypes ;
@@ -688,7 +702,8 @@ clang::QualType ClangTypeConverter::visitSILFunctionType(SILFunctionType *type)
688
702
auto optionalResult = results.empty ()
689
703
? std::nullopt
690
704
: std::optional<SILResultInfo>(results[0 ]);
691
- clangTy = getFunctionType (type->getParameters (), optionalResult, newRepr);
705
+ clangTy = getFunctionType<templateArgument>(type->getParameters (),
706
+ optionalResult, newRepr);
692
707
}
693
708
return clang::QualType (clangTy, 0 );
694
709
}
@@ -933,6 +948,13 @@ clang::QualType ClangTypeConverter::convertTemplateArgument(Type type) {
933
948
if (auto floatType = type->getAs <BuiltinFloatType>())
934
949
return withCache ([&]() { return visitBuiltinFloatType (floatType); });
935
950
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
+
936
958
if (auto structType = type->getAs <StructType>()) {
937
959
// Swift structs are not supported in general, but some foreign types are
938
960
// imported as Swift structs. We reverse that mapping here.
@@ -953,8 +975,6 @@ clang::QualType ClangTypeConverter::convertTemplateArgument(Type type) {
953
975
return withCache ([&]() { return reverseBuiltinTypeMapping (structType); });
954
976
}
955
977
956
- // TODO: function pointers are not yet supported, but they should be.
957
-
958
978
if (auto boundGenericType = type->getAs <BoundGenericType>()) {
959
979
if (boundGenericType->getGenericArgs ().size () != 1 )
960
980
// Must've got something other than a T?, *Pointer<T>, or SIMD*<T>
@@ -968,8 +988,8 @@ clang::QualType ClangTypeConverter::convertTemplateArgument(Type type) {
968
988
auto pointeeType = argType->getAs <BoundGenericType>()
969
989
->getGenericArgs ()[0 ]
970
990
->getCanonicalType ();
971
- return convertPointerType (pointeeType, kind. value () ,
972
- /* templateArgument= */ true );
991
+ return convertPointerType< /* templateArgument= */ true > (pointeeType,
992
+ kind. value () );
973
993
});
974
994
975
995
// Arbitrary optional types are not (yet) supported
@@ -978,19 +998,31 @@ clang::QualType ClangTypeConverter::convertTemplateArgument(Type type) {
978
998
979
999
if (auto kind = classifyPointer (boundGenericType))
980
1000
return withCache ([&]() {
981
- return convertPointerType (argType, kind. value () ,
982
- /* templateArgument= */ true );
1001
+ return convertPointerType< /* templateArgument= */ true > (argType,
1002
+ kind. value () );
983
1003
});
984
1004
985
1005
if (auto width = classifySIMD (boundGenericType))
986
1006
return withCache ([&]() {
987
- return convertSIMDType (argType, width. value () ,
988
- /* templateArgument= */ true );
1007
+ return convertSIMDType< /* templateArgument= */ true > (argType,
1008
+ width. value () );
989
1009
});
990
1010
991
1011
return clang::QualType ();
992
1012
}
993
1013
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
+
994
1026
// Most types cannot be used to instantiate C++ function templates; give up.
995
1027
return clang::QualType ();
996
1028
}
0 commit comments