@@ -41,6 +41,7 @@ class FunctionType;
41
41
class SILExtInfo ;
42
42
class SILExtInfoBuilder ;
43
43
class SILFunctionType ;
44
+ enum class SILFunctionTypeRepresentation : uint8_t ;
44
45
} // namespace swift
45
46
46
47
namespace swift {
@@ -54,6 +55,7 @@ class ClangTypeInfo {
54
55
friend ASTExtInfoBuilder;
55
56
friend SILExtInfoBuilder;
56
57
58
+ // [NOTE: ClangTypeInfo-contents]
57
59
// We preserve a full clang::Type *, not a clang::FunctionType * as:
58
60
// 1. We need to keep sugar in case we need to present an error to the user
59
61
// (for AnyFunctionType).
@@ -81,6 +83,26 @@ class ClangTypeInfo {
81
83
void dump (llvm::raw_ostream &os, const clang::ASTContext &ctx) const ;
82
84
};
83
85
86
+ // MARK: - UnexpectedClangTypeError
87
+ // / Potential errors when trying to store a Clang type in an ExtInfo.
88
+ struct UnexpectedClangTypeError {
89
+ enum class Kind {
90
+ NullForCOrBlock,
91
+ NonnullForNonCOrBlock,
92
+ NotBlockPointer,
93
+ NotFunctionPointerOrReference,
94
+ NonCanonical,
95
+ };
96
+ const Kind errorKind;
97
+ const clang::Type *type;
98
+
99
+ static Optional<UnexpectedClangTypeError> checkClangType (
100
+ SILFunctionTypeRepresentation fnRep, const clang::Type *type,
101
+ bool expectNonnullForCOrBlock, bool expectCanonical);
102
+
103
+ void dump ();
104
+ };
105
+
84
106
// MARK: - FunctionTypeRepresentation
85
107
// / The representation form of a function.
86
108
enum class FunctionTypeRepresentation : uint8_t {
@@ -146,6 +168,41 @@ enum class SILFunctionTypeRepresentation : uint8_t {
146
168
Closure,
147
169
};
148
170
171
+ constexpr SILFunctionTypeRepresentation
172
+ convertRepresentation (FunctionTypeRepresentation rep) {
173
+ switch (rep) {
174
+ case FunctionTypeRepresentation::Swift:
175
+ return SILFunctionTypeRepresentation::Thick;
176
+ case FunctionTypeRepresentation::Block:
177
+ return SILFunctionTypeRepresentation::Block;
178
+ case FunctionTypeRepresentation::Thin:
179
+ return SILFunctionTypeRepresentation::Thin;
180
+ case FunctionTypeRepresentation::CFunctionPointer:
181
+ return SILFunctionTypeRepresentation::CFunctionPointer;
182
+ }
183
+ llvm_unreachable (" Unhandled FunctionTypeRepresentation!" );
184
+ };
185
+
186
+ inline Optional<FunctionTypeRepresentation>
187
+ convertRepresentation (SILFunctionTypeRepresentation rep) {
188
+ switch (rep) {
189
+ case SILFunctionTypeRepresentation::Thick:
190
+ return {FunctionTypeRepresentation::Swift};
191
+ case SILFunctionTypeRepresentation::Block:
192
+ return {FunctionTypeRepresentation::Block};
193
+ case SILFunctionTypeRepresentation::Thin:
194
+ return {FunctionTypeRepresentation::Thin};
195
+ case SILFunctionTypeRepresentation::CFunctionPointer:
196
+ return {FunctionTypeRepresentation::CFunctionPointer};
197
+ case SILFunctionTypeRepresentation::Method:
198
+ case SILFunctionTypeRepresentation::ObjCMethod:
199
+ case SILFunctionTypeRepresentation::WitnessMethod:
200
+ case SILFunctionTypeRepresentation::Closure:
201
+ return None;
202
+ }
203
+ llvm_unreachable (" Unhandled SILFunctionTypeRepresentation!" );
204
+ };
205
+
149
206
// / Can this calling convention result in a function being called indirectly
150
207
// / through the runtime.
151
208
constexpr bool canBeCalledIndirectly (SILFunctionTypeRepresentation rep) {
@@ -165,6 +222,25 @@ constexpr bool canBeCalledIndirectly(SILFunctionTypeRepresentation rep) {
165
222
llvm_unreachable (" Unhandled SILFunctionTypeRepresentation in switch." );
166
223
}
167
224
225
+ template <typename Repr> constexpr bool shouldStoreClangType (Repr repr) {
226
+ static_assert (std::is_same<Repr, FunctionTypeRepresentation>::value ||
227
+ std::is_same<Repr, SILFunctionTypeRepresentation>::value,
228
+ " Expected a Representation type as the argument type." );
229
+ switch (static_cast <SILFunctionTypeRepresentation>(repr)) {
230
+ case SILFunctionTypeRepresentation::CFunctionPointer:
231
+ case SILFunctionTypeRepresentation::Block:
232
+ return true ;
233
+ case SILFunctionTypeRepresentation::ObjCMethod:
234
+ case SILFunctionTypeRepresentation::Thick:
235
+ case SILFunctionTypeRepresentation::Thin:
236
+ case SILFunctionTypeRepresentation::Method:
237
+ case SILFunctionTypeRepresentation::WitnessMethod:
238
+ case SILFunctionTypeRepresentation::Closure:
239
+ return false ;
240
+ }
241
+ llvm_unreachable (" Unhandled SILFunctionTypeRepresentation." );
242
+ }
243
+
168
244
// MARK: - ASTExtInfoBuilder
169
245
// / A builder type for creating an \c ASTExtInfo.
170
246
// /
@@ -292,7 +368,8 @@ class ASTExtInfoBuilder {
292
368
LLVM_NODISCARD
293
369
ASTExtInfoBuilder withRepresentation (Representation rep) const {
294
370
return ASTExtInfoBuilder ((bits & ~RepresentationMask) | (unsigned )rep,
295
- clangTypeInfo);
371
+ shouldStoreClangType (rep) ? clangTypeInfo
372
+ : ClangTypeInfo ());
296
373
}
297
374
LLVM_NODISCARD
298
375
ASTExtInfoBuilder withNoEscape (bool noEscape = true ) const {
@@ -333,7 +410,8 @@ class ASTExtInfoBuilder {
333
410
ASTExtInfoBuilder
334
411
withSILRepresentation (SILFunctionTypeRepresentation rep) const {
335
412
return ASTExtInfoBuilder ((bits & ~RepresentationMask) | (unsigned )rep,
336
- clangTypeInfo);
413
+ shouldStoreClangType (rep) ? clangTypeInfo
414
+ : ClangTypeInfo ());
337
415
}
338
416
339
417
bool isEqualTo (ASTExtInfoBuilder other, bool useClangTypes) const {
@@ -360,12 +438,16 @@ class ASTExtInfo {
360
438
361
439
ASTExtInfoBuilder builder;
362
440
441
+ // Only for use by ASTExtInfoBuilder::build. Don't use it elsewhere!
363
442
ASTExtInfo (ASTExtInfoBuilder builder) : builder(builder) {}
443
+
364
444
ASTExtInfo (unsigned bits, ClangTypeInfo clangTypeInfo)
365
- : builder(bits, clangTypeInfo){};
445
+ : builder(bits, clangTypeInfo) {
446
+ builder.checkInvariants ();
447
+ };
366
448
367
449
public:
368
- ASTExtInfo () : builder(){ };
450
+ ASTExtInfo () : builder() { builder. checkInvariants (); };
369
451
370
452
// / Create a builder with the same state as \c this.
371
453
ASTExtInfoBuilder intoBuilder () const { return builder; }
@@ -504,7 +586,7 @@ class SILExtInfoBuilder {
504
586
using Representation = SILFunctionTypeRepresentation;
505
587
506
588
SILExtInfoBuilder (unsigned bits, ClangTypeInfo clangTypeInfo)
507
- : bits(bits), clangTypeInfo(clangTypeInfo) {}
589
+ : bits(bits), clangTypeInfo(clangTypeInfo.getCanonical() ) {}
508
590
509
591
static constexpr unsigned makeBits (Representation rep, bool isPseudogeneric,
510
592
bool isNoEscape, bool isAsync,
@@ -606,7 +688,8 @@ class SILExtInfoBuilder {
606
688
// the following with methods instead of mutating these objects.
607
689
SILExtInfoBuilder withRepresentation (Representation rep) const {
608
690
return SILExtInfoBuilder ((bits & ~RepresentationMask) | (unsigned )rep,
609
- clangTypeInfo);
691
+ shouldStoreClangType (rep) ? clangTypeInfo
692
+ : ClangTypeInfo ());
610
693
}
611
694
SILExtInfoBuilder withIsPseudogeneric (bool isPseudogeneric = true ) const {
612
695
return SILExtInfoBuilder (isPseudogeneric ? (bits | PseudogenericMask)
@@ -629,6 +712,10 @@ class SILExtInfoBuilder {
629
712
((unsigned )differentiability << DifferentiabilityMaskOffset),
630
713
clangTypeInfo);
631
714
}
715
+ LLVM_NODISCARD
716
+ SILExtInfoBuilder withClangFunctionType (const clang::Type *type) const {
717
+ return SILExtInfoBuilder (bits, ClangTypeInfo (type).getCanonical ());
718
+ }
632
719
633
720
bool isEqualTo (SILExtInfoBuilder other, bool useClangTypes) const {
634
721
return bits == other.bits &&
@@ -654,12 +741,21 @@ class SILExtInfo {
654
741
655
742
SILExtInfoBuilder builder;
656
743
744
+ // Only for use by SILExtInfoBuilder::build. Don't use it elsewhere!
657
745
SILExtInfo (SILExtInfoBuilder builder) : builder(builder) {}
746
+
658
747
SILExtInfo (unsigned bits, ClangTypeInfo clangTypeInfo)
659
- : builder(bits, clangTypeInfo){};
748
+ : builder(bits, clangTypeInfo) {
749
+ builder.checkInvariants ();
750
+ };
660
751
661
752
public:
662
- SILExtInfo () : builder(){};
753
+ SILExtInfo () : builder() { builder.checkInvariants (); };
754
+
755
+ SILExtInfo (ASTExtInfo info, bool isPseudogeneric)
756
+ : builder(info.intoBuilder(), isPseudogeneric) {
757
+ builder.checkInvariants ();
758
+ }
663
759
664
760
static SILExtInfo getThin () {
665
761
return SILExtInfoBuilder (SILExtInfoBuilder::Representation::Thin, false ,
@@ -722,6 +818,8 @@ class SILExtInfo {
722
818
constexpr std::pair<unsigned , const void *> getFuncAttrKey () const {
723
819
return builder.getFuncAttrKey ();
724
820
}
821
+
822
+ Optional<UnexpectedClangTypeError> checkClangType () const ;
725
823
};
726
824
727
825
// / Helper function to obtain the useClangTypes parameter for checking equality
0 commit comments