Skip to content

Commit fed7373

Browse files
committed
[cxx-interop] Allow many specializations of a class template
An old piece of logic in ClangImporter was trying to limit the number of instantiations for each C++ class template to prevent long compile times. Unfortunately this started causing hard-to-reproduce deserialization errors on large projects which use many different instantiations of `std::vector` and `std::allocator`. The instantiation limit was arbitrary, it serves no real purpose and causes issues. This change removes it. rdar://158397914
1 parent 3ee222f commit fed7373

File tree

2 files changed

+6
-20
lines changed

2 files changed

+6
-20
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3237,26 +3237,12 @@ namespace {
32373237

32383238
Decl *VisitClassTemplateSpecializationDecl(
32393239
const clang::ClassTemplateSpecializationDecl *decl) {
3240-
bool isPair = decl->getSpecializedTemplate()->isInStdNamespace() &&
3241-
decl->getSpecializedTemplate()->getName() == "pair";
3242-
3243-
// Before we go any further, check if we've already got tens of thousands
3244-
// of specializations. If so, it means we're likely instantiating a very
3245-
// deep/complex template, or we've run into an infinite loop. In either
3246-
// case, its not worth the compile time, so bail.
3247-
// TODO: this could be configurable at some point.
3248-
size_t specializationLimit = !isPair ? 1000 : 10000;
3249-
if (size_t(
3250-
llvm::size(decl->getSpecializedTemplate()->specializations())) >
3251-
specializationLimit) {
3252-
// Note: it would be nice to import a dummy unavailable struct,
3253-
// but we would then need to instantiate the template here,
3254-
// as we cannot import a struct without a definition. That would
3255-
// defeat the purpose. Also, we can't make the dummy
3256-
// struct simply unavailable, as that still makes the
3257-
// typelias that references it available.
3240+
// Importing std::conditional substantially increases compile times when
3241+
// building with libstdc++, i.e. on most Linux distros.
3242+
if (decl->isInStdNamespace() && decl->getIdentifier() &&
3243+
(decl->getName() == "conditional" || decl->getName() == "__or_" ||
3244+
decl->getName() == "_Expr"))
32583245
return nullptr;
3259-
}
32603246

32613247
// `decl->getDefinition()` can return nullptr before the call to sema and
32623248
// return its definition afterwards.

test/Interop/Cxx/templates/many-specializations.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@
55
// CHECK-NEXT: struct TemplateStruct<T> {
66
// CHECK-NEXT: }
77

8-
// CHECK-NOT: typealias
8+
// CHECK: typealias T1000

0 commit comments

Comments
 (0)