@@ -41,6 +41,7 @@ class FunctionType;
4141class SILExtInfo ;
4242class SILExtInfoBuilder ;
4343class SILFunctionType ;
44+ enum class SILFunctionTypeRepresentation : uint8_t ;
4445} // namespace swift
4546
4647namespace swift {
@@ -54,6 +55,7 @@ class ClangTypeInfo {
5455 friend ASTExtInfoBuilder;
5556 friend SILExtInfoBuilder;
5657
58+ // [NOTE: ClangTypeInfo-contents]
5759 // We preserve a full clang::Type *, not a clang::FunctionType * as:
5860 // 1. We need to keep sugar in case we need to present an error to the user
5961 // (for AnyFunctionType).
@@ -81,6 +83,26 @@ class ClangTypeInfo {
8183 void dump (llvm::raw_ostream &os, const clang::ASTContext &ctx) const ;
8284};
8385
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+
84106// MARK: - FunctionTypeRepresentation
85107// / The representation form of a function.
86108enum class FunctionTypeRepresentation : uint8_t {
@@ -146,6 +168,41 @@ enum class SILFunctionTypeRepresentation : uint8_t {
146168 Closure,
147169};
148170
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+
149206// / Can this calling convention result in a function being called indirectly
150207// / through the runtime.
151208constexpr bool canBeCalledIndirectly (SILFunctionTypeRepresentation rep) {
@@ -165,6 +222,25 @@ constexpr bool canBeCalledIndirectly(SILFunctionTypeRepresentation rep) {
165222 llvm_unreachable (" Unhandled SILFunctionTypeRepresentation in switch." );
166223}
167224
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+
168244// MARK: - ASTExtInfoBuilder
169245// / A builder type for creating an \c ASTExtInfo.
170246// /
@@ -292,7 +368,8 @@ class ASTExtInfoBuilder {
292368 LLVM_NODISCARD
293369 ASTExtInfoBuilder withRepresentation (Representation rep) const {
294370 return ASTExtInfoBuilder ((bits & ~RepresentationMask) | (unsigned )rep,
295- clangTypeInfo);
371+ shouldStoreClangType (rep) ? clangTypeInfo
372+ : ClangTypeInfo ());
296373 }
297374 LLVM_NODISCARD
298375 ASTExtInfoBuilder withNoEscape (bool noEscape = true ) const {
@@ -333,7 +410,8 @@ class ASTExtInfoBuilder {
333410 ASTExtInfoBuilder
334411 withSILRepresentation (SILFunctionTypeRepresentation rep) const {
335412 return ASTExtInfoBuilder ((bits & ~RepresentationMask) | (unsigned )rep,
336- clangTypeInfo);
413+ shouldStoreClangType (rep) ? clangTypeInfo
414+ : ClangTypeInfo ());
337415 }
338416
339417 bool isEqualTo (ASTExtInfoBuilder other, bool useClangTypes) const {
@@ -360,12 +438,16 @@ class ASTExtInfo {
360438
361439 ASTExtInfoBuilder builder;
362440
441+ // Only for use by ASTExtInfoBuilder::build. Don't use it elsewhere!
363442 ASTExtInfo (ASTExtInfoBuilder builder) : builder(builder) {}
443+
364444 ASTExtInfo (unsigned bits, ClangTypeInfo clangTypeInfo)
365- : builder(bits, clangTypeInfo){};
445+ : builder(bits, clangTypeInfo) {
446+ builder.checkInvariants ();
447+ };
366448
367449public:
368- ASTExtInfo () : builder(){ };
450+ ASTExtInfo () : builder() { builder. checkInvariants (); };
369451
370452 // / Create a builder with the same state as \c this.
371453 ASTExtInfoBuilder intoBuilder () const { return builder; }
@@ -504,7 +586,7 @@ class SILExtInfoBuilder {
504586 using Representation = SILFunctionTypeRepresentation;
505587
506588 SILExtInfoBuilder (unsigned bits, ClangTypeInfo clangTypeInfo)
507- : bits(bits), clangTypeInfo(clangTypeInfo) {}
589+ : bits(bits), clangTypeInfo(clangTypeInfo.getCanonical() ) {}
508590
509591 static constexpr unsigned makeBits (Representation rep, bool isPseudogeneric,
510592 bool isNoEscape, bool isAsync,
@@ -606,7 +688,8 @@ class SILExtInfoBuilder {
606688 // the following with methods instead of mutating these objects.
607689 SILExtInfoBuilder withRepresentation (Representation rep) const {
608690 return SILExtInfoBuilder ((bits & ~RepresentationMask) | (unsigned )rep,
609- clangTypeInfo);
691+ shouldStoreClangType (rep) ? clangTypeInfo
692+ : ClangTypeInfo ());
610693 }
611694 SILExtInfoBuilder withIsPseudogeneric (bool isPseudogeneric = true ) const {
612695 return SILExtInfoBuilder (isPseudogeneric ? (bits | PseudogenericMask)
@@ -629,6 +712,10 @@ class SILExtInfoBuilder {
629712 ((unsigned )differentiability << DifferentiabilityMaskOffset),
630713 clangTypeInfo);
631714 }
715+ LLVM_NODISCARD
716+ SILExtInfoBuilder withClangFunctionType (const clang::Type *type) const {
717+ return SILExtInfoBuilder (bits, ClangTypeInfo (type).getCanonical ());
718+ }
632719
633720 bool isEqualTo (SILExtInfoBuilder other, bool useClangTypes) const {
634721 return bits == other.bits &&
@@ -654,12 +741,21 @@ class SILExtInfo {
654741
655742 SILExtInfoBuilder builder;
656743
744+ // Only for use by SILExtInfoBuilder::build. Don't use it elsewhere!
657745 SILExtInfo (SILExtInfoBuilder builder) : builder(builder) {}
746+
658747 SILExtInfo (unsigned bits, ClangTypeInfo clangTypeInfo)
659- : builder(bits, clangTypeInfo){};
748+ : builder(bits, clangTypeInfo) {
749+ builder.checkInvariants ();
750+ };
660751
661752public:
662- SILExtInfo () : builder(){};
753+ SILExtInfo () : builder() { builder.checkInvariants (); };
754+
755+ SILExtInfo (ASTExtInfo info, bool isPseudogeneric)
756+ : builder(info.intoBuilder(), isPseudogeneric) {
757+ builder.checkInvariants ();
758+ }
663759
664760 static SILExtInfo getThin () {
665761 return SILExtInfoBuilder (SILExtInfoBuilder::Representation::Thin, false ,
@@ -722,6 +818,8 @@ class SILExtInfo {
722818 constexpr std::pair<unsigned , const void *> getFuncAttrKey () const {
723819 return builder.getFuncAttrKey ();
724820 }
821+
822+ Optional<UnexpectedClangTypeError> checkClangType () const ;
725823};
726824
727825// / Helper function to obtain the useClangTypes parameter for checking equality
0 commit comments