diff options
author | Alp Toker <alp@nuanti.com> | 2013-10-18 05:54:19 +0000 |
---|---|---|
committer | Alp Toker <alp@nuanti.com> | 2013-10-18 05:54:19 +0000 |
commit | ae3a944a6e35dc94f553fb11b749f8e042a6d721 (patch) | |
tree | ff95cb0fe226b8325c070f8591335afe11d9cda0 /clang/lib/Sema/SemaDeclCXX.cpp | |
parent | b01092f0e37a31f89968f56dafc8dfcf4b4c2119 (diff) | |
download | bcm5719-llvm-ae3a944a6e35dc94f553fb11b749f8e042a6d721.tar.gz bcm5719-llvm-ae3a944a6e35dc94f553fb11b749f8e042a6d721.zip |
Fix missed exception spec checks and crashes
Delayed exception specification checking for defaulted members and virtual
destructors are both susceptible to mutation during iteration so we need to
swap and process the worklists.
This resolves both accepts-invalid and rejects-valid issues and moreover fixes
potential invalid memory access as the contents of the vectors change during
iteration and recursive template instantiation.
Checking can be further delayed where parent classes aren't yet fully defined.
This patch adds two assertions at end of TU to ensure no specs are left
unchecked as was happenning before the fix, plus a test case from Marshall Clow
for the defaulted member crash extracted from the libcxx headers.
Reviewed by Richard Smith.
llvm-svn: 192947
Diffstat (limited to 'clang/lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 47 |
1 files changed, 24 insertions, 23 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 81283e1f782..ed5724b88fb 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -4873,14 +4873,28 @@ void Sema::CheckExplicitlyDefaultedMemberExceptionSpec( SpecifiedType, MD->getLocation()); } -void Sema::CheckDelayedExplicitlyDefaultedMemberExceptionSpecs() { - for (unsigned I = 0, N = DelayedDefaultedMemberExceptionSpecs.size(); - I != N; ++I) - CheckExplicitlyDefaultedMemberExceptionSpec( - DelayedDefaultedMemberExceptionSpecs[I].first, - DelayedDefaultedMemberExceptionSpecs[I].second); +void Sema::CheckDelayedMemberExceptionSpecs() { + SmallVector<std::pair<const CXXDestructorDecl *, const CXXDestructorDecl *>, + 2> Checks; + SmallVector<std::pair<CXXMethodDecl *, const FunctionProtoType *>, 2> Specs; - DelayedDefaultedMemberExceptionSpecs.clear(); + std::swap(Checks, DelayedDestructorExceptionSpecChecks); + std::swap(Specs, DelayedDefaultedMemberExceptionSpecs); + + // Perform any deferred checking of exception specifications for virtual + // destructors. + for (unsigned i = 0, e = Checks.size(); i != e; ++i) { + const CXXDestructorDecl *Dtor = Checks[i].first; + assert(!Dtor->getParent()->isDependentType() && + "Should not ever add destructors of templates into the list."); + CheckOverridingFunctionExceptionSpec(Dtor, Checks[i].second); + } + + // Check that any explicitly-defaulted methods have exception specifications + // compatible with their implicit exception specifications. + for (unsigned I = 0, N = Specs.size(); I != N; ++I) + CheckExplicitlyDefaultedMemberExceptionSpec(Specs[I].first, + Specs[I].second); } namespace { @@ -8191,9 +8205,8 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, } void Sema::ActOnFinishDelayedMemberInitializers(Decl *D) { - // Check that any explicitly-defaulted methods have exception specifications - // compatible with their implicit exception specifications. - CheckDelayedExplicitlyDefaultedMemberExceptionSpecs(); + // Perform any delayed checks on exception specifications. + CheckDelayedMemberExceptionSpecs(); // Once all the member initializers are processed, perform checks to see if // any unintialized use is happeneing. @@ -8716,23 +8729,11 @@ void Sema::ActOnFinishCXXMemberDecls() { // If the context is an invalid C++ class, just suppress these checks. if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(CurContext)) { if (Record->isInvalidDecl()) { + DelayedDefaultedMemberExceptionSpecs.clear(); DelayedDestructorExceptionSpecChecks.clear(); return; } } - - // Perform any deferred checking of exception specifications for virtual - // destructors. - for (unsigned i = 0, e = DelayedDestructorExceptionSpecChecks.size(); - i != e; ++i) { - const CXXDestructorDecl *Dtor = - DelayedDestructorExceptionSpecChecks[i].first; - assert(!Dtor->getParent()->isDependentType() && - "Should not ever add destructors of templates into the list."); - CheckOverridingFunctionExceptionSpec(Dtor, - DelayedDestructorExceptionSpecChecks[i].second); - } - DelayedDestructorExceptionSpecChecks.clear(); } void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl, |