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. llvm-svn: 102974
This commit is contained in:
parent
81bfca7bde
commit
1bd7a94460
|
@ -3309,7 +3309,8 @@ public:
|
|||
|
||||
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 {
|
||||
|
|
|
@ -38,10 +38,16 @@ using namespace clang;
|
|||
/// 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 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,
|
|||
|
||||
// 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;
|
||||
|
|
|
@ -1970,8 +1970,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
|
|||
|
||||
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 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
|
|||
CurContext = Function;
|
||||
|
||||
MultiLevelTemplateArgumentList TemplateArgs =
|
||||
getTemplateInstantiationArgs(Function);
|
||||
getTemplateInstantiationArgs(Function, 0, false, PatternDecl);
|
||||
|
||||
// If this is a constructor, instantiate the member initializers.
|
||||
if (const CXXConstructorDecl *Ctor =
|
||||
|
|
|
@ -142,3 +142,68 @@ namespace FriendTemplateDefinition {
|
|||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue