From 84973e56e3094d4b93d0f1eab9e251c239d6455c Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Sat, 21 Apr 2012 18:42:51 +0000 Subject: Fix regression in r154844. If necessary, defer computing adjusted destructor exception specifications in C++11 until after we've parsed the exception specifications for nested classes. llvm-svn: 155293 --- clang/lib/Sema/SemaDecl.cpp | 15 --------------- clang/lib/Sema/SemaDeclCXX.cpp | 39 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 17 deletions(-) (limited to 'clang/lib/Sema') diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 1550993079a..38bb852fa23 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -9784,21 +9784,6 @@ void Sema::ActOnFields(Scope* S, if (!Completed) Record->completeDefinition(); - // Now that the record is complete, do any delayed exception spec checks - // we were missing. - while (!DelayedDestructorExceptionSpecChecks.empty()) { - const CXXDestructorDecl *Dtor = - DelayedDestructorExceptionSpecChecks.back().first; - if (Dtor->getParent() != Record) - break; - - assert(!Dtor->getParent()->isDependentType() && - "Should not ever add destructors of templates into the list."); - CheckOverridingFunctionExceptionSpec(Dtor, - DelayedDestructorExceptionSpecChecks.back().second); - DelayedDestructorExceptionSpecChecks.pop_back(); - } - } else { ObjCIvarDecl **ClsFields = reinterpret_cast(RecFields.data()); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 65c8bbe7cff..b6395f5dcbf 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -7317,15 +7317,42 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, } } +/// \brief Perform any semantic analysis which needs to be delayed until all +/// pending class member declarations have been parsed. +void Sema::ActOnFinishCXXMemberDecls() { + // Now we have parsed all exception specifications, determine the implicit + // exception specifications for destructors. + for (unsigned i = 0, e = DelayedDestructorExceptionSpecs.size(); + i != e; ++i) { + CXXDestructorDecl *Dtor = DelayedDestructorExceptionSpecs[i]; + AdjustDestructorExceptionSpec(Dtor->getParent(), Dtor, true); + } + DelayedDestructorExceptionSpecs.clear(); + + // 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, - CXXDestructorDecl *destructor) { + CXXDestructorDecl *destructor, + bool WasDelayed) { // C++11 [class.dtor]p3: // A declaration of a destructor that does not have an exception- // specification is implicitly considered to have the same exception- // specification as an implicit declaration. const FunctionProtoType *dtorType = destructor->getType()-> getAs(); - if (dtorType->hasExceptionSpec()) + if (!WasDelayed && dtorType->hasExceptionSpec()) return; ImplicitExceptionSpecification exceptSpec = @@ -7342,6 +7369,14 @@ void Sema::AdjustDestructorExceptionSpec(CXXRecordDecl *classDecl, destructor->setType(ty); + // If we can't compute the exception specification for this destructor yet + // (because it depends on an exception specification which we have not parsed + // yet), make a note that we need to try again when the class is complete. + if (epi.ExceptionSpecType == EST_Delayed) { + assert(!WasDelayed && "couldn't compute destructor exception spec"); + DelayedDestructorExceptionSpecs.push_back(destructor); + } + // FIXME: If the destructor has a body that could throw, and the newly created // spec doesn't allow exceptions, we should emit a warning, because this // change in behavior can break conforming C++03 programs at runtime. -- cgit v1.2.3