]> granicus.if.org Git - clang/commitdiff
When we are instantiating a member function of a local class, be sure
authorDouglas Gregor <dgregor@apple.com>
Sat, 16 Jan 2010 20:21:20 +0000 (20:21 +0000)
committerDouglas Gregor <dgregor@apple.com>
Sat, 16 Jan 2010 20:21:20 +0000 (20:21 +0000)
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

include/clang/AST/DeclBase.h
lib/AST/DeclBase.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/SemaTemplate/instantiate-local-class.cpp [new file with mode: 0644]

index 497f86347a860bc22e28a17205744cccbb450c4b..0902b450a4acaecc26eb7ca9a224d94fd5eb6cef 100644 (file)
@@ -1017,13 +1017,8 @@ private:
 };
 
 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.
index 3afb4e44f3eb05c32ebdae56004f983e26659431..76ff83448a0300e3f5be5cdd2119aa4baf537111 100644 (file)
@@ -102,6 +102,17 @@ bool Decl::isFunctionOrFunctionTemplate() const {
   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
 //===----------------------------------------------------------------------===//
index e909c4f0b9b6761e99e5cae58942c3a229315755..e6be5389cd06c6a178e3ed2cb023310613c5e727 100644 (file)
@@ -717,7 +717,10 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D,
       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 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
       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 (file)
index 0000000..5cb63b4
--- /dev/null
@@ -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>();