When we are instantiating a member function of a local class, be sure
to merge the local instantiation scope with the outer local
instantiation scope, so that we can instantiate declarations from the
function owning the local class. Fixes an assert while instantiating
Boost.MPL's BOOST_MPL_ASSERT_MSG.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93651 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index 497f863..0902b45 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -1017,13 +1017,8 @@
 };
 
 inline bool Decl::isTemplateParameter() const {
-  return getKind() == TemplateTypeParm || getKind() == NonTypeTemplateParm;
-}
-
-inline bool Decl::isDefinedOutsideFunctionOrMethod() const {
-  if (getDeclContext())
-    return !getDeclContext()->getLookupContext()->isFunctionOrMethod();
-  return true;
+  return getKind() == TemplateTypeParm || getKind() == NonTypeTemplateParm ||
+         getKind() == TemplateTemplateParm;
 }
 
 } // end clang.
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 3afb4e4..76ff834 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -102,6 +102,17 @@
   return isa<FunctionDecl>(this) || isa<FunctionTemplateDecl>(this);
 }
 
+bool Decl::isDefinedOutsideFunctionOrMethod() const {
+  for (const DeclContext *DC = getDeclContext(); 
+       DC && !DC->isTranslationUnit(); 
+       DC = DC->getParent())
+    if (DC->isFunctionOrMethod())
+      return false;
+
+  return true;
+}
+
+
 //===----------------------------------------------------------------------===//
 // PrettyStackTraceDecl Implementation
 //===----------------------------------------------------------------------===//
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index e909c4f..e6be538 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -717,7 +717,10 @@
       return Info->Function;
   }
 
-  Sema::LocalInstantiationScope Scope(SemaRef, TemplateParams != 0);
+  bool MergeWithParentScope = (TemplateParams != 0) ||
+    !(isa<Decl>(Owner) && 
+      cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod());
+  Sema::LocalInstantiationScope Scope(SemaRef, MergeWithParentScope);
 
   llvm::SmallVector<ParmVarDecl *, 4> Params;
   QualType T = SubstFunctionType(D, Params);
@@ -844,7 +847,10 @@
       return Info->Function;
   }
 
-  Sema::LocalInstantiationScope Scope(SemaRef, TemplateParams != 0);
+  bool MergeWithParentScope = (TemplateParams != 0) ||
+    !(isa<Decl>(Owner) && 
+      cast<Decl>(Owner)->isDefinedOutsideFunctionOrMethod());
+  Sema::LocalInstantiationScope Scope(SemaRef, MergeWithParentScope);
 
   llvm::SmallVector<ParmVarDecl *, 4> Params;
   QualType T = SubstFunctionType(D, Params);
diff --git a/test/SemaTemplate/instantiate-local-class.cpp b/test/SemaTemplate/instantiate-local-class.cpp
new file mode 100644
index 0000000..5cb63b4
--- /dev/null
+++ b/test/SemaTemplate/instantiate-local-class.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -verify %s
+template<typename T>
+void f0() {
+  struct X;
+  typedef struct Y {
+    T (X::* f1())(int) { return 0; }
+  } Y2;
+
+  Y2 y = Y();
+}
+
+template void f0<int>();