Ensure that we don't leave behind "InstantiatingSpecialization" entries

after destroying an InstantiatingTemplate object.

This previously caused us to (silently!) bail out of class template
instantiation, thinking we'd produced an error, in some corner cases.
This commit is contained in:
Richard Smith 2020-12-10 16:49:27 -08:00
parent f23fae29eb
commit a3fe12dc58
3 changed files with 24 additions and 14 deletions

View File

@ -390,6 +390,9 @@ void Sema::Initialize() {
}
Sema::~Sema() {
assert(InstantiatingSpecializations.empty() &&
"failed to clean up an InstantiatingTemplate?");
if (VisContext) FreeVisContext();
// Kill all the active scopes.

View File

@ -261,7 +261,7 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
AlreadyInstantiating = !Inst.Entity ? false :
!SemaRef.InstantiatingSpecializations
.insert(std::make_pair(Inst.Entity->getCanonicalDecl(), Inst.Kind))
.insert({Inst.Entity->getCanonicalDecl(), Inst.Kind})
.second;
atTemplateBegin(SemaRef.TemplateInstCallbacks, SemaRef, Inst);
}
@ -480,7 +480,7 @@ void Sema::InstantiatingTemplate::Clear() {
auto &Active = SemaRef.CodeSynthesisContexts.back();
if (Active.Entity)
SemaRef.InstantiatingSpecializations.erase(
std::make_pair(Active.Entity, Active.Kind));
{Active.Entity->getCanonicalDecl(), Active.Kind});
}
atTemplateEnd(SemaRef.TemplateInstCallbacks, SemaRef,
@ -3037,14 +3037,16 @@ bool Sema::usesPartialOrExplicitSpecialization(
/// Get the instantiation pattern to use to instantiate the definition of a
/// given ClassTemplateSpecializationDecl (either the pattern of the primary
/// template or of a partial specialization).
static CXXRecordDecl *
static ActionResult<CXXRecordDecl *>
getPatternForClassTemplateSpecialization(
Sema &S, SourceLocation PointOfInstantiation,
ClassTemplateSpecializationDecl *ClassTemplateSpec,
TemplateSpecializationKind TSK, bool Complain) {
TemplateSpecializationKind TSK) {
Sema::InstantiatingTemplate Inst(S, PointOfInstantiation, ClassTemplateSpec);
if (Inst.isInvalid() || Inst.isAlreadyInstantiating())
return nullptr;
if (Inst.isInvalid())
return {/*Invalid=*/true};
if (Inst.isAlreadyInstantiating())
return {/*Invalid=*/false};
llvm::PointerUnion<ClassTemplateDecl *,
ClassTemplatePartialSpecializationDecl *>
@ -3141,7 +3143,7 @@ getPatternForClassTemplateSpecialization(
<< S.getTemplateArgumentBindingsText(
P->Partial->getTemplateParameters(), *P->Args);
return nullptr;
return {/*Invalid=*/true};
}
}
@ -3192,14 +3194,15 @@ bool Sema::InstantiateClassTemplateSpecialization(
if (ClassTemplateSpec->isInvalidDecl())
return true;
CXXRecordDecl *Pattern = getPatternForClassTemplateSpecialization(
*this, PointOfInstantiation, ClassTemplateSpec, TSK, Complain);
if (!Pattern)
return true;
ActionResult<CXXRecordDecl *> Pattern =
getPatternForClassTemplateSpecialization(*this, PointOfInstantiation,
ClassTemplateSpec, TSK);
if (!Pattern.isUsable())
return Pattern.isInvalid();
return InstantiateClass(PointOfInstantiation, ClassTemplateSpec, Pattern,
getTemplateInstantiationArgs(ClassTemplateSpec), TSK,
Complain);
return InstantiateClass(
PointOfInstantiation, ClassTemplateSpec, Pattern.get(),
getTemplateInstantiationArgs(ClassTemplateSpec), TSK, Complain);
}
/// Instantiates the definitions of all of the member

View File

@ -4521,6 +4521,8 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
// into a template instantiation for this specific function template
// specialization, which is not a SFINAE context, so that we diagnose any
// further errors in the declaration itself.
//
// FIXME: This is a hack.
typedef Sema::CodeSynthesisContext ActiveInstType;
ActiveInstType &ActiveInst = SemaRef.CodeSynthesisContexts.back();
if (ActiveInst.Kind == ActiveInstType::ExplicitTemplateArgumentSubstitution ||
@ -4530,6 +4532,8 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
assert(FunTmpl->getTemplatedDecl() == Tmpl &&
"Deduction from the wrong function template?");
(void) FunTmpl;
SemaRef.InstantiatingSpecializations.erase(
{ActiveInst.Entity->getCanonicalDecl(), ActiveInst.Kind});
atTemplateEnd(SemaRef.TemplateInstCallbacks, SemaRef, ActiveInst);
ActiveInst.Kind = ActiveInstType::TemplateInstantiation;
ActiveInst.Entity = New;