Skip to content

Commit d76c45d

Browse files
committed
[interop] NFC, refactor clang function printer to share code between C and C++ signature printer
1 parent 513507e commit d76c45d

File tree

3 files changed

+45
-99
lines changed

3 files changed

+45
-99
lines changed

lib/PrintAsClang/DeclAndTypePrinter.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -826,8 +826,9 @@ class DeclAndTypePrinter::Implementation
826826
os << "SWIFT_EXTERN ";
827827

828828
DeclAndTypeClangFunctionPrinter funcPrinter(os, owningPrinter.typeMapping);
829-
funcPrinter.printFunctionDeclAsCFunctionDecl(FD, funcABI.getSymbolName(),
830-
resultTy);
829+
funcPrinter.printFunctionSignature(
830+
FD, funcABI.getSymbolName(), resultTy,
831+
DeclAndTypeClangFunctionPrinter::FunctionSignatureKind::CFunctionProto);
831832
// Swift functions can't throw exceptions, we can only
832833
// throw them from C++ when emitting C++ inline thunks for the Swift
833834
// functions.
@@ -864,8 +865,9 @@ class DeclAndTypePrinter::Implementation
864865

865866
os << "inline ";
866867
DeclAndTypeClangFunctionPrinter funcPrinter(os, owningPrinter.typeMapping);
867-
funcPrinter.printFunctionDeclAsCxxFunctionDecl(
868-
FD, FD->getName().getBaseIdentifier().get(), resultTy);
868+
funcPrinter.printFunctionSignature(
869+
FD, FD->getName().getBaseIdentifier().get(), resultTy,
870+
DeclAndTypeClangFunctionPrinter::FunctionSignatureKind::CxxInlineThunk);
869871
// FIXME: Support throwing exceptions for Swift errors.
870872
os << " noexcept";
871873
printFunctionClangAttributes(FD, funcTy);

lib/PrintAsClang/PrintClangFunction.cpp

Lines changed: 26 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,6 @@ using namespace swift;
2626

