From: Richard Smith Date: Fri, 11 Dec 2020 00:49:27 +0000 (-0800) Subject: Ensure that we don't leave behind "InstantiatingSpecialization" entries X-Git-Tag: llvmorg-13-init~3703 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a3fe12dc58aa2a0dd7292d748b7c104225f863ba;p=platform%2Fupstream%2Fllvm.git 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. --- diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 456daab..829ab22 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -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. diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index e8e34c3..39ea9e0 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -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 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 @@ -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 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 diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 9db4f23..d3d6df5 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -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;