diff options
| author | Douglas Gregor <dgregor@apple.com> | 2010-05-11 20:24:17 +0000 |
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2010-05-11 20:24:17 +0000 |
| commit | 0c4aad15c2493bdf7b1ecd71755382a1276fd35a (patch) | |
| tree | 21496be6387e5ebf76c11fa219d5880c6384195e /clang/lib/Sema/SemaDeclCXX.cpp | |
| parent | 6c5e4355bbda4ef15dc753c140a8a04e425b806c (diff) | |
| download | bcm5719-llvm-0c4aad15c2493bdf7b1ecd71755382a1276fd35a.tar.gz bcm5719-llvm-0c4aad15c2493bdf7b1ecd71755382a1276fd35a.zip | |
Do not mark the virtual members of an implicitly-instantiated class as
referenced unless we see one of them defined (or the key function
defined, if it as one) or if we need the vtable for something. Fixes
PR7114.
llvm-svn: 103497
Diffstat (limited to 'clang/lib/Sema/SemaDeclCXX.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 59 |
1 files changed, 51 insertions, 8 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index e32a308af58..dc27dca1958 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -4146,7 +4146,9 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor"); ImplicitlyDefinedFunctionScope Scope(*this, Constructor); - if (SetBaseOrMemberInitializers(Constructor, 0, 0, /*AnyErrors=*/false)) { + ErrorTrap Trap(*this); + if (SetBaseOrMemberInitializers(Constructor, 0, 0, /*AnyErrors=*/false) || + Trap.hasErrorOccurred()) { Diag(CurrentLocation, diag::note_member_synthesized_at) << CXXConstructor << Context.getTagDeclType(ClassDecl); Constructor->setInvalidDecl(); @@ -4162,14 +4164,16 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, CXXRecordDecl *ClassDecl = Destructor->getParent(); assert(ClassDecl && "DefineImplicitDestructor - invalid destructor"); + if (Destructor->isInvalidDecl()) + return; + ImplicitlyDefinedFunctionScope Scope(*this, Destructor); + ErrorTrap Trap(*this); MarkBaseAndMemberDestructorsReferenced(Destructor->getLocation(), Destructor->getParent()); - // FIXME: If CheckDestructor fails, we should emit a note about where the - // implicit destructor was needed. - if (CheckDestructor(Destructor)) { + if (CheckDestructor(Destructor) || Trap.hasErrorOccurred()) { Diag(CurrentLocation, diag::note_member_synthesized_at) << CXXDestructor << Context.getTagDeclType(ClassDecl); @@ -4396,6 +4400,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, CopyAssignOperator->setUsed(); ImplicitlyDefinedFunctionScope Scope(*this, CopyAssignOperator); + ErrorTrap Trap(*this); // C++0x [class.copy]p30: // The implicitly-defined or explicitly-defaulted copy assignment operator @@ -4619,6 +4624,13 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, } } + if (Trap.hasErrorOccurred()) { + Diag(CurrentLocation, diag::note_member_synthesized_at) + << CXXCopyAssignment << Context.getTagDeclType(ClassDecl); + CopyAssignOperator->setInvalidDecl(); + return; + } + if (Invalid) { CopyAssignOperator->setInvalidDecl(); return; @@ -4642,8 +4654,10 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor"); ImplicitlyDefinedFunctionScope Scope(*this, CopyConstructor); + ErrorTrap Trap(*this); - if (SetBaseOrMemberInitializers(CopyConstructor, 0, 0, /*AnyErrors=*/false)) { + if (SetBaseOrMemberInitializers(CopyConstructor, 0, 0, /*AnyErrors=*/false) || + Trap.hasErrorOccurred()) { Diag(CurrentLocation, diag::note_member_synthesized_at) << CXXCopyConstructor << Context.getTagDeclType(ClassDecl); CopyConstructor->setInvalidDecl(); @@ -6068,12 +6082,32 @@ void Sema::MaybeMarkVirtualMembersReferenced(SourceLocation Loc, return; TemplateSpecializationKind kind = RD->getTemplateSpecializationKind(); - if (kind == TSK_ImplicitInstantiation) - ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(RD, Loc)); - else + if (kind == TSK_ImplicitInstantiation) { + CXXRecordDecl *CanonRD = cast<CXXRecordDecl>(RD->getCanonicalDecl()); + if (UnmarkedClassesRequiringVtable.insert(CanonRD)) + ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(RD, Loc)); + } else MarkVirtualMembersReferenced(Loc, RD); } +void Sema::MaybeMarkVirtualMembersReferenced(SourceLocation Loc, + CXXRecordDecl *RD) { + if (RD->isDependentContext() || !RD->isDynamicClass()) + return; + + if (RD->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) + return; + + // Classes with a key function will be dealt with when we see the + // definition of the key function. + if (Context.getKeyFunction(RD)) + return; + + CXXRecordDecl *CanonRD = cast<CXXRecordDecl>(RD->getCanonicalDecl()); + if (UnmarkedClassesRequiringVtable.insert(CanonRD)) + ClassesWithUnmarkedVirtualMembers.push_back(std::make_pair(RD, Loc)); +} + bool Sema::ProcessPendingClassesWithUnmarkedVirtualMembers() { if (ClassesWithUnmarkedVirtualMembers.empty()) return false; @@ -6082,6 +6116,15 @@ bool Sema::ProcessPendingClassesWithUnmarkedVirtualMembers() { CXXRecordDecl *RD = ClassesWithUnmarkedVirtualMembers.back().first; SourceLocation Loc = ClassesWithUnmarkedVirtualMembers.back().second; ClassesWithUnmarkedVirtualMembers.pop_back(); + + // If an implicitly-instantiated class doesn't require a vtable, + // don't mark its virtual members as referenced. + if (RD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) { + CXXRecordDecl *CanonRD = cast<CXXRecordDecl>(RD->getCanonicalDecl()); + if (!UnmarkedClassesRequiringVtable.count(CanonRD)) + continue; + } + MarkVirtualMembersReferenced(Loc, RD); } |