2727
namespace {
2828

29-
class ClangFunctionSignatureTypePrinter : private ClangSyntaxPrinter {
30-
public:
31-
ClangFunctionSignatureTypePrinter(raw_ostream &os) : ClangSyntaxPrinter(os) {}
32-
33-
void printIfSimpleType(StringRef name, bool canBeNullable,
34-
Optional<OptionalTypeKind> optionalKind) {
35-
os << name;
36-
if (canBeNullable)
37-
printNullability(optionalKind);
38-
}
39-
40-
void printVoidType() { os << "void"; }
41-
};
42-
4329
// Prints types in the C function signature that corresponds to the
4430
// native Swift function/method.
4531
class CFunctionSignatureTypePrinter
@@ -55,16 +41,9 @@ class CFunctionSignatureTypePrinter
5541

5642
bool printIfKnownSimpleType(const TypeDecl *typeDecl,
5743
Optional<OptionalTypeKind> optionalKind) {
58-
if (languageMode == OutputLanguageMode::Cxx) {
59-
auto knownTypeInfo = typeMapping.getKnownCxxTypeInfo(typeDecl);
60-
if (!knownTypeInfo)
61-
return false;
62-
os << knownTypeInfo->name;
63-
if (knownTypeInfo->canBeNullable)
64-
printNullability(optionalKind);
65-
return true;
66-
}
67-
auto knownTypeInfo = typeMapping.getKnownCTypeInfo(typeDecl);
44+
auto knownTypeInfo = languageMode == OutputLanguageMode::Cxx
45+
? typeMapping.getKnownCxxTypeInfo(typeDecl)
46+
: typeMapping.getKnownCTypeInfo(typeDecl);
6847
if (!knownTypeInfo)
6948
return false;
7049
os << knownTypeInfo->name;
@@ -116,15 +95,17 @@ class CFunctionSignatureTypePrinter
11695

11796
} // end namespace
11897

119-
void DeclAndTypeClangFunctionPrinter::printFunctionDeclAsCFunctionDecl(
120-
FuncDecl *FD, StringRef name, Type resultTy) {
98+
void DeclAndTypeClangFunctionPrinter::printFunctionSignature(
99+
FuncDecl *FD, StringRef name, Type resultTy, FunctionSignatureKind kind) {
100+
OutputLanguageMode outputLang = kind == FunctionSignatureKind::CFunctionProto
101+
? OutputLanguageMode::ObjC
102+
: OutputLanguageMode::Cxx;
121103
// FIXME: Might need a PrintMultiPartType here.
122-
auto print = [this](Type ty, Optional<OptionalTypeKind> optionalKind,
123-
StringRef name) {
104+
auto print = [&, this](Type ty, Optional<OptionalTypeKind> optionalKind,
105+
StringRef name) {
124106
// FIXME: add support for noescape and PrintMultiPartType,
125107
// see DeclAndTypePrinter::print.
126-
CFunctionSignatureTypePrinter typePrinter(os, typeMapping,
127-
OutputLanguageMode::ObjC);
108+
CFunctionSignatureTypePrinter typePrinter(os, typeMapping, outputLang);
128109
typePrinter.visit(ty, optionalKind);
129110

130111
if (!name.empty()) {
@@ -134,59 +115,12 @@ void DeclAndTypeClangFunctionPrinter::printFunctionDeclAsCFunctionDecl(
134115
};
135116

136117
// Print out the return type.
137-
OptionalTypeKind kind;
118+
OptionalTypeKind retKind;
138119
Type objTy;
139-
std::tie(objTy, kind) =
120+
std::tie(objTy, retKind) =
140121
DeclAndTypePrinter::getObjectTypeAndOptionality(FD, resultTy);
141-
CFunctionSignatureTypePrinter typePrinter(os, typeMapping,
142-
OutputLanguageMode::ObjC);
143-
typePrinter.visit(objTy, kind);
144-
145-
os << ' ' << name << '(';
146-
147-
// Print out the parameter types.
148-
auto params = FD->getParameters();
149-
if (params->size()) {
150-
llvm::interleaveComma(*params, os, [&](const ParamDecl *param) {
151-
OptionalTypeKind kind;
152-
Type objTy;
153-
std::tie(objTy, kind) = DeclAndTypePrinter::getObjectTypeAndOptionality(
154-
param, param->getInterfaceType());
155-
StringRef paramName =
156-
param->getName().empty() ? "" : param->getName().str();
157-
print(objTy, kind, paramName);
158-
});
159-
} else {
160-
os << "void";
161-
}
162-
os << ')';
163-
}
164-
165-
void DeclAndTypeClangFunctionPrinter::printFunctionDeclAsCxxFunctionDecl(
166-
FuncDecl *FD, StringRef name, Type resultTy) {
167-
// FIXME: Might need a PrintMultiPartType here.
168-
auto print = [this](Type ty, Optional<OptionalTypeKind> optionalKind,
169-
StringRef name) {
170-
// FIXME: add support for noescape and PrintMultiPartType,
171-
// see DeclAndTypePrinter::print.
172-
CFunctionSignatureTypePrinter typePrinter(os, typeMapping,
173-
OutputLanguageMode::Cxx);
174-
typePrinter.visit(ty, optionalKind);
175-
176-
if (!name.empty()) {
177-
os << ' ';
178-
ClangSyntaxPrinter(os).printIdentifier(name);
179-
}
180-
};
181-
182-
// Print out the return type.
183-
OptionalTypeKind kind;
184-
Type objTy;
185-
std::tie(objTy, kind) =
186-
DeclAndTypePrinter::getObjectTypeAndOptionality(FD, resultTy);
187-
CFunctionSignatureTypePrinter typePrinter(os, typeMapping,
188-
OutputLanguageMode::Cxx);
189-
typePrinter.visit(objTy, kind);
122+
CFunctionSignatureTypePrinter typePrinter(os, typeMapping, outputLang);
123+
typePrinter.visit(objTy, retKind);
190124

191125
os << ' ' << name << '(';
192126

@@ -195,19 +129,25 @@ void DeclAndTypeClangFunctionPrinter::printFunctionDeclAsCxxFunctionDecl(
195129
if (params->size()) {
196130
size_t paramIndex = 1;
197131
llvm::interleaveComma(*params, os, [&](const ParamDecl *param) {
198-
OptionalTypeKind kind;
132+
OptionalTypeKind argKind;
199133
Type objTy;
200-
std::tie(objTy, kind) = DeclAndTypePrinter::getObjectTypeAndOptionality(
201-
param, param->getInterfaceType());
134+
std::tie(objTy, argKind) =
135+
DeclAndTypePrinter::getObjectTypeAndOptionality(
136+
param, param->getInterfaceType());
202137
std::string paramName =
203138
param->getName().empty() ? "" : param->getName().str().str();
204-
if (paramName.empty()) {
139+
// Always emit a named parameter for the C++ inline thunk to ensure it can
140+
// be referenced in the body.
141+
if (kind == FunctionSignatureKind::CxxInlineThunk && paramName.empty()) {
205142
llvm::raw_string_ostream os(paramName);
206143
os << "_" << paramIndex;
207144
}
208-
print(objTy, kind, paramName);
145+
print(objTy, argKind, paramName);
209146
++paramIndex;
210147
});
148+
} else if (kind == FunctionSignatureKind::CFunctionProto) {
149+
// Emit 'void' in an empty parameter list for C function declarations.
150+
os << "void";
211151
}
212152
os << ')';
213153
}

lib/PrintAsClang/PrintClangFunction.h

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,19 @@ class DeclAndTypeClangFunctionPrinter {
3131
PrimitiveTypeMapping &typeMapping)
3232
: os(os), typeMapping(typeMapping) {}
3333

34-
/// Print the C function declaration that corresponds to the given function
35-
/// declaration.
36-
void printFunctionDeclAsCFunctionDecl(FuncDecl *FD, StringRef name,
37-
Type resultTy);
38-
39-
/// Print the inline C++ function thunk declaration that corresponds to the
40-
/// given Swift function declaration.
41-
void printFunctionDeclAsCxxFunctionDecl(FuncDecl *FD, StringRef name,
42-
Type resultTy);
34+
/// What kind of function signature should be emitted for the given Swift
35+
/// function.
36+
enum class FunctionSignatureKind {
37+
/// Emit a signature for the C function prototype.
38+
CFunctionProto,
39+
/// Emit a signature for the inline C++ function thunk.
40+
CxxInlineThunk
41+
};
42+
43+
/// Print the C function declaration or the C++ function thunk that
44+
/// corresponds to the given function declaration.
45+
void printFunctionSignature(FuncDecl *FD, StringRef name, Type resultTy,
46+
FunctionSignatureKind kind);
4347

4448
private:
4549
raw_ostream &os;

0 commit comments

Comments
 (0)