aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Sema/Sema.h3
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp14
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp6
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 =