Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/AST/ClangTypeConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1083,8 +1083,8 @@ ClangTypeConverter::getClangTemplateArguments(
// error.
SmallVector<Type, 2> failedTypes;
for (clang::NamedDecl *param : *templateParams) {
// Note: all template parameters must be template type parameters. This is
// verified when we import the Clang decl.
// Note: all template parameters must be non-pack template type parameters.
// This is verified when we import the Clang decl.
auto templateParam = cast<clang::TemplateTypeParmDecl>(param);
// We must have found a defaulted parameter at the end of the list.
if (templateParam->getIndex() >= genericArgs.size()) {
Expand Down
7 changes: 5 additions & 2 deletions lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5009,9 +5009,12 @@ namespace {
importFullName(decl->getAsFunction());
if (!importedName)
return nullptr;
// All template parameters must be template type parameters.
// All template parameters must be template type parameters, and none of
// them may be a parameter pack.
if (!llvm::all_of(*decl->getTemplateParameters(), [](auto param) {
return isa<clang::TemplateTypeParmDecl>(param);
const auto *typeParam =
dyn_cast<clang::TemplateTypeParmDecl>(param);
return typeParam && !typeParam->isParameterPack();
Comment on lines +5015 to +5017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could probably hoist this check into importNameImpl and save some cycles on name lookup. I don't think this is very important though.

}))
return nullptr;
auto *imported = importFunctionDecl(decl->getAsFunction(), importedName,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_FUNCTION_TEMPLATE_PARAMETER_PACK_H
#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_FUNCTION_TEMPLATE_PARAMETER_PACK_H

// Those below include 'pack'/'Pack' in their names on purpose. We will grep by
// name to ensure they are not imported.

template <typename... Ts>
void takesPack(Ts... ts) {}

template <typename T, typename... Ts>
void takesTypeAndPack(T t, Ts... ts) {}

template <typename... Ts>
void unusedPack() {}

template <typename... Ts>
int packInReturnTypeOnly() {
return sizeof...(Ts);
}

// The struct should be included, but not its member functions.
struct HasVariadicTemplateMembers {
template <typename... Ts>
void memberTakesPack(Ts... ts) {}

template <typename... Ts>
static void staticMemberTakesPack(Ts... ts) {}
};

#endif // TEST_INTEROP_CXX_TEMPLATES_INPUTS_FUNCTION_TEMPLATE_PARAMETER_PACK_H
5 changes: 5 additions & 0 deletions test/Interop/Cxx/templates/Inputs/module.modulemap
Original file line number Diff line number Diff line change
Expand Up @@ -202,3 +202,8 @@ module FunctionTemplateWithOptionalFrt {
header "function-template-with-optional-frt.h"
requires cplusplus
}

module FunctionTemplateParameterPack {
header "function-template-parameter-pack.h"
requires cplusplus
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// RUN: %target-swift-ide-test \
// RUN: -print-module \
// RUN: -module-to-print=FunctionTemplateParameterPack \
// RUN: -I %S/Inputs \
// RUN: -source-filename=x \
// RUN: -cxx-interoperability-mode=default \
// RUN: | %FileCheck %s --implicit-check-not Pack --implicit-check-not pack

// Ensure that function templates with a template parameter pack are not
// imported. In our test, those contain 'pack'/'Pack' in their names, so we use
// --implicit-check-not to verify that. The struct HasVariadicTemplateMembers
// itself should be printed.

// CHECK: struct HasVariadicTemplateMembers
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// RUN: %target-typecheck-verify-swift \
// RUN: -cxx-interoperability-mode=default \
// RUN: -I %S/Inputs
// RUN: %target-typecheck-verify-swift \
// RUN: -cxx-interoperability-mode=default \
// RUN: -enable-experimental-feature ImportCxxMembersLazily \
// RUN: -I %S/Inputs
//
// REQUIRES: swift_feature_ImportCxxMembersLazily

import FunctionTemplateParameterPack

// Function templates with a template parameter pack are not imported. Try to
// call them anyway to make sure we don't crash trying to resolve them.

public func callFreeFunctionTemplatesWithPack() {
takesPack(1, Ts: CInt.self)
// expected-error@-1{{cannot find 'takesPack' in scope}}
takesTypeAndPack(1, 2, Ts: CInt.self)
// expected-error@-1{{cannot find 'takesTypeAndPack' in scope}}
unusedPack(Ts: CInt.self)
// expected-error@-1{{cannot find 'unusedPack' in scope}}
let _ = packInReturnTypeOnly(Ts: CInt.self)
// expected-error@-1{{cannot find 'packInReturnTypeOnly' in scope}}
}

public func callMemberFunctionTemplatesWithPack(
_ s: inout HasVariadicTemplateMembers) {
s.memberTakesPack(1, Ts: CInt.self)
// expected-error@-1{{value of type 'HasVariadicTemplateMembers' has no member 'memberTakesPack'}}
HasVariadicTemplateMembers.staticMemberTakesPack(1, Ts: CInt.self)
// expected-error@-1{{type 'HasVariadicTemplateMembers' has no member 'staticMemberTakesPack'}}
}