diff options
| author | Douglas Gregor <dgregor@apple.com> | 2010-01-06 17:00:51 +0000 |
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2010-01-06 17:00:51 +0000 |
| commit | 859f0ae041a41d484a1b6ce75ee813633d88ab36 (patch) | |
| tree | 4e551ac1ab9b04ddbf7e842f69fdbf2828219cde | |
| parent | 127286c58ba78e15bd8f79b7ba50dfb2a71f41b9 (diff) | |
| download | bcm5719-llvm-859f0ae041a41d484a1b6ce75ee813633d88ab36.tar.gz bcm5719-llvm-859f0ae041a41d484a1b6ce75ee813633d88ab36.zip | |
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.
llvm-svn: 92839
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 37 | ||||
| -rw-r--r-- | clang/test/SemaCXX/virtual-member-functions-key-function.cpp | 11 |
2 files changed, 38 insertions, 10 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 383893cc2fc..9ed37f604fc 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -5086,6 +5086,29 @@ void Sema::ActOnStartCXXMemberDeclarations(Scope *S, DeclPtrTy TagD, "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 @@ void Sema::ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagD, // 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); } diff --git a/clang/test/SemaCXX/virtual-member-functions-key-function.cpp b/clang/test/SemaCXX/virtual-member-functions-key-function.cpp index 8da6bf55984..2e21fb7365e 100644 --- a/clang/test/SemaCXX/virtual-member-functions-key-function.cpp +++ b/clang/test/SemaCXX/virtual-member-functions-key-function.cpp @@ -16,3 +16,14 @@ void f() { (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() { } |

