diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-10-14 15:31:12 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-10-14 15:31:12 +0000 |
commit | 2060650f2743650a815ce3daa414352911d408fd (patch) | |
tree | 8f1edf0ad49092a628e05bbd30bc70fc4aebea94 /lib/Sema/SemaTemplate.cpp | |
parent | 6164ea1d75385b6fc3c19e5ab9bb686298436a5a (diff) |
When declaring an out-of-line template, attempt to rebuild any types
within the template parameter list that may have changed now that we
know the current instantiation. Fixes <rdar://problem/10194295>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141954 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index cf8848bc6e..929d74efa9 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -846,6 +846,15 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, if (RequireCompleteDeclContext(SS, SemanticContext)) return true; + // If we're adding a template to a dependent context, we may need to + // rebuilding some of the types used within the template parameter list, + // now that we know what the current instantiation is. + if (SemanticContext->isDependentContext()) { + ContextRAII SavedContext(*this, SemanticContext); + if (RebuildTemplateParamsInCurrentInstantiation(TemplateParams)) + Invalid = true; + } + LookupQualifiedName(Previous, SemanticContext); } else { SemanticContext = CurContext; @@ -6699,6 +6708,45 @@ bool Sema::RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS) { return false; } +/// \brief Rebuild the template parameters now that we know we're in a current +/// instantiation. +bool Sema::RebuildTemplateParamsInCurrentInstantiation( + TemplateParameterList *Params) { + for (unsigned I = 0, N = Params->size(); I != N; ++I) { + Decl *Param = Params->getParam(I); + + // There is nothing to rebuild in a type parameter. + if (isa<TemplateTypeParmDecl>(Param)) + continue; + + // Rebuild the template parameter list of a template template parameter. + if (TemplateTemplateParmDecl *TTP + = dyn_cast<TemplateTemplateParmDecl>(Param)) { + if (RebuildTemplateParamsInCurrentInstantiation( + TTP->getTemplateParameters())) + return true; + + continue; + } + + // Rebuild the type of a non-type template parameter. + NonTypeTemplateParmDecl *NTTP = cast<NonTypeTemplateParmDecl>(Param); + TypeSourceInfo *NewTSI + = RebuildTypeInCurrentInstantiation(NTTP->getTypeSourceInfo(), + NTTP->getLocation(), + NTTP->getDeclName()); + if (!NewTSI) + return true; + + if (NewTSI != NTTP->getTypeSourceInfo()) { + NTTP->setTypeSourceInfo(NewTSI); + NTTP->setType(NewTSI->getType()); + } + } + + return false; +} + /// \brief Produces a formatted string that describes the binding of /// template parameters to template arguments. std::string |