diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/Sema.h | 3 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 14 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 6 |
3 files changed, 16 insertions, 7 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index e6cf0599b4..f146c85787 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -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 { diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index e727cdbc9e..14bd243201 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -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; diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index a81e5e95f8..8b851b21ea 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -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 = |