Skip to content

Commit b810077

Browse files
authored
Merge pull request #74339 from apple/gaborh/print-function-sig-transactional
[cxx-interop] Make function signature printing transactional
2 parents cd7e4c3 + cee81a4 commit b810077

File tree

2 files changed

+91
-78
lines changed

2 files changed

+91
-78
lines changed

lib/PrintAsClang/PrintClangFunction.cpp

Lines changed: 88 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -531,10 +531,10 @@ class CFunctionSignatureTypePrinter
531531

532532
ClangRepresentation
533533
DeclAndTypeClangFunctionPrinter::printClangFunctionReturnType(
534-
Type ty, OptionalTypeKind optKind, ModuleDecl *moduleContext,
535-
OutputLanguageMode outputLang) {
534+
raw_ostream &stream, Type ty, OptionalTypeKind optKind,
535+
ModuleDecl *moduleContext, OutputLanguageMode outputLang) {
536536
CFunctionSignatureTypePrinter typePrinter(
537-
os, cPrologueOS, typeMapping, outputLang, interopContext,
537+
stream, cPrologueOS, typeMapping, outputLang, interopContext,
538538
CFunctionSignatureTypePrinterModifierDelegate(), moduleContext,
539539
declPrinter, FunctionSignatureTypeUse::ReturnType);
540540
// Param for indirect return cannot be marked as inout
@@ -703,12 +703,14 @@ ClangRepresentation DeclAndTypeClangFunctionPrinter::printFunctionSignature(
703703
const AbstractFunctionDecl *FD, const LoweredFunctionSignature &signature,
704704
StringRef name, Type resultTy, FunctionSignatureKind kind,
705705
FunctionSignatureModifiers modifiers) {
706+
std::string functionSignature;
707+
llvm::raw_string_ostream functionSignatureOS(functionSignature);
706708
// Print any template and requires clauses for the
707709
// C++ class context to which this C++ member will belong to.
708710
if (const auto *typeDecl = modifiers.qualifierContext) {
709711
assert(kind == FunctionSignatureKind::CxxInlineThunk);
710-
ClangSyntaxPrinter(os).printNominalTypeOutsideMemberDeclTemplateSpecifiers(
711-
typeDecl);
712+
ClangSyntaxPrinter(functionSignatureOS)
713+
.printNominalTypeOutsideMemberDeclTemplateSpecifiers(typeDecl);
712714
}
713715
if (FD->isGeneric()) {
714716
auto Signature = FD->getGenericSignature().getCanonicalSignature();
@@ -717,7 +719,7 @@ ClangRepresentation DeclAndTypeClangFunctionPrinter::printFunctionSignature(
717719

718720
// Print the template and requires clauses for this function.
719721
if (kind == FunctionSignatureKind::CxxInlineThunk)
720-
ClangSyntaxPrinter(os).printGenericSignature(Signature);
722+
ClangSyntaxPrinter(functionSignatureOS).printGenericSignature(Signature);
721723
}
722724
if (const auto *enumDecl = FD->getDeclContext()->getSelfEnumDecl()) {
723725
// We cannot emit functions with the same name as an enum case yet, the resulting header
@@ -743,31 +745,31 @@ ClangRepresentation DeclAndTypeClangFunctionPrinter::printFunctionSignature(
743745
// FIXME: add support for noescape and PrintMultiPartType,
744746
// see DeclAndTypePrinter::print.
745747
CFunctionSignatureTypePrinter typePrinter(
746-
os, cPrologueOS, typeMapping, outputLang, interopContext, delegate,
747-
emittedModule, declPrinter);
748+
functionSignatureOS, cPrologueOS, typeMapping, outputLang,
749+
interopContext, delegate, emittedModule, declPrinter);
748750
auto result = typePrinter.visit(ty, optionalKind, isInOutParam);
749751

750752
if (!name.empty()) {
751-
os << ' ';
752-
ClangSyntaxPrinter(os).printIdentifier(name);
753+
functionSignatureOS << ' ';
754+
ClangSyntaxPrinter(functionSignatureOS).printIdentifier(name);
753755
}
754756
return result;
755757
};
756758

757759
// Print any modifiers before the signature.
758760
if (modifiers.isStatic) {
759761
assert(!modifiers.isConst);
760-
os << "static ";
762+
functionSignatureOS << "static ";
761763
}
762764
if (modifiers.isInline)
763-
ClangSyntaxPrinter(os).printInlineForThunk();
765+
ClangSyntaxPrinter(functionSignatureOS).printInlineForThunk();
764766

765767
ClangRepresentation resultingRepresentation =
766768
ClangRepresentation::representable;
767769

768770
// Print out the return type.
769771
if (FD->hasThrows() && outputLang == OutputLanguageMode::Cxx)
770-
os << "swift::ThrowingResult<";
772+
functionSignatureOS << "swift::ThrowingResult<";
771773
if (kind == FunctionSignatureKind::CFunctionProto) {
772774
// First, verify that the C++ return type is representable.
773775
{
@@ -794,19 +796,20 @@ ClangRepresentation DeclAndTypeClangFunctionPrinter::printFunctionSignature(
794796
return ClangRepresentation::unsupported;
795797

796798
if (!directResultType) {
797-
os << "void";
799+
functionSignatureOS << "void";
798800
} else {
799801
if (!printDirectReturnOrParamCType(
800-
*directResultType, resultTy, emittedModule, os, cPrologueOS,
801-
typeMapping, interopContext, [&]() {
802+
*directResultType, resultTy, emittedModule, functionSignatureOS,
803+
cPrologueOS, typeMapping, interopContext, [&]() {
802804
OptionalTypeKind retKind;
803805
Type objTy;
804806
std::tie(objTy, retKind) =
805807
DeclAndTypePrinter::getObjectTypeAndOptionality(FD,
806808
resultTy);
807809

808810
auto s = printClangFunctionReturnType(
809-
objTy, retKind, emittedModule, outputLang);
811+
functionSignatureOS, objTy, retKind, emittedModule,
812+
outputLang);
810813
assert(!s.isUnsupported());
811814
}))
812815
return ClangRepresentation::unsupported;
@@ -817,19 +820,19 @@ ClangRepresentation DeclAndTypeClangFunctionPrinter::printFunctionSignature(
817820
std::tie(objTy, retKind) =
818821
DeclAndTypePrinter::getObjectTypeAndOptionality(FD, resultTy);
819822
if (resultingRepresentation
820-
.merge(printClangFunctionReturnType(objTy, retKind, emittedModule,
821-
outputLang))
823+
.merge(printClangFunctionReturnType(
824+
functionSignatureOS, objTy, retKind, emittedModule, outputLang))
822825
.isUnsupported())
823826
return resultingRepresentation;
824827
}
825828
if (FD->hasThrows() && outputLang == OutputLanguageMode::Cxx)
826-
os << ">";
827-
os << ' ';
829+
functionSignatureOS << ">";
830+
functionSignatureOS << ' ';
828831
if (const auto *typeDecl = modifiers.qualifierContext)
829-
ClangSyntaxPrinter(os).printNominalTypeQualifier(
830-
typeDecl, typeDecl->getModuleContext());
831-
ClangSyntaxPrinter(os).printIdentifier(name);
832-
os << '(';
832+
ClangSyntaxPrinter(functionSignatureOS)
833+
.printNominalTypeQualifier(typeDecl, typeDecl->getModuleContext());
834+
ClangSyntaxPrinter(functionSignatureOS).printIdentifier(name);
835+
functionSignatureOS << '(';
833836

834837
bool HasParams = false;
835838

@@ -855,7 +858,7 @@ ClangRepresentation DeclAndTypeClangFunctionPrinter::printFunctionSignature(
855858
bool needsComma = false;
856859
auto emitNewParam = [&]() {
857860
if (needsComma)
858-
os << ", ";
861+
functionSignatureOS << ", ";
859862
needsComma = true;
860863
};
861864
auto printParamName = [&](const ParamDecl &param) {
@@ -864,8 +867,8 @@ ClangRepresentation DeclAndTypeClangFunctionPrinter::printFunctionSignature(
864867
if (param.isSelfParameter())
865868
paramName = "_self";
866869
if (!paramName.empty()) {
867-
os << ' ';
868-
ClangSyntaxPrinter(os).printIdentifier(paramName);
870+
functionSignatureOS << ' ';
871+
ClangSyntaxPrinter(functionSignatureOS).printIdentifier(paramName);
869872
}
870873
};
871874
auto printParamCType = [&](const ParamDecl &param) {
@@ -875,9 +878,9 @@ ClangRepresentation DeclAndTypeClangFunctionPrinter::printFunctionSignature(
875878
DeclAndTypePrinter::getObjectTypeAndOptionality(
876879
&param, param.getInterfaceType());
877880
CFunctionSignatureTypePrinter typePrinter(
878-
os, cPrologueOS, typeMapping, outputLang, interopContext,
879-
CFunctionSignatureTypePrinterModifierDelegate(), emittedModule,
880-
declPrinter);
881+
functionSignatureOS, cPrologueOS, typeMapping, outputLang,
882+
interopContext, CFunctionSignatureTypePrinterModifierDelegate(),
883+
emittedModule, declPrinter);
881884
auto s = typePrinter.visit(ty, optionalKind, param.isInOut());
882885
assert(!s.isUnsupported());
883886
};
@@ -886,22 +889,22 @@ ClangRepresentation DeclAndTypeClangFunctionPrinter::printFunctionSignature(
886889
&indirectResult) {
887890
emitNewParam();
888891
if (indirectResult.hasSRet())
889-
os << "SWIFT_INDIRECT_RESULT ";
892+
functionSignatureOS << "SWIFT_INDIRECT_RESULT ";
890893
// FIXME: it would be nice to print out the C struct type here.
891-
os << "void * _Nonnull";
894+
functionSignatureOS << "void * _Nonnull";
892895
},
893896
[&](const LoweredFunctionSignature::DirectParameter &param) {
894897
emitNewParam();
895898
printDirectReturnOrParamCType(
896-
param, param.getParamDecl().getInterfaceType(), emittedModule, os,
897-
cPrologueOS, typeMapping, interopContext,
899+
param, param.getParamDecl().getInterfaceType(), emittedModule,
900+
functionSignatureOS, cPrologueOS, typeMapping, interopContext,
898901
[&]() { printParamCType(param.getParamDecl()); });
899902
printParamName(param.getParamDecl());
900903
},
901904
[&](const LoweredFunctionSignature::IndirectParameter &param) {
902905
emitNewParam();
903906
if (param.getParamDecl().isSelfParameter())
904-
os << "SWIFT_CONTEXT ";
907+
functionSignatureOS << "SWIFT_CONTEXT ";
905908
bool isConst =
906909
!param.getParamDecl().isInOut() &&
907910
!(param.getParamDecl().isSelfParameter() &&
@@ -910,7 +913,7 @@ ClangRepresentation DeclAndTypeClangFunctionPrinter::printFunctionSignature(
910913
.getInterfaceType()
911914
->isAnyClassReferenceType());
912915
if (isConst)
913-
os << "const ";
916+
functionSignatureOS << "const ";
914917
if (isKnownCType(param.getParamDecl().getInterfaceType(),
915918
typeMapping) ||
916919
(!param.getParamDecl().getInterfaceType()->hasTypeParameter() &&
@@ -919,76 +922,86 @@ ClangRepresentation DeclAndTypeClangFunctionPrinter::printFunctionSignature(
919922
->isAnyClassReferenceType()))
920923
printParamCType(param.getParamDecl());
921924
else
922-
os << "void * _Nonnull";
925+
functionSignatureOS << "void * _Nonnull";
923926
printParamName(param.getParamDecl());
924927
},
925928
[&](const LoweredFunctionSignature::GenericRequirementParameter
926929
&genericRequirementParam) {
927930
emitNewParam();
928-
os << "void * _Nonnull ";
931+
functionSignatureOS << "void * _Nonnull ";
929932
auto reqt = genericRequirementParam.getRequirement();
930933
if (reqt.isAnyWitnessTable())
931-
ClangSyntaxPrinter(os).printBaseName(reqt.getProtocol());
934+
ClangSyntaxPrinter(functionSignatureOS)
935+
.printBaseName(reqt.getProtocol());
932936
else
933937
assert(reqt.isAnyMetadata());
934938
},
935939
[&](const LoweredFunctionSignature::MetadataSourceParameter
936940
&metadataSrcParam) {
937941
emitNewParam();
938-
os << "void * _Nonnull ";
942+
functionSignatureOS << "void * _Nonnull ";
939943
},
940944
[&](const LoweredFunctionSignature::ContextParameter &) {
941945
emitNewParam();
942-
os << "SWIFT_CONTEXT void * _Nonnull _ctx";
946+
functionSignatureOS << "SWIFT_CONTEXT void * _Nonnull _ctx";
943947
},
944948
[&](const LoweredFunctionSignature::ErrorResultValue &) {
945949
emitNewParam();
946-
os << "SWIFT_ERROR_RESULT void * _Nullable * _Nullable _error";
950+
functionSignatureOS
951+
<< "SWIFT_ERROR_RESULT void * _Nullable * _Nullable _error";
947952
});
948953
if (needsComma == false)
949954
// Emit 'void' in an empty parameter list for C function declarations.
950-
os << "void";
951-
os << ')';
955+
functionSignatureOS << "void";
956+
functionSignatureOS << ')';
957+
if (!resultingRepresentation.isUnsupported())
958+
os << functionSignatureOS.str();
952959
return resultingRepresentation;
953960
}
954961

955962
// Print out the C++ parameter types.
956963
auto params = FD->getParameters();
957964
if (params->size()) {
958965
if (HasParams)
959-
os << ", ";
966+
functionSignatureOS << ", ";
960967
HasParams = true;
961968
size_t paramIndex = 1;
962-
llvm::interleaveComma(*params, os, [&](const ParamDecl *param) {
963-
OptionalTypeKind argKind;
964-
Type objTy;
965-
std::tie(objTy, argKind) =
966-
DeclAndTypePrinter::getObjectTypeAndOptionality(
967-
param, param->getInterfaceType());
968-
std::string paramName =
969-
param->getName().empty() ? "" : param->getName().str().str();
970-
renameCxxParameterIfNeeded(FD, paramName);
971-
// Always emit a named parameter for the C++ inline thunk to ensure it
972-
// can be referenced in the body.
973-
if (kind == FunctionSignatureKind::CxxInlineThunk && paramName.empty()) {
974-
llvm::raw_string_ostream os(paramName);
975-
os << "_" << paramIndex;
976-
}
977-
resultingRepresentation.merge(
978-
print(objTy, argKind, paramName, param->isInOut()));
979-
++paramIndex;
980-
});
981-
if (resultingRepresentation.isUnsupported())
969+
llvm::interleaveComma(
970+
*params, functionSignatureOS, [&](const ParamDecl *param) {
971+
OptionalTypeKind argKind;
972+
Type objTy;
973+
std::tie(objTy, argKind) =
974+
DeclAndTypePrinter::getObjectTypeAndOptionality(
975+
param, param->getInterfaceType());
976+
std::string paramName =
977+
param->getName().empty() ? "" : param->getName().str().str();
978+
renameCxxParameterIfNeeded(FD, paramName);
979+
// Always emit a named parameter for the C++ inline thunk to ensure it
980+
// can be referenced in the body.
981+
if (kind == FunctionSignatureKind::CxxInlineThunk &&
982+
paramName.empty()) {
983+
llvm::raw_string_ostream os(paramName);
984+
os << "_" << paramIndex;
985+
}
986+
resultingRepresentation.merge(
987+
print(objTy, argKind, paramName, param->isInOut()));
988+
++paramIndex;
989+
});
990+
if (resultingRepresentation.isUnsupported()) {
982991
return resultingRepresentation;
992+
}
983993
}
984-
os << ')';
994+
functionSignatureOS << ')';
985995
if (modifiers.isConst)
986-
os << " const";
996+
functionSignatureOS << " const";
987997
if (modifiers.isNoexcept)
988-
os << " noexcept";
998+
functionSignatureOS << " noexcept";
989999
if (modifiers.hasSymbolUSR)
990-
ClangSyntaxPrinter(os).printSymbolUSRAttribute(
991-
modifiers.symbolUSROverride ? modifiers.symbolUSROverride : FD);
1000+
ClangSyntaxPrinter(functionSignatureOS)
1001+
.printSymbolUSRAttribute(
1002+
modifiers.symbolUSROverride ? modifiers.symbolUSROverride : FD);
1003+
if (!resultingRepresentation.isUnsupported())
1004+
os << functionSignatureOS.str();
9921005
return resultingRepresentation;
9931006
}
9941007

@@ -1474,8 +1487,9 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
14741487
std::tie(objTy, retKind) =
14751488
DeclAndTypePrinter::getObjectTypeAndOptionality(FD, resultTy);
14761489

1477-
auto s = printClangFunctionReturnType(objTy, retKind, const_cast<ModuleDecl *>(moduleContext),
1478-
OutputLanguageMode::Cxx);
1490+
auto s = printClangFunctionReturnType(
1491+
os, objTy, retKind, const_cast<ModuleDecl *>(moduleContext),
1492+
OutputLanguageMode::Cxx);
14791493
os << ">(swift::Error(opaqueError));\n";
14801494
os << "#endif\n";
14811495

@@ -1484,7 +1498,7 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
14841498
os << "\n";
14851499
os << " return SWIFT_RETURN_THUNK(";
14861500
printClangFunctionReturnType(
1487-
objTy, retKind, const_cast<ModuleDecl *>(moduleContext),
1501+
os, objTy, retKind, const_cast<ModuleDecl *>(moduleContext),
14881502
OutputLanguageMode::Cxx);
14891503
os << ", returnValue);\n";
14901504
}

lib/PrintAsClang/PrintClangFunction.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,9 @@ class DeclAndTypeClangFunctionPrinter {
143143
std::optional<IRABIDetailsProvider::MethodDispatchInfo> dispatchInfo);
144144

145145
/// Print Swift type as C/C++ type, as the return type of a C/C++ function.
146-
ClangRepresentation
147-
printClangFunctionReturnType(Type ty, OptionalTypeKind optKind,
148-
ModuleDecl *moduleContext,
149-
OutputLanguageMode outputLang);
146+
ClangRepresentation printClangFunctionReturnType(
147+
raw_ostream &stream, Type ty, OptionalTypeKind optKind,
148+
ModuleDecl *moduleContext, OutputLanguageMode outputLang);
150149

151150
static void printGenericReturnSequence(
152151
raw_ostream &os, const GenericTypeParamType *gtpt,

0 commit comments

Comments
 (0)