@@ -7300,10 +7300,8 @@ clang::FunctionDecl *ClangImporter::instantiateCXXFunctionTemplate(
73007300 // Instantiate a specialization of this template using the substitution map.
73017301 auto *templateArgList = clang::TemplateArgumentList::CreateCopy (
73027302 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 = [&]() {
73077305 std::string templateParams;
73087306 llvm::raw_string_ostream templateParamsStream (templateParams);
73097307 llvm::interleaveComma (templateArgList->asArray (), templateParamsStream,
@@ -7315,9 +7313,24 @@ clang::FunctionDecl *ClangImporter::instantiateCXXFunctionTemplate(
73157313 Impl.diagnose (HeaderLoc (func->getBeginLoc ()),
73167314 diag::unable_to_substitute_cxx_function_template,
73177315 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 ();
73187323 return nullptr ;
73197324 }
7325+
73207326 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+
73217334 return spec;
73227335}
73237336
@@ -7714,6 +7727,12 @@ ClangImporter::getCXXFunctionTemplateSpecialization(SubstitutionMap subst,
77147727 assert (isa<clang::FunctionTemplateDecl>(decl->getClangDecl ()) &&
77157728 " This API should only be used with function templates." );
77167729
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+
77177736 auto *newFn =
77187737 decl->getASTContext ()
77197738 .getClangModuleLoader ()
@@ -7722,31 +7741,28 @@ ClangImporter::getCXXFunctionTemplateSpecialization(SubstitutionMap subst,
77227741 const_cast <clang::FunctionTemplateDecl *>(
77237742 cast<clang::FunctionTemplateDecl>(decl->getClangDecl ())),
77247743 subst);
7725- // We failed to specialize this function template. The compiler is going to
7726- // exit soon. Return something valid in the meantime.
77277744 if (!newFn)
7728- return ConcreteDeclRef (decl );
7745+ return failurePlaceholder ( );
77297746
77307747 auto [fnIt, inserted] =
77317748 Impl.specializedFunctionTemplates .try_emplace (newFn, nullptr );
77327749 if (!inserted)
77337750 return ConcreteDeclRef (fnIt->second );
77347751
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 ();
77387756
7739- if (auto fn = dyn_cast<AbstractFunctionDecl>(newDecl)) {
7757+ if (auto * fn = dyn_cast<AbstractFunctionDecl>(newDecl)) {
77407758 if (!subst.empty ()) {
77417759 newDecl = rewriteIntegerTypes (subst, decl, fn);
77427760 }
77437761 }
77447762
7745- if (auto fn = dyn_cast<FuncDecl>(decl)) {
7763+ if (auto * fn = dyn_cast<FuncDecl>(decl)) {
77467764 newDecl = addThunkForDependentTypes (fn, cast<FuncDecl>(newDecl));
7747- }
77487765
7749- if (auto fn = dyn_cast<FuncDecl>(decl)) {
77507766 if (newFn->getNumParams () != fn->getParameters ()->size ()) {
77517767 newDecl = generateThunkForExtraMetatypes (subst, fn,
77527768 cast<FuncDecl>(newDecl));
0 commit comments