diff --git a/lib/ClangImporter/ClangClassTemplateNamePrinter.cpp b/lib/ClangImporter/ClangClassTemplateNamePrinter.cpp index 1f3771df6340e..6f8a411f512d1 100644 --- a/lib/ClangImporter/ClangClassTemplateNamePrinter.cpp +++ b/lib/ClangImporter/ClangClassTemplateNamePrinter.cpp @@ -12,6 +12,7 @@ #include "ClangClassTemplateNamePrinter.h" #include "ImporterImpl.h" +#include "clang/AST/TemplateArgumentVisitor.h" #include "clang/AST/TypeVisitor.h" using namespace swift; @@ -150,41 +151,72 @@ struct TemplateInstantiationNamePrinter } }; +struct TemplateArgumentPrinter + : clang::ConstTemplateArgumentVisitor { + TemplateInstantiationNamePrinter typePrinter; + + TemplateArgumentPrinter(ASTContext &swiftCtx, NameImporter *nameImporter, + ImportNameVersion version) + : typePrinter(swiftCtx, nameImporter, version) {} + + void VisitTemplateArgument(const clang::TemplateArgument &arg, + llvm::raw_svector_ostream &buffer) { + // Print "_" as a fallback if we couldn't emit a more meaningful type name. + buffer << "_"; + } + + void VisitTypeTemplateArgument(const clang::TemplateArgument &arg, + llvm::raw_svector_ostream &buffer) { + auto ty = arg.getAsType(); + buffer << typePrinter.Visit(ty.getTypePtr()); + if (ty.isConstQualified()) { + buffer << "_const"; + } + } + + void VisitIntegralTemplateArgument(const clang::TemplateArgument &arg, + llvm::raw_svector_ostream &buffer) { + buffer << "_"; + if (arg.getIntegralType()->isBuiltinType()) { + buffer << typePrinter.Visit(arg.getIntegralType().getTypePtr()) << "_"; + } + arg.getAsIntegral().print(buffer, true); + } + + void VisitPackTemplateArgument(const clang::TemplateArgument &arg, + llvm::raw_svector_ostream &buffer) { + VisitTemplateArgumentArray(arg.getPackAsArray(), buffer); + } + + void VisitTemplateArgumentArray(ArrayRef args, + llvm::raw_svector_ostream &buffer) { + bool needsComma = false; + for (auto &arg : args) { + // Do not try to print empty packs. + if (arg.getKind() == clang::TemplateArgument::ArgKind::Pack && + arg.getPackAsArray().empty()) + continue; + + if (needsComma) + buffer << ", "; + Visit(arg, buffer); + needsComma = true; + } + } +}; + std::string swift::importer::printClassTemplateSpecializationName( const clang::ClassTemplateSpecializationDecl *decl, ASTContext &swiftCtx, NameImporter *nameImporter, ImportNameVersion version) { - TemplateInstantiationNamePrinter templateNamePrinter(swiftCtx, nameImporter, - version); + TemplateArgumentPrinter templateArgPrinter(swiftCtx, nameImporter, version); - // TODO: the following logic should probably be a ConstTemplateArgumentVisitor llvm::SmallString<128> storage; llvm::raw_svector_ostream buffer(storage); decl->printName(buffer); buffer << "<"; - llvm::interleaveComma( - decl->getTemplateArgs().asArray(), buffer, - [&buffer, &templateNamePrinter](const clang::TemplateArgument &arg) { - // Use import name here so builtin types such as "int" map to their - // Swift equivalent ("CInt"). - if (arg.getKind() == clang::TemplateArgument::Type) { - auto ty = arg.getAsType(); - buffer << templateNamePrinter.Visit(ty.getTypePtr()); - if (ty.isConstQualified()) { - buffer << "_const"; - } - return; - } else if (arg.getKind() == clang::TemplateArgument::Integral) { - buffer << "_"; - if (arg.getIntegralType()->isBuiltinType()) { - buffer << templateNamePrinter.Visit( - arg.getIntegralType().getTypePtr()) - << "_"; - } - arg.getAsIntegral().print(buffer, true); - return; - } - buffer << "_"; - }); + templateArgPrinter.VisitTemplateArgumentArray( + decl->getTemplateArgs().asArray(), buffer); buffer << ">"; return buffer.str().str(); } diff --git a/test/Interop/Cxx/templates/Inputs/class-template-variadic.h b/test/Interop/Cxx/templates/Inputs/class-template-variadic.h index dce5366f0d5de..6fc7dd88715ae 100644 --- a/test/Interop/Cxx/templates/Inputs/class-template-variadic.h +++ b/test/Interop/Cxx/templates/Inputs/class-template-variadic.h @@ -25,6 +25,9 @@ struct IntWrapper { int getValue() const { return value; } }; +typedef Tuple Single; typedef Tuple Pair; +typedef Tuple Triple; +typedef Tuple, Tuple> Nested; #endif // TEST_INTEROP_CXX_TEMPLATES_INPUTS_CLASS_TEMPLATE_VARIADIC_H diff --git a/test/Interop/Cxx/templates/class-template-in-namespace-module-interface.swift b/test/Interop/Cxx/templates/class-template-in-namespace-module-interface.swift index a8f41d8200184..77b7dc235dabe 100644 --- a/test/Interop/Cxx/templates/class-template-in-namespace-module-interface.swift +++ b/test/Interop/Cxx/templates/class-template-in-namespace-module-interface.swift @@ -1,11 +1,8 @@ // RUN: %target-swift-ide-test -print-module -module-to-print=ClassTemplateInNamespace -I %S/Inputs -source-filename=x -enable-experimental-cxx-interop | %FileCheck %s // CHECK: enum Space { -// CHECK: struct Ship<_> { -// CHECK: init() -// CHECK: } // CHECK: @available(*, unavailable, message: "Un-specialized class templates are not currently supported. Please use a specialization of this type.") // CHECK: struct Ship<> { // CHECK: } -// CHECK: typealias Orbiter = Space.Ship<_> +// CHECK: typealias Orbiter = Space.Ship<((CBool) -> Void)> // CHECK: } diff --git a/test/Interop/Cxx/templates/class-template-variardic-parameter-module-interface.swift b/test/Interop/Cxx/templates/class-template-variardic-parameter-module-interface.swift new file mode 100644 index 0000000000000..42ae6fdf58b82 --- /dev/null +++ b/test/Interop/Cxx/templates/class-template-variardic-parameter-module-interface.swift @@ -0,0 +1,12 @@ +// RUN: %target-swift-ide-test -print-module -module-to-print=ClassTemplateVariadic -I %S/Inputs -source-filename=x -enable-experimental-cxx-interop | %FileCheck %s +// RUN: %target-swift-ide-test -print-module -module-to-print=ClassTemplateVariadic -I %S/Inputs -source-filename=x -cxx-interoperability-mode=swift-6 | %FileCheck %s +// RUN: %target-swift-ide-test -print-module -module-to-print=ClassTemplateVariadic -I %S/Inputs -source-filename=x -cxx-interoperability-mode=upcoming-swift | %FileCheck %s + +// CHECK: @available(*, unavailable +// CHECK: struct Tuple { +// CHECK: } + +// CHECK: typealias Single = Tuple +// CHECK: typealias Pair = Tuple +// CHECK: typealias Triple = Tuple +// CHECK: typealias Nested = Tuple, Tuple>