@@ -7300,10 +7300,8 @@ clang::FunctionDecl *ClangImporter::instantiateCXXFunctionTemplate(
7300
7300
// Instantiate a specialization of this template using the substitution map.
7301
7301
auto *templateArgList = clang::TemplateArgumentList::CreateCopy (
7302
7302
func->getASTContext (), templateSubst);
7303
- auto &sema = getClangInstance ().getSema ();
7304
- auto *spec = sema.InstantiateFunctionDeclaration (func, templateArgList,
7305
- clang::SourceLocation ());
7306
- if (!spec) {
7303
+
7304
+ auto diagnoseSubstFail = [&]() {
7307
7305
std::string templateParams;
7308
7306
llvm::raw_string_ostream templateParamsStream (templateParams);
7309
7307
llvm::interleaveComma (templateArgList->asArray (), templateParamsStream,
@@ -7315,9 +7313,24 @@ clang::FunctionDecl *ClangImporter::instantiateCXXFunctionTemplate(
7315
7313
Impl.diagnose (HeaderLoc (func->getBeginLoc ()),
7316
7314
diag::unable_to_substitute_cxx_function_template,
7317
7315
getFuncName (), templateParams);
7316
+ };
7317
+
7318
+ auto &sema = getClangInstance ().getSema ();
7319
+ auto *spec = sema.InstantiateFunctionDeclaration (func, templateArgList,
7320
+ clang::SourceLocation ());
7321
+ if (!spec || spec->isInvalidDecl ()) {
7322
+ diagnoseSubstFail ();
7318
7323
return nullptr ;
7319
7324
}
7325
+
7320
7326
sema.InstantiateFunctionDefinition (clang::SourceLocation (), spec);
7327
+ // Even if the declaration can be instantiated, the definition may contain
7328
+ // a substitution failure that renders spec invalid as a side-effect.
7329
+ if (spec->isInvalidDecl ()) {
7330
+ diagnoseSubstFail ();
7331
+ return nullptr ;
7332
+ }
7333
+
7321
7334
return spec;
7322
7335
}
7323
7336
@@ -7714,6 +7727,12 @@ ClangImporter::getCXXFunctionTemplateSpecialization(SubstitutionMap subst,
7714
7727
assert (isa<clang::FunctionTemplateDecl>(decl->getClangDecl ()) &&
7715
7728
" This API should only be used with function templates." );
7716
7729
7730
+ // If we hit some instantiation failure and expect the compiler to imminently
7731
+ // terminate (with an error), return some reasonable-looking placeholder value
7732
+ // in the meantime because callers expect this function to return some
7733
+ // non-empty ConcreteDeclRef.
7734
+ auto failurePlaceholder = [&]() { return ConcreteDeclRef (decl); };
7735
+
7717
7736
auto *newFn =
7718
7737
decl->getASTContext ()
7719
7738
.getClangModuleLoader ()
@@ -7722,31 +7741,28 @@ ClangImporter::getCXXFunctionTemplateSpecialization(SubstitutionMap subst,
7722
7741
const_cast <clang::FunctionTemplateDecl *>(
7723
7742
cast<clang::FunctionTemplateDecl>(decl->getClangDecl ())),
7724
7743
subst);
7725
- // We failed to specialize this function template. The compiler is going to
7726
- // exit soon. Return something valid in the meantime.
7727
7744
if (!newFn)
7728
- return ConcreteDeclRef (decl );
7745
+ return failurePlaceholder ( );
7729
7746
7730
7747
auto [fnIt, inserted] =
7731
7748
Impl.specializedFunctionTemplates .try_emplace (newFn, nullptr );
7732
7749
if (!inserted)
7733
7750
return ConcreteDeclRef (fnIt->second );
7734
7751
7735
- auto newDecl = cast_or_null<ValueDecl>(
7736
- decl->getASTContext ().getClangModuleLoader ()->importDeclDirectly (
7737
- newFn));
7752
+ auto *newDecl = cast_or_null<ValueDecl>(
7753
+ decl->getASTContext ().getClangModuleLoader ()->importDeclDirectly (newFn));
7754
+ if (!newDecl)
7755
+ return failurePlaceholder ();
7738
7756
7739
- if (auto fn = dyn_cast<AbstractFunctionDecl>(newDecl)) {
7757
+ if (auto * fn = dyn_cast<AbstractFunctionDecl>(newDecl)) {
7740
7758
if (!subst.empty ()) {
7741
7759
newDecl = rewriteIntegerTypes (subst, decl, fn);
7742
7760
}
7743
7761
}
7744
7762
7745
- if (auto fn = dyn_cast<FuncDecl>(decl)) {
7763
+ if (auto * fn = dyn_cast<FuncDecl>(decl)) {
7746
7764
newDecl = addThunkForDependentTypes (fn, cast<FuncDecl>(newDecl));
7747
- }
7748
7765
7749
- if (auto fn = dyn_cast<FuncDecl>(decl)) {
7750
7766
if (newFn->getNumParams () != fn->getParameters ()->size ()) {
7751
7767
newDecl = generateThunkForExtraMetatypes (subst, fn,
7752
7768
cast<FuncDecl>(newDecl));
0 commit comments