@@ -42,6 +42,12 @@ getKnownTypeInfo(const TypeDecl *typeDecl, PrimitiveTypeMapping &typeMapping,
42
42
bool isKnownType (Type t, PrimitiveTypeMapping &typeMapping,
43
43
OutputLanguageMode languageMode) {
44
44
const TypeDecl *typeDecl;
45
+ if (auto *bgt = dyn_cast<BoundGenericStructType>(
46
+ t->isOptional () ? t->getOptionalObjectType ()->getDesugaredType ()
47
+ : t->getDesugaredType ())) {
48
+ return bgt->isUnsafePointer () || bgt->isUnsafeMutablePointer ();
49
+ }
50
+
45
51
if (auto *typeAliasType = dyn_cast<TypeAliasType>(t.getPointer ()))
46
52
typeDecl = typeAliasType->getDecl ();
47
53
else if (auto *structDecl = t->getStructOrBoundGenericStruct ())
@@ -93,6 +99,10 @@ class CFunctionSignatureTypePrinter
93
99
languageMode(languageMode), modifiersDelegate(modifiersDelegate),
94
100
moduleContext(moduleContext), typeUseKind(typeUseKind) {}
95
101
102
+ void printInoutTypeModifier () {
103
+ os << (languageMode == swift::OutputLanguageMode::Cxx ? " &" : " *" );
104
+ }
105
+
96
106
bool printIfKnownSimpleType (const TypeDecl *typeDecl,
97
107
Optional<OptionalTypeKind> optionalKind,
98
108
bool isInOutParam) {
@@ -103,9 +113,8 @@ class CFunctionSignatureTypePrinter
103
113
if (knownTypeInfo->canBeNullable ) {
104
114
printNullability (optionalKind);
105
115
}
106
- if (isInOutParam) {
107
- os << (languageMode == swift::OutputLanguageMode::Cxx ? " &" : " *" );
108
- }
116
+ if (isInOutParam)
117
+ printInoutTypeModifier ();
109
118
return true ;
110
119
}
111
120
@@ -177,6 +186,37 @@ class CFunctionSignatureTypePrinter
177
186
.printValueTypeReturnType (decl, languageMode, moduleContext);
178
187
}
179
188
189
+ bool printIfKnownGenericStruct (const BoundGenericStructType *BGT,
190
+ Optional<OptionalTypeKind> optionalKind,
191
+ bool isInOutParam) {
192
+ auto bgsTy = Type (const_cast <BoundGenericStructType *>(BGT));
193
+ bool isConst;
194
+ if (bgsTy->isUnsafePointer ())
195
+ isConst = true ;
196
+ else if (bgsTy->isUnsafeMutablePointer ())
197
+ isConst = false ;
198
+ else
199
+ return false ;
200
+
201
+ auto args = BGT->getGenericArgs ();
202
+ assert (args.size () == 1 );
203
+ visitPart (args.front (), OTK_None, /* isInOutParam=*/ false );
204
+ if (isConst)
205
+ os << " const" ;
206
+ os << " *" ;
207
+ printNullability (optionalKind);
208
+ if (isInOutParam)
209
+ printInoutTypeModifier ();
210
+ return true ;
211
+ }
212
+
213
+ void visitBoundGenericStructType (BoundGenericStructType *BGT,
214
+ Optional<OptionalTypeKind> optionalKind,
215
+ bool isInOutParam) {
216
+ if (printIfKnownGenericStruct (BGT, optionalKind, isInOutParam))
217
+ return ;
218
+ }
219
+
180
220
void visitPart (Type Ty, Optional<OptionalTypeKind> optionalKind,
181
221
bool isInOutParam) {
182
222
TypeVisitor::visit (Ty, optionalKind, isInOutParam);
@@ -220,6 +260,14 @@ void DeclAndTypeClangFunctionPrinter::printFunctionSignature(
220
260
}
221
261
};
222
262
263
+ // Print any modifiers before the signature.
264
+ if (modifiers.isStatic ) {
265
+ assert (!modifiers.isConst );
266
+ os << " static " ;
267
+ }
268
+ if (modifiers.isInline )
269
+ os << " inline " ;
270
+
223
271
// Print out the return type.
224
272
bool isIndirectReturnType =
225
273
kind == FunctionSignatureKind::CFunctionProto &&
@@ -314,6 +362,8 @@ void DeclAndTypeClangFunctionPrinter::printFunctionSignature(
314
362
os << " void" ;
315
363
}
316
364
os << ' )' ;
365
+ if (modifiers.isConst )
366
+ os << " const" ;
317
367
}
318
368
319
369
void DeclAndTypeClangFunctionPrinter::printCxxToCFunctionParameterUse (
@@ -463,21 +513,18 @@ void DeclAndTypeClangFunctionPrinter::printCxxMethod(
463
513
StringRef swiftSymbolName, Type resultTy, bool isDefinition) {
464
514
bool isConstructor = isa<ConstructorDecl>(FD);
465
515
os << " " ;
466
- if (isConstructor && !isDefinition)
467
- os << " static " ;
468
- os << " inline " ;
469
- // FIXME: Full qualifier.
516
+
470
517
FunctionSignatureModifiers modifiers;
471
518
if (isDefinition)
472
519
modifiers.qualifierContext = typeDeclContext;
520
+ modifiers.isStatic = isConstructor && !isDefinition;
521
+ modifiers.isInline = true ;
522
+ bool isMutating =
523
+ isa<FuncDecl>(FD) ? cast<FuncDecl>(FD)->isMutating () : false ;
524
+ modifiers.isConst = !isMutating && !isConstructor;
473
525
printFunctionSignature (
474
526
FD, isConstructor ? " init" : FD->getName ().getBaseIdentifier ().get (),
475
527
resultTy, FunctionSignatureKind::CxxInlineThunk, {}, modifiers);
476
- bool isMutating = false ;
477
- if (auto *funcDecl = dyn_cast<FuncDecl>(FD))
478
- isMutating = funcDecl->isMutating ();
479
- if (!isMutating && !isConstructor)
480
- os << " const" ;
481
528
if (!isDefinition) {
482
529
os << " ;\n " ;
483
530
return ;
@@ -497,30 +544,48 @@ void DeclAndTypeClangFunctionPrinter::printCxxMethod(
497
544
os << " }\n " ;
498
545
}
499
546
500
- void DeclAndTypeClangFunctionPrinter::printCxxPropertyAccessorMethod (
501
- const NominalTypeDecl *typeDeclContext, const AccessorDecl *accessor,
502
- StringRef swiftSymbolName, Type resultTy, bool isDefinition) {
503
- assert (accessor->isSetter () || accessor->getParameters ()->size () == 0 );
504
- os << " inline " ;
547
+ // / Returns true if the given property name like `isEmpty` can be remapped
548
+ // / directly to a C++ method.
549
+ static bool canRemapBoolPropertyNameDirectly (StringRef name) {
550
+ auto startsWithAndLonger = [&](StringRef prefix) -> bool {
551
+ return name.startswith (prefix) && name.size () > prefix.size ();
552
+ };
553
+ return startsWithAndLonger (" is" ) || startsWithAndLonger (" has" );
554
+ }
505
555
506
- StringRef propertyName;
556
+ static std::string remapPropertyName (const AccessorDecl *accessor,
557
+ Type resultTy) {
507
558
// For a getter or setter, go through the variable or subscript decl.
508
- propertyName = accessor->getStorage ()->getBaseIdentifier ().str ();
559
+ StringRef propertyName = accessor->getStorage ()->getBaseIdentifier ().str ();
560
+
561
+ // Boolean property getters can be remapped directly in certain cases.
562
+ if (accessor->isGetter () && resultTy->isBool () &&
563
+ canRemapBoolPropertyNameDirectly (propertyName)) {
564
+ return propertyName.str ();
565
+ }
509
566
510
567
std::string name;
511
568
llvm::raw_string_ostream nameOS (name);
512
- // FIXME: some names are remapped differently. (e.g. isX).
513
569
nameOS << (accessor->isSetter () ? " set" : " get" )
514
570
<< char (std::toupper (propertyName[0 ])) << propertyName.drop_front ();
571
+ nameOS.flush ();
572
+ return name;
573
+ }
574
+
575
+ void DeclAndTypeClangFunctionPrinter::printCxxPropertyAccessorMethod (
576
+ const NominalTypeDecl *typeDeclContext, const AccessorDecl *accessor,
577
+ StringRef swiftSymbolName, Type resultTy, bool isDefinition) {
578
+ assert (accessor->isSetter () || accessor->getParameters ()->size () == 0 );
579
+ os << " " ;
515
580
516
581
FunctionSignatureModifiers modifiers;
517
582
if (isDefinition)
518
583
modifiers.qualifierContext = typeDeclContext;
519
- printFunctionSignature (accessor, nameOS. str (), resultTy,
520
- FunctionSignatureKind::CxxInlineThunk, {}, modifiers );
521
- if (accessor-> isGetter ()) {
522
- os << " const " ;
523
- }
584
+ modifiers. isInline = true ;
585
+ modifiers. isConst = accessor-> isGetter ( );
586
+ printFunctionSignature (accessor, remapPropertyName (accessor, resultTy),
587
+ resultTy, FunctionSignatureKind::CxxInlineThunk, {},
588
+ modifiers);
524
589
if (!isDefinition) {
525
590
os << " ;\n " ;
526
591
return ;
0 commit comments