Skip to content

Commit 84a2f33

Browse files
authored
Merge pull request #66749 from apple/egorzhdan/cxx-template-subst-crash
[cxx-interop] Avoid crashing when template substitution fails
2 parents c9d20c4 + 4a1afa9 commit 84a2f33

File tree

5 files changed

+69
-5
lines changed

5 files changed

+69
-5
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2128,6 +2128,9 @@ ERROR(unable_to_convert_generic_swift_types,none,
21282128
"the following Swift type(s) provided to '%0' could not be "
21292129
"converted: %1",
21302130
(StringRef, StringRef))
2131+
ERROR(unable_to_substitute_cxx_function_template,none,
2132+
"could not substitute parameters for C++ function template '%0': %1",
2133+
(StringRef, StringRef))
21312134

21322135
// Type aliases
21332136
ERROR(type_alias_underlying_type_access,none,

lib/ClangImporter/ClangImporter.cpp

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5772,20 +5772,24 @@ clang::FunctionDecl *ClangImporter::instantiateCXXFunctionTemplate(
57725772
std::unique_ptr<TemplateInstantiationError> error =
57735773
ctx.getClangTemplateArguments(func->getTemplateParameters(),
57745774
subst.getReplacementTypes(), templateSubst);
5775-
if (error) {
5776-
std::string failedTypesStr;
5777-
llvm::raw_string_ostream failedTypesStrStream(failedTypesStr);
5778-
llvm::interleaveComma(error->failedTypes, failedTypesStrStream);
57795775

5776+
auto getFuncName = [&]() -> std::string {
57805777
std::string funcName;
57815778
llvm::raw_string_ostream funcNameStream(funcName);
57825779
func->printQualifiedName(funcNameStream);
5780+
return funcName;
5781+
};
5782+
5783+
if (error) {
5784+
std::string failedTypesStr;
5785+
llvm::raw_string_ostream failedTypesStrStream(failedTypesStr);
5786+
llvm::interleaveComma(error->failedTypes, failedTypesStrStream);
57835787

57845788
// TODO: Use the location of the apply here.
57855789
// TODO: This error message should not reference implementation details.
57865790
// See: https://github.com/apple/swift/pull/33053#discussion_r477003350
57875791
ctx.Diags.diagnose(SourceLoc(), diag::unable_to_convert_generic_swift_types,
5788-
funcName, failedTypesStr);
5792+
getFuncName(), failedTypesStr);
57895793
return nullptr;
57905794
}
57915795

@@ -5795,6 +5799,20 @@ clang::FunctionDecl *ClangImporter::instantiateCXXFunctionTemplate(
57955799
auto &sema = getClangInstance().getSema();
57965800
auto *spec = sema.InstantiateFunctionDeclaration(func, templateArgList,
57975801
clang::SourceLocation());
5802+
if (!spec) {
5803+
std::string templateParams;
5804+
llvm::raw_string_ostream templateParamsStream(templateParams);
5805+
llvm::interleaveComma(templateArgList->asArray(), templateParamsStream,
5806+
[&](const clang::TemplateArgument &arg) {
5807+
arg.print(func->getASTContext().getPrintingPolicy(),
5808+
templateParamsStream,
5809+
/*IncludeType*/ true);
5810+
});
5811+
ctx.Diags.diagnose(SourceLoc(),
5812+
diag::unable_to_substitute_cxx_function_template,
5813+
getFuncName(), templateParams);
5814+
return nullptr;
5815+
}
57985816
sema.InstantiateFunctionDefinition(clang::SourceLocation(), spec);
57995817
return spec;
58005818
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_ENABLE_IF_H
2+
#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_ENABLE_IF_H
3+
4+
template <bool B, class T = void>
5+
struct enable_if {};
6+
7+
template <class T>
8+
struct enable_if<true, T> {
9+
typedef T type;
10+
};
11+
12+
template <class T>
13+
struct is_bool {
14+
static const bool value = false;
15+
};
16+
17+
template <>
18+
struct is_bool<bool> {
19+
static const bool value = true;
20+
};
21+
22+
struct HasMethodWithEnableIf {
23+
template <typename T>
24+
typename enable_if<is_bool<T>::value, bool>::type onlyEnabledForBool(T t) const {
25+
return !t;
26+
}
27+
};
28+
29+
#endif // TEST_INTEROP_CXX_TEMPLATES_INPUTS_ENABLE_IF_H

test/Interop/Cxx/templates/Inputs/module.modulemap

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,11 @@ module TemplateTypeParameterNotInSignature {
133133
requires cplusplus
134134
}
135135

136+
module EnableIf {
137+
header "enable-if.h"
138+
requires cplusplus
139+
}
140+
136141
module DefineReferencedInline {
137142
header "define-referenced-inline.h"
138143
requires cplusplus
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: not %target-swift-emit-ir %s -I %S/Inputs -enable-experimental-cxx-interop -enable-objc-interop 2>&1 | %FileCheck %s
2+
// REQUIRES: objc_interop
3+
4+
import StdlibUnittest
5+
import EnableIf
6+
7+
let x = HasMethodWithEnableIf()
8+
x.onlyEnabledForBool("a")
9+
// CHECK: error: could not substitute parameters for C++ function template 'HasMethodWithEnableIf::onlyEnabledForBool': NSString *

0 commit comments

Comments
 (0)