[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