]> granicus.if.org Git - clang/commitdiff
When declaring an out-of-line template, attempt to rebuild any types
authorDouglas Gregor <dgregor@apple.com>
Fri, 14 Oct 2011 15:31:12 +0000 (15:31 +0000)
committerDouglas Gregor <dgregor@apple.com>
Fri, 14 Oct 2011 15:31:12 +0000 (15:31 +0000)
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

include/clang/Sema/Sema.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaTemplate.cpp
test/SemaTemplate/current-instantiation.cpp

index dabbcb4734205f9f4b5c05a5e56feb0d63ff7e4b..22d5db2944401b93a1981583f1e81e926edb0fa8 100644 (file)
@@ -4134,7 +4134,9 @@ public:
   bool RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS);
 
   ExprResult RebuildExprInCurrentInstantiation(Expr *E);
-
+  bool RebuildTemplateParamsInCurrentInstantiation(
+                                                TemplateParameterList *Params);
+  
   std::string
   getTemplateArgumentBindingsText(const TemplateParameterList *Params,
                                   const TemplateArgumentList &Args);
index 8e2ff5ca881a55b5ac4870f432e10956c76ff683..ecc81ccb8397bbadfb1ab6ec3243ed7b3db2fbd0 100644 (file)
@@ -4789,6 +4789,16 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
           Diag(NewFD->getLocation(), diag::err_destructor_template);
           return 0;
         }
+        
+        // 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 (DC->isDependentContext()) {
+          ContextRAII SavedContext(*this, DC);
+          if (RebuildTemplateParamsInCurrentInstantiation(TemplateParams))
+            Invalid = true;
+        }
+        
 
         FunctionTemplate = FunctionTemplateDecl::Create(Context, DC,
                                                         NewFD->getLocation(),
index cf8848bc6e69870e8bd77f3f21592a7bcf68ba73..929d74efa98a4121f486f68f3edd0ec72985af53 100644 (file)
@@ -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
index fe7213f14385114b45162988f12320aaf21a4f73..ccef811e22243837f610a8f356336298d9268d55 100644 (file)
@@ -215,3 +215,23 @@ namespace PR9255 {
     };
   };
 }
+
+namespace rdar10194295 {
+  template<typename XT>
+  class X {
+  public:
+    enum Enum { Yes, No };
+    template<Enum> void foo();
+    template<Enum> class Inner;
+  };
+
+  template<typename XT>
+  template<typename X<XT>::Enum>
+  void X<XT>::foo()
+  {
+  }
+
+  template<typename XT>
+  template<typename X<XT>::Enum>
+  class X<XT>::Inner { };
+}