@@ -42,6 +42,12 @@ getKnownTypeInfo(const TypeDecl *typeDecl, PrimitiveTypeMapping &typeMapping,
4242bool isKnownType (Type t, PrimitiveTypeMapping &typeMapping,
4343 OutputLanguageMode languageMode) {
4444 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+
4551 if (auto *typeAliasType = dyn_cast<TypeAliasType>(t.getPointer ()))
4652 typeDecl = typeAliasType->getDecl ();
4753 else if (auto *structDecl = t->getStructOrBoundGenericStruct ())
@@ -93,6 +99,10 @@ class CFunctionSignatureTypePrinter
9399 languageMode(languageMode), modifiersDelegate(modifiersDelegate),
94100 moduleContext(moduleContext), typeUseKind(typeUseKind) {}
95101
102+ void printInoutTypeModifier () {
103+ os << (languageMode == swift::OutputLanguageMode::Cxx ? " &" : " *" );
104+ }
105+
96106 bool printIfKnownSimpleType (const TypeDecl *typeDecl,
97107 Optional<OptionalTypeKind> optionalKind,
98108 bool isInOutParam) {
@@ -103,9 +113,8 @@ class CFunctionSignatureTypePrinter
103113 if (knownTypeInfo->canBeNullable ) {
104114 printNullability (optionalKind);
105115 }
106- if (isInOutParam) {
107- os << (languageMode == swift::OutputLanguageMode::Cxx ? " &" : " *" );
108- }
116+ if (isInOutParam)
117+ printInoutTypeModifier ();
109118 return true ;
110119 }
111120
@@ -177,6 +186,37 @@ class CFunctionSignatureTypePrinter
177186 .printValueTypeReturnType (decl, languageMode, moduleContext);
178187 }
179188
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+
180220 void visitPart (Type Ty, Optional<OptionalTypeKind> optionalKind,
181221 bool isInOutParam) {
182222 TypeVisitor::visit (Ty, optionalKind, isInOutParam);
@@ -220,6 +260,14 @@ void DeclAndTypeClangFunctionPrinter::printFunctionSignature(
220260 }
221261 };
222262
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+
223271 // Print out the return type.
224272 bool isIndirectReturnType =
225273 kind == FunctionSignatureKind::CFunctionProto &&
@@ -314,6 +362,8 @@ void DeclAndTypeClangFunctionPrinter::printFunctionSignature(
314362 os << " void" ;
315363 }
316364 os << ' )' ;
365+ if (modifiers.isConst )
366+ os << " const" ;
317367}
318368
319369void DeclAndTypeClangFunctionPrinter::printCxxToCFunctionParameterUse (
@@ -463,21 +513,18 @@ void DeclAndTypeClangFunctionPrinter::printCxxMethod(
463513 StringRef swiftSymbolName, Type resultTy, bool isDefinition) {
464514 bool isConstructor = isa<ConstructorDecl>(FD);
465515 os << " " ;
466- if (isConstructor && !isDefinition)
467- os << " static " ;
468- os << " inline " ;
469- // FIXME: Full qualifier.
516+
470517 FunctionSignatureModifiers modifiers;
471518 if (isDefinition)
472519 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;
473525 printFunctionSignature (
474526 FD, isConstructor ? " init" : FD->getName ().getBaseIdentifier ().get (),
475527 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" ;
481528 if (!isDefinition) {
482529 os << " ;\n " ;
483530 return ;
@@ -497,30 +544,48 @@ void DeclAndTypeClangFunctionPrinter::printCxxMethod(
497544 os << " }\n " ;
498545}
499546
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+ }
505555
506- StringRef propertyName;
556+ static std::string remapPropertyName (const AccessorDecl *accessor,
557+ Type resultTy) {
507558 // 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+ }
509566
510567 std::string name;
511568 llvm::raw_string_ostream nameOS (name);
512- // FIXME: some names are remapped differently. (e.g. isX).
513569 nameOS << (accessor->isSetter () ? " set" : " get" )
514570 << 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 << " " ;
515580
516581 FunctionSignatureModifiers modifiers;
517582 if (isDefinition)
518583 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);
524589 if (!isDefinition) {
525590 os << " ;\n " ;
526591 return ;
0 commit comments