[cfe-commits] r92839 - in /cfe/trunk: lib/Sema/SemaDecl.cpp test/SemaCXX/virtual-member-functions-key-function.cpp

Douglas Gregor dgregor at apple.com
Wed Jan 6 09:00:52 PST 2010


Author: dgregor
Date: Wed Jan  6 11:00:51 2010
New Revision: 92839

URL: http://llvm.org/viewvc/llvm-project?rev=92839&view=rev
Log:
Make sure that the key-function computation produces the correct
result for a nested class whose first non-pure virtual member function
has an inline body. Previously, we were checking for the key function
before we had seen the (delayed) inline body. 

Modified:
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/SemaCXX/virtual-member-functions-key-function.cpp

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=92839&r1=92838&r2=92839&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Jan  6 11:00:51 2010
@@ -5086,6 +5086,29 @@
          "Broken injected-class-name");
 }
 
+// Traverses the class and any nested classes, making a note of any 
+// dynamic classes that have no key function so that we can mark all of
+// their virtual member functions as "used" at the end of the translation
+// unit. This ensures that all functions needed by the vtable will get
+// instantiated/synthesized.
+static void 
+RecordDynamicClassesWithNoKeyFunction(Sema &S, CXXRecordDecl *Record,
+                                      SourceLocation Loc) {
+  // We don't look at dependent or undefined classes.
+  if (Record->isDependentContext() || !Record->isDefinition())
+    return;
+  
+  if (Record->isDynamicClass() && !S.Context.getKeyFunction(Record))
+    S.ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(Record, Loc));
+  
+  for (DeclContext::decl_iterator D = Record->decls_begin(), 
+                               DEnd = Record->decls_end();
+       D != DEnd; ++D) {
+    if (CXXRecordDecl *Nested = dyn_cast<CXXRecordDecl>(*D))
+      RecordDynamicClassesWithNoKeyFunction(S, Nested, Loc);
+  }
+}
+
 void Sema::ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagD,
                                     SourceLocation RBraceLoc) {
   AdjustDeclIfTemplate(TagD);
@@ -5098,16 +5121,10 @@
   // Exit this scope of this tag's definition.
   PopDeclContext();
 
-  // 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 (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(Tag)) {
-    if (!Record->isDependentContext() && Record->isDynamicClass() &&
-        !Context.getKeyFunction(Record))
-      ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(Record, 
-                                                                 RBraceLoc));
-  }
-
+  if (isa<CXXRecordDecl>(Tag) && !Tag->getDeclContext()->isRecord())
+    RecordDynamicClassesWithNoKeyFunction(*this, cast<CXXRecordDecl>(Tag),
+                                          RBraceLoc);
+                                          
   // Notify the consumer that we've defined a tag.
   Consumer.HandleTagDeclDefinition(Tag);
 }

Modified: cfe/trunk/test/SemaCXX/virtual-member-functions-key-function.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/virtual-member-functions-key-function.cpp?rev=92839&r1=92838&r2=92839&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/virtual-member-functions-key-function.cpp (original)
+++ cfe/trunk/test/SemaCXX/virtual-member-functions-key-function.cpp Wed Jan  6 11:00:51 2010
@@ -16,3 +16,14 @@
   (void)new B;
   (void)new C;
 }
+
+// Make sure that the key-function computation is consistent when the
+// first virtual member function of a nested class has an inline body.
+struct Outer {
+  struct Inner {
+    virtual void f() { }
+    void g();
+  };
+};
+
+void Outer::Inner::g() { }





More information about the cfe-commits mailing list