aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaTemplate.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-10-14 15:31:12 +0000
committerDouglas Gregor <dgregor@apple.com>2011-10-14 15:31:12 +0000
commit2060650f2743650a815ce3daa414352911d408fd (patch)
tree8f1edf0ad49092a628e05bbd30bc70fc4aebea94 /lib/Sema/SemaTemplate.cpp
parent6164ea1d75385b6fc3c19e5ab9bb686298436a5a (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.cpp48
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