[cfe-commits] r102974 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaTemplateInstantiate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaTemplate/friend-template.cpp

Douglas Gregor dgregor at apple.com
Mon May 3 16:29:10 PDT 2010


Author: dgregor
Date: Mon May  3 18:29:10 2010
New Revision: 102974

URL: http://llvm.org/viewvc/llvm-project?rev=102974&view=rev
Log:
When computing the template arguments for the instantiation of a
friend function template, be sure to adjust the computed template
argument lists based on the location of the definition of the function
template: it's possible that the definition we're instantiating with
and the template declaration that we found when creating the
specialization are in different contexts, which meant that we would
end up using the wrong template arguments for instantiation.

Fixes PR7013; all Boost.DynamicBitset tests now pass.


Modified:
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/test/SemaTemplate/friend-template.cpp

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=102974&r1=102973&r2=102974&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon May  3 18:29:10 2010
@@ -3309,7 +3309,8 @@
 
   MultiLevelTemplateArgumentList getTemplateInstantiationArgs(NamedDecl *D,
                                      const TemplateArgumentList *Innermost = 0,
-                                     bool RelativeToPrimary = false);
+                                                bool RelativeToPrimary = false,
+                                               const FunctionDecl *Pattern = 0);
 
   /// \brief A template instantiation that is currently in progress.
   struct ActiveTemplateInstantiation {

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=102974&r1=102973&r2=102974&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Mon May  3 18:29:10 2010
@@ -38,10 +38,16 @@
 /// arguments relative to the primary template, even when we're
 /// dealing with a specialization. This is only relevant for function
 /// template specializations.
+///
+/// \param Pattern If non-NULL, indicates the pattern from which we will be
+/// instantiating the definition of the given declaration, \p D. This is
+/// used to determine the proper set of template instantiation arguments for
+/// friend function template specializations.
 MultiLevelTemplateArgumentList
 Sema::getTemplateInstantiationArgs(NamedDecl *D, 
                                    const TemplateArgumentList *Innermost,
-                                   bool RelativeToPrimary) {
+                                   bool RelativeToPrimary,
+                                   const FunctionDecl *Pattern) {
   // Accumulate the set of template argument lists in this structure.
   MultiLevelTemplateArgumentList Result;
 
@@ -89,9 +95,11 @@
       
       // If this is a friend declaration and it declares an entity at
       // namespace scope, take arguments from its lexical parent
-      // instead of its semantic parent.
+      // instead of its semantic parent, unless of course the pattern we're
+      // instantiating actually comes from the file's context!
       if (Function->getFriendObjectKind() &&
-          Function->getDeclContext()->isFileContext()) {
+          Function->getDeclContext()->isFileContext() &&
+          (!Pattern || !Pattern->getLexicalDeclContext()->isFileContext())) {
         Ctx = Function->getLexicalDeclContext();
         RelativeToPrimary = false;
         continue;

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=102974&r1=102973&r2=102974&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon May  3 18:29:10 2010
@@ -1970,8 +1970,8 @@
 
   InstantiatingTemplate Inst(*this, PointOfInstantiation, Function);
   if (Inst)
-    return;
-
+    return;  
+  
   // If we're performing recursive template instantiation, create our own
   // queue of pending implicit instantiations that we will instantiate later,
   // while we're still within our own instantiation context.
@@ -2003,7 +2003,7 @@
   CurContext = Function;
 
   MultiLevelTemplateArgumentList TemplateArgs =
-    getTemplateInstantiationArgs(Function);
+    getTemplateInstantiationArgs(Function, 0, false, PatternDecl);
 
   // If this is a constructor, instantiate the member initializers.
   if (const CXXConstructorDecl *Ctor =

Modified: cfe/trunk/test/SemaTemplate/friend-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/friend-template.cpp?rev=102974&r1=102973&r2=102974&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/friend-template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/friend-template.cpp Mon May  3 18:29:10 2010
@@ -142,3 +142,68 @@
     f(x, i5);
   }
 }
+
+namespace PR7013a {
+  template<class > struct X0
+  {
+    typedef int type;
+  };
+  template<typename > struct X1
+  {
+  };
+  template<typename , typename T> struct X2
+  {
+    typename T::type e;
+  };
+  namespace N
+  {
+    template <typename = int, typename = X1<int> > struct X3
+    {
+      template <typename T1, typename T2, typename B> friend void op(X2<T1, T2>& , B);
+    };
+    template <typename Ch, typename Tr, typename B> void op(X2<Ch, Tr>& , B)
+    {
+      X2<int, Tr> s;
+    }
+  }
+  int n()
+  {
+    X2<int, X0<int> > ngs;
+    N::X3<> b;
+    op(ngs, b);
+    return 0;
+  }
+}
+
+namespace PR7013b {
+  template<class > struct X0
+  {
+    typedef int type;
+  };
+  template<typename > struct X1
+  {
+  };
+  template<typename , typename T> struct X2
+  {
+    typename T::type e;
+  };
+  namespace N
+  {
+    template <typename = X1<int> > struct X3
+    {
+      template <typename T1, typename T2, typename B> friend void op(X2<T1, T2>& , B);
+    };
+    template <typename Ch, typename Tr, typename B> void op(X2<Ch, Tr>& , B)
+    {
+      X2<int, Tr> s;
+    }
+  }
+  int n()
+  {
+    X2<int, X0<int> > ngs;
+    N::X3<> b;
+    op(ngs, b);
+    return 0;
+  }
+
+}





More information about the cfe-commits mailing list