Skip to content

Commit afc6ccd

Browse files
Re-land parsing and printing for Clang function types.
This reverts commit e805fe4, which reverted the change earlier. The problem was caused due to a simultaneous change to some code by the PR with parsing and printing for Clang function types (#28737) and the PR which introduced Located<T> (#28643). This commit also includes a small change to make sure the intersecting region is fixed: the change is limited to using the fields of Located<T> in the `tryParseClangType` lambda.
1 parent 6e7521a commit afc6ccd

22 files changed

+274
-22
lines changed

include/swift/AST/ASTPrinter.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define SWIFT_AST_ASTPRINTER_H
1515

1616
#include "swift/Basic/LLVM.h"
17+
#include "swift/Basic/QuotedString.h"
1718
#include "swift/Basic/UUID.h"
1819
#include "swift/AST/Identifier.h"
1920
#include "llvm/ADT/StringRef.h"
@@ -185,6 +186,8 @@ class ASTPrinter {
185186
return *this;
186187
}
187188

189+
ASTPrinter &operator<<(QuotedString s);
190+
188191
ASTPrinter &operator<<(unsigned long long N);
189192
ASTPrinter &operator<<(UUID UU);
190193

include/swift/AST/ClangModuleLoader.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class CompilerInstance;
2121
class Preprocessor;
2222
class Sema;
2323
class TargetInfo;
24+
class Type;
2425
} // namespace clang
2526

2627
namespace swift {
@@ -100,6 +101,16 @@ class ClangModuleLoader : public ModuleLoader {
100101
lookupRelatedEntity(StringRef clangName, ClangTypeKind kind,
101102
StringRef relatedEntityKind,
102103
llvm::function_ref<void(TypeDecl *)> receiver) = 0;
104+
105+
/// Try to parse the string as a Clang function type.
106+
///
107+
/// Returns null if there was a parsing failure.
108+
virtual const clang::Type *parseClangFunctionType(StringRef type,
109+
SourceLoc loc) const = 0;
110+
111+
/// Print the Clang type.
112+
virtual void printClangType(const clang::Type *type,
113+
llvm::raw_ostream &os) const = 0;
103114
};
104115

105116
} // namespace swift

include/swift/AST/DiagnosticsSema.def

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3924,6 +3924,13 @@ ERROR(unsupported_convention,none,
39243924
"convention '%0' not supported", (StringRef))
39253925
ERROR(unreferenced_generic_parameter,none,
39263926
"generic parameter '%0' is not used in function signature", (StringRef))
3927+
ERROR(unexpected_ctype_for_non_c_convention,none,
3928+
"convention '%0' does not support the 'cType' argument label, did you "
3929+
"mean @convention(c, cType: \"%1\") or @convention(block, cType: \"%1\") "
3930+
"instead?", (StringRef, StringRef))
3931+
ERROR(unable_to_parse_c_function_type,none,
3932+
"unable to parse '%0'; it should be a C function pointer type or a "
3933+
"block pointer type", (StringRef))
39273934

39283935
// Opaque types
39293936
ERROR(unsupported_opaque_type,none,

include/swift/AST/PrintOptions.h

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -306,8 +306,21 @@ struct PrintOptions {
306306
/// List of decls that should be printed even if they are implicit and \c SkipImplicit is set to true.
307307
std::vector<const Decl*> TreatAsExplicitDeclList;
308308

309+
enum class FunctionRepresentationMode : uint8_t {
310+
/// Print the entire convention, including an arguments.
311+
/// For example, this will print a cType argument label if applicable.
312+
Full,
313+
/// Print only the name of the convention, skipping extra argument labels.
314+
NameOnly,
315+
/// Skip printing the @convention(..) altogether.
316+
None
317+
};
318+
309319
/// Whether to print function @convention attribute on function types.
310-
bool PrintFunctionRepresentationAttrs = true;
320+
// FIXME: [clang-function-type-serialization] Once we start serializing Clang
321+
// types, we should also start printing the full type in the swiftinterface.
322+
FunctionRepresentationMode PrintFunctionRepresentationAttrs =
323+
FunctionRepresentationMode::NameOnly;
311324

312325
/// Whether to print storage representation attributes on types, e.g.
313326
/// '@sil_weak', '@sil_unmanaged'.
@@ -502,7 +515,8 @@ struct PrintOptions {
502515
/// consistent and well-formed.
503516
///
504517
/// \see swift::emitSwiftInterface
505-
static PrintOptions printSwiftInterfaceFile(bool preferTypeRepr);
518+
static PrintOptions printSwiftInterfaceFile(bool preferTypeRepr,
519+
bool printFullConvention);
506520

507521
/// Retrieve the set of options suitable for "Generated Interfaces", which
508522
/// are a prettified representation of the public API of a module, to be
@@ -585,7 +599,8 @@ struct PrintOptions {
585599
PO.SkipUnderscoredKeywords = true;
586600
PO.EnumRawValues = EnumRawValueMode::Print;
587601
PO.PrintImplicitAttrs = false;
588-
PO.PrintFunctionRepresentationAttrs = false;
602+
PO.PrintFunctionRepresentationAttrs =
603+
PrintOptions::FunctionRepresentationMode::None;
589604
PO.PrintDocumentationComments = false;
590605
PO.ExcludeAttrList.push_back(DAK_Available);
591606
PO.SkipPrivateStdlibDecls = true;

include/swift/AST/Types.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ class AssociatedTypeDecl;
5959
class ASTContext;
6060
enum BufferPointerTypeKind : unsigned;
6161
class ClassDecl;
62+
class ClangModuleLoader;
6263
class DependentMemberType;
6364
class GenericTypeParamDecl;
6465
class GenericTypeParamType;
@@ -2950,6 +2951,11 @@ class AnyFunctionType : public TypeBase {
29502951

29512952
bool empty() const { return !ClangFunctionType; }
29522953
Uncommon(const clang::Type *type) : ClangFunctionType(type) {}
2954+
2955+
public:
2956+
/// Use the ClangModuleLoader to print the Clang type as a string.
2957+
void printClangFunctionType(ClangModuleLoader *cml,
2958+
llvm::raw_ostream &os);
29532959
};
29542960

29552961
private:
@@ -3894,6 +3900,11 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode,
38943900

38953901
bool empty() const { return !ClangFunctionType; }
38963902
Uncommon(const clang::FunctionType *type) : ClangFunctionType(type) {}
3903+
3904+
public:
3905+
/// Analog of AnyFunctionType::ExtInfo::Uncommon::printClangFunctionType.
3906+
void printClangFunctionType(ClangModuleLoader *cml,
3907+
llvm::raw_ostream &os) const;
38973908
};
38983909

38993910
Uncommon Other;
@@ -3947,6 +3958,11 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode,
39473958
return getSILFunctionLanguage(getRepresentation());
39483959
}
39493960

3961+
/// Return the underlying Uncommon value if it is not the default value.
3962+
Optional<Uncommon> getUncommonInfo() const {
3963+
return Other.empty() ? Optional<Uncommon>() : Other;
3964+
}
3965+
39503966
bool hasSelfParam() const {
39513967
switch (getRepresentation()) {
39523968
case Representation::Thick:

include/swift/ClangImporter/ClangImporter.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ namespace clang {
4040
class NamedDecl;
4141
class Sema;
4242
class TargetInfo;
43+
class Type;
4344
class VisibleDeclConsumer;
4445
class DeclarationName;
4546
}
@@ -416,6 +417,11 @@ class ClangImporter final : public ClangModuleLoader {
416417
/// with -import-objc-header option.
417418
getPCHFilename(const ClangImporterOptions &ImporterOptions,
418419
StringRef SwiftPCHHash, bool &isExplicit);
420+
421+
const clang::Type *parseClangFunctionType(StringRef type,
422+
SourceLoc loc) const override;
423+
void printClangType(const clang::Type *type,
424+
llvm::raw_ostream &os) const override;
419425
};
420426

421427
ImportDecl *createImportDecl(ASTContext &Ctx, DeclContext *DC, ClangNode ClangN,

include/swift/Frontend/ModuleInterfaceSupport.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ struct ModuleInterfaceOptions {
3131
/// interface, or should we fully-qualify them?
3232
bool PreserveTypesAsWritten = false;
3333

34+
/// Should we emit the cType when printing @convention(c) or no?
35+
/// FIXME: [clang-function-type-serialization] This check should go away.
36+
bool PrintFullConvention = false;
37+
3438
/// Copy of all the command-line flags passed at .swiftinterface
3539
/// generation time, re-applied to CompilerInvocation when reading
3640
/// back .swiftinterface and reconstructing .swiftmodule.

include/swift/Option/FrontendOptions.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,11 @@ def module_interface_preserve_types_as_written :
602602
HelpText<"When emitting a module interface, preserve types as they were "
603603
"written in the source">;
604604

605+
def experimental_print_full_convention :
606+
Flag<["-"], "experimental-print-full-convention">,
607+
HelpText<"When emitting a module interface, emit additional @convention "
608+
"arguments, regardless of whether they were written in the source">;
609+
605610
def prebuilt_module_cache_path :
606611
Separate<["-"], "prebuilt-module-cache-path">,
607612
HelpText<"Directory of prebuilt modules for loading module interfaces">;

lib/AST/ASTContext.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3156,6 +3156,11 @@ ArrayRef<Requirement> GenericFunctionType::getRequirements() const {
31563156
return Signature->getRequirements();
31573157
}
31583158

3159+
void SILFunctionType::ExtInfo::Uncommon::printClangFunctionType(
3160+
ClangModuleLoader *cml, llvm::raw_ostream &os) const {
3161+
cml->printClangType(ClangFunctionType, os);
3162+
}
3163+
31593164
void SILFunctionType::Profile(
31603165
llvm::FoldingSetNodeID &id,
31613166
GenericSignature genericParams,

lib/AST/ASTPrinter.cpp

Lines changed: 64 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "swift/AST/ASTMangler.h"
2020
#include "swift/AST/ASTVisitor.h"
2121
#include "swift/AST/Attr.h"
22+
#include "swift/AST/ClangModuleLoader.h"
2223
#include "swift/AST/Comment.h"
2324
#include "swift/AST/Decl.h"
2425
#include "swift/AST/Expr.h"
@@ -98,7 +99,8 @@ static bool contributesToParentTypeStorage(const AbstractStorageDecl *ASD) {
9899
return !ND->isResilient() && ASD->hasStorage() && !ASD->isStatic();
99100
}
100101

101-
PrintOptions PrintOptions::printSwiftInterfaceFile(bool preferTypeRepr) {
102+
PrintOptions PrintOptions::printSwiftInterfaceFile(bool preferTypeRepr,
103+
bool printFullConvention) {
102104
PrintOptions result;
103105
result.PrintLongAttrsOnSeparateLines = true;
104106
result.TypeDefinitions = true;
@@ -115,6 +117,9 @@ PrintOptions PrintOptions::printSwiftInterfaceFile(bool preferTypeRepr) {
115117
result.OpaqueReturnTypePrinting =
116118
OpaqueReturnTypePrintingMode::StableReference;
117119
result.PreferTypeRepr = preferTypeRepr;
120+
if (printFullConvention)
121+
result.PrintFunctionRepresentationAttrs =
122+
PrintOptions::FunctionRepresentationMode::Full;
118123

119124
// We should print __consuming, __owned, etc for the module interface file.
120125
result.SkipUnderscoredKeywords = false;
@@ -321,6 +326,14 @@ void ASTPrinter::callPrintDeclPre(const Decl *D,
321326
printDeclPre(D, Bracket);
322327
}
323328

329+
ASTPrinter &ASTPrinter::operator<<(QuotedString s) {
330+
llvm::SmallString<32> Str;
331+
llvm::raw_svector_ostream OS(Str);
332+
OS << s;
333+
printTextImpl(OS.str());
334+
return *this;
335+
}
336+
324337
ASTPrinter &ASTPrinter::operator<<(unsigned long long N) {
325338
llvm::SmallString<32> Str;
326339
llvm::raw_svector_ostream OS(Str);
@@ -3478,6 +3491,15 @@ void Pattern::print(llvm::raw_ostream &OS, const PrintOptions &Options) const {
34783491
// Type Printing
34793492
//===----------------------------------------------------------------------===//
34803493

3494+
template <typename ExtInfo>
3495+
void printCType(ASTContext &Ctx, ASTPrinter &Printer, ExtInfo &info) {
3496+
auto *cml = Ctx.getClangModuleLoader();
3497+
SmallString<64> buf;
3498+
llvm::raw_svector_ostream os(buf);
3499+
info.getUncommonInfo().getValue().printClangFunctionType(cml, os);
3500+
Printer << ", cType: " << QuotedString(os.str());
3501+
}
3502+
34813503
namespace {
34823504
class TypePrinter : public TypeVisitor<TypePrinter> {
34833505
using super = TypeVisitor;
@@ -3840,7 +3862,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
38403862
visit(staticSelfT);
38413863
}
38423864

3843-
void printFunctionExtInfo(AnyFunctionType::ExtInfo info) {
3865+
void printFunctionExtInfo(ASTContext &Ctx, AnyFunctionType::ExtInfo info) {
38443866
if (Options.SkipAttributes)
38453867
return;
38463868

@@ -3853,9 +3875,18 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
38533875
}
38543876
}
38553877

3856-
if (Options.PrintFunctionRepresentationAttrs &&
3857-
!Options.excludeAttrKind(TAK_convention) &&
3858-
info.getSILRepresentation() != SILFunctionType::Representation::Thick) {
3878+
SmallString<64> buf;
3879+
switch (Options.PrintFunctionRepresentationAttrs) {
3880+
case PrintOptions::FunctionRepresentationMode::None:
3881+
return;
3882+
case PrintOptions::FunctionRepresentationMode::Full:
3883+
case PrintOptions::FunctionRepresentationMode::NameOnly:
3884+
if (Options.excludeAttrKind(TAK_convention) ||
3885+
info.getSILRepresentation() == SILFunctionType::Representation::Thick)
3886+
return;
3887+
3888+
bool printNameOnly = Options.PrintFunctionRepresentationAttrs ==
3889+
PrintOptions::FunctionRepresentationMode::NameOnly;
38593890
Printer.callPrintStructurePre(PrintStructureKind::BuiltinAttribute);
38603891
Printer.printAttrName("@convention");
38613892
Printer << "(";
@@ -3871,6 +3902,11 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
38713902
break;
38723903
case SILFunctionType::Representation::CFunctionPointer:
38733904
Printer << "c";
3905+
// FIXME: [clang-function-type-serialization] Once we start serializing
3906+
// Clang function types, we should be able to remove the second check.
3907+
if (printNameOnly || !info.getUncommonInfo().hasValue())
3908+
break;
3909+
printCType(Ctx, Printer, info);
38743910
break;
38753911
case SILFunctionType::Representation::Method:
38763912
Printer << "method";
@@ -3891,7 +3927,8 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
38913927
}
38923928
}
38933929

3894-
void printFunctionExtInfo(SILFunctionType::ExtInfo info,
3930+
void printFunctionExtInfo(ASTContext &Ctx,
3931+
SILFunctionType::ExtInfo info,
38953932
ProtocolConformanceRef witnessMethodConformance) {
38963933
if (Options.SkipAttributes)
38973934
return;
@@ -3905,9 +3942,19 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
39053942
}
39063943
}
39073944

3908-
if (Options.PrintFunctionRepresentationAttrs &&
3909-
!Options.excludeAttrKind(TAK_convention) &&
3910-
info.getRepresentation() != SILFunctionType::Representation::Thick) {
3945+
3946+
SmallString<64> buf;
3947+
switch (Options.PrintFunctionRepresentationAttrs) {
3948+
case PrintOptions::FunctionRepresentationMode::None:
3949+
break;
3950+
case PrintOptions::FunctionRepresentationMode::NameOnly:
3951+
case PrintOptions::FunctionRepresentationMode::Full:
3952+
if (Options.excludeAttrKind(TAK_convention) ||
3953+
info.getRepresentation() == SILFunctionType::Representation::Thick)
3954+
break;
3955+
3956+
bool printNameOnly = Options.PrintFunctionRepresentationAttrs ==
3957+
PrintOptions::FunctionRepresentationMode::NameOnly;
39113958
Printer.callPrintStructurePre(PrintStructureKind::BuiltinAttribute);
39123959
Printer.printAttrName("@convention");
39133960
Printer << "(";
@@ -3922,6 +3969,11 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
39223969
break;
39233970
case SILFunctionType::Representation::CFunctionPointer:
39243971
Printer << "c";
3972+
// FIXME: [clang-function-type-serialization] Once we start serializing
3973+
// Clang function types, we should be able to remove the second check.
3974+
if (printNameOnly || !info.getUncommonInfo().hasValue())
3975+
break;
3976+
printCType(Ctx, Printer, info);
39253977
break;
39263978
case SILFunctionType::Representation::Method:
39273979
Printer << "method";
@@ -3991,7 +4043,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
39914043
Printer.printStructurePost(PrintStructureKind::FunctionType);
39924044
};
39934045

3994-
printFunctionExtInfo(T->getExtInfo());
4046+
printFunctionExtInfo(T->getASTContext(), T->getExtInfo());
39954047

39964048
// If we're stripping argument labels from types, do it when printing.
39974049
visitAnyFunctionTypeParams(T->getParams(), /*printLabels*/false);
@@ -4028,7 +4080,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
40284080
Printer.printStructurePost(PrintStructureKind::FunctionType);
40294081
};
40304082

4031-
printFunctionExtInfo(T->getExtInfo());
4083+
printFunctionExtInfo(T->getASTContext(), T->getExtInfo());
40324084
printGenericSignature(T->getGenericSignature(),
40334085
PrintAST::PrintParams |
40344086
PrintAST::PrintRequirements);
@@ -4081,7 +4133,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
40814133

40824134
void visitSILFunctionType(SILFunctionType *T) {
40834135
printSILCoroutineKind(T->getCoroutineKind());
4084-
printFunctionExtInfo(T->getExtInfo(),
4136+
printFunctionExtInfo(T->getASTContext(), T->getExtInfo(),
40854137
T->getWitnessMethodConformanceOrInvalid());
40864138
printCalleeConvention(T->getCalleeConvention());
40874139

lib/AST/Type.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "swift/AST/Types.h"
1818
#include "ForeignRepresentationInfo.h"
1919
#include "swift/AST/ASTContext.h"
20+
#include "swift/AST/ClangModuleLoader.h"
2021
#include "swift/AST/ExistentialLayout.h"
2122
#include "swift/AST/ReferenceCounting.h"
2223
#include "swift/AST/TypeCheckRequests.h"
@@ -3239,6 +3240,11 @@ Type ProtocolCompositionType::get(const ASTContext &C,
32393240
return build(C, CanTypes, HasExplicitAnyObject);
32403241
}
32413242

3243+
void AnyFunctionType::ExtInfo::Uncommon::printClangFunctionType(
3244+
ClangModuleLoader *cml, llvm::raw_ostream &os) {
3245+
cml->printClangType(ClangFunctionType, os);
3246+
}
3247+
32423248
void
32433249
AnyFunctionType::ExtInfo::assertIsFunctionType(const clang::Type *type) {
32443250
#ifndef NDEBUG

0 commit comments

Comments
 (0)