]> granicus.if.org Git - clang/commitdiff
Fix instantiation of template functions with local classes that contain virtual
authorChandler Carruth <chandlerc@gmail.com>
Mon, 15 Feb 2010 22:12:26 +0000 (22:12 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Mon, 15 Feb 2010 22:12:26 +0000 (22:12 +0000)
methods.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96283 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaTemplateInstantiate.cpp
test/SemaTemplate/instantiate-local-class.cpp

index 2d354575f0e4fd6cd9c5c1eeeca67c61ea875fc9..51e17fe472e5a3cdff47ce606f36da9f09f11eeb 100644 (file)
@@ -1130,9 +1130,18 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
   // If this is a polymorphic C++ class without a key function, we'll
   // have to mark all of the virtual members to allow emission of a vtable
   // in this translation unit.
-  if (Instantiation->isDynamicClass() && !Context.getKeyFunction(Instantiation))
+  if (Instantiation->isDynamicClass() &&
+      !Context.getKeyFunction(Instantiation)) {
+    // Local classes need to have their methods instantiated immediately in
+    // order to have the correct instantiation scope.
+    if (Instantiation->isLocalClass()) {
+      MarkVirtualMembersReferenced(PointOfInstantiation,
+                                   Instantiation);
+    } else {
       ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(Instantiation,
                                                        PointOfInstantiation));
+    }
+  }
 
   if (!Invalid)
     Consumer.HandleTagDeclDefinition(Instantiation);
index 768eb2170a155cc111a976fbace192d3782745cc..72ad90a04f20af56d119b09f5d12ff44845963c3 100644 (file)
@@ -32,3 +32,21 @@ namespace PR5764 {
   }
 }
 
+// Instantiation of local classes with virtual functions.
+namespace local_class_with_virtual_functions {
+  template <typename T> struct X { };
+  template <typename T> struct Y { };
+
+  template <typename T>
+  void f() {
+    struct Z : public X<Y<T>*> {
+      virtual void g(Y<T>* y) { }
+      void g2(int x) {(void)x;}
+    };
+    Z z;
+    (void)z;
+  }
+
+  struct S { };
+  void test() { f<S>(); }
+}