Skip to content

Commit bc6a7a6

Browse files
authored
Merge pull request swiftlang#35963 from zoecarver/cxx/bail-on-large-templates
[cxx-interop] Bail on deep template specializations.
2 parents e024d96 + 2f0e7fc commit bc6a7a6

File tree

4 files changed

+45
-0
lines changed

4 files changed

+45
-0
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3698,6 +3698,22 @@ namespace {
36983698
return VisitRecordDecl(decl);
36993699
}
37003700

3701+
bool isSpecializationDepthGreaterThan(
3702+
const clang::ClassTemplateSpecializationDecl *decl, unsigned maxDepth) {
3703+
for (auto arg : decl->getTemplateArgs().asArray()) {
3704+
if (arg.getKind() == clang::TemplateArgument::Type) {
3705+
if (auto classSpec =
3706+
dyn_cast_or_null<clang::ClassTemplateSpecializationDecl>(
3707+
arg.getAsType()->getAsCXXRecordDecl())) {
3708+
if (maxDepth == 0 ||
3709+
isSpecializationDepthGreaterThan(classSpec, maxDepth - 1))
3710+
return true;
3711+
}
3712+
}
3713+
}
3714+
return false;
3715+
}
3716+
37013717
Decl *VisitClassTemplateSpecializationDecl(
37023718
const clang::ClassTemplateSpecializationDecl *decl) {
37033719
// `Sema::isCompleteType` will try to instantiate the class template as a
@@ -3715,6 +3731,13 @@ namespace {
37153731
decl->getDefinition());
37163732
assert(def && "Class template instantiation didn't have definition");
37173733

3734+
// Currently this is a relatively low number, in the future we might
3735+
// consider increasing it, but this should keep compile time down,
3736+
// especially for types that become exponentially large when
3737+
// instantiating.
3738+
if (isSpecializationDepthGreaterThan(def, 8))
3739+
return nullptr;
3740+
37183741
// FIXME: This will instantiate all members of the specialization (and detect
37193742
// instantiation failures in them), which can be more than is necessary
37203743
// and is more than what Clang does. As a result we reject some C++
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
template <class T>
2+
struct HasTypeWithSelfAsParam {
3+
using TT = HasTypeWithSelfAsParam<HasTypeWithSelfAsParam<T>>;
4+
};
5+
6+
using WillBeInfinite = HasTypeWithSelfAsParam<int>;

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,8 @@ module MemberTemplates {
112112
header "member-templates.h"
113113
requires cplusplus
114114
}
115+
116+
module LargeClassTemplates {
117+
header "large-class-templates.h"
118+
requires cplusplus
119+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %target-swift-ide-test -print-module -module-to-print=LargeClassTemplates -I %S/Inputs -source-filename=x -enable-cxx-interop | %FileCheck %s
2+
3+
// CHECK: struct HasTypeWithSelfAsParam<T> {
4+
// CHECK: }
5+
6+
// CHECK: struct __CxxTemplateInst22HasTypeWithSelfAsParamIiE {
7+
// CHECK: typealias TT = __CxxTemplateInst22HasTypeWithSelfAsParamIS_IiEE
8+
// CHECK: init()
9+
// CHECK: }
10+
11+
// CHECK: typealias WillBeInfinite = __CxxTemplateInst22HasTypeWithSelfAsParamIiE

0 commit comments

Comments
 (0)