[cfe-commits] r155293 - in /cfe/trunk: include/clang/Sema/Sema.h lib/Parse/ParseDeclCXX.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp test/SemaCXX/implicit-exception-spec.cpp
Richard Smith
richard-llvm at metafoo.co.uk
Sat Apr 21 11:42:51 PDT 2012
Author: rsmith
Date: Sat Apr 21 13:42:51 2012
New Revision: 155293
URL: http://llvm.org/viewvc/llvm-project?rev=155293&view=rev
Log:
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.
Modified:
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Parse/ParseDeclCXX.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/test/SemaCXX/implicit-exception-spec.cpp
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=155293&r1=155292&r2=155293&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Sat Apr 21 13:42:51 2012
@@ -331,6 +331,11 @@
/// cycle detection at the end of the TU.
DelegatingCtorDeclsType DelegatingCtorDecls;
+ /// \brief All the destructors seen during a class definition that had their
+ /// exception spec computation delayed because it depended on an unparsed
+ /// exception spec.
+ SmallVector<CXXDestructorDecl*, 2> DelayedDestructorExceptionSpecs;
+
/// \brief All the overriding destructors seen during a class definition
/// (there could be multiple due to nested classes) that had their exception
/// spec checks delayed, plus the overridden destructor.
@@ -3203,7 +3208,8 @@
/// C++11 says that user-defined destructors with no exception spec get one
/// that looks as if the destructor was implicitly declared.
void AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl,
- CXXDestructorDecl *Destructor);
+ CXXDestructorDecl *Destructor,
+ bool WasDelayed = false);
/// \brief Declare all inherited constructors for the given class.
///
@@ -4048,6 +4054,7 @@
SourceLocation LBrac,
SourceLocation RBrac,
AttributeList *AttrList);
+ void ActOnFinishCXXMemberDecls();
void ActOnReenterTemplateScope(Scope *S, Decl *Template);
void ActOnReenterDeclaratorTemplateScope(Scope *S, DeclaratorDecl *D);
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=155293&r1=155292&r2=155293&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Sat Apr 21 13:42:51 2012
@@ -2369,6 +2369,10 @@
SourceLocation SavedPrevTokLocation = PrevTokLocation;
ParseLexedAttributes(getCurrentClass());
ParseLexedMethodDeclarations(getCurrentClass());
+
+ // We've finished with all pending member declarations.
+ Actions.ActOnFinishCXXMemberDecls();
+
ParseLexedMemberInitializers(getCurrentClass());
ParseLexedMethodDefs(getCurrentClass());
PrevTokLocation = SavedPrevTokLocation;
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=155293&r1=155292&r2=155293&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sat Apr 21 13:42:51 2012
@@ -9784,21 +9784,6 @@
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<ObjCIvarDecl**>(RecFields.data());
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=155293&r1=155292&r2=155293&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sat Apr 21 13:42:51 2012
@@ -7317,15 +7317,42 @@
}
}
+/// \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<FunctionProtoType>();
- if (dtorType->hasExceptionSpec())
+ if (!WasDelayed && dtorType->hasExceptionSpec())
return;
ImplicitExceptionSpecification exceptSpec =
@@ -7342,6 +7369,14 @@
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.
Modified: cfe/trunk/test/SemaCXX/implicit-exception-spec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/implicit-exception-spec.cpp?rev=155293&r1=155292&r2=155293&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/implicit-exception-spec.cpp (original)
+++ cfe/trunk/test/SemaCXX/implicit-exception-spec.cpp Sat Apr 21 13:42:51 2012
@@ -54,3 +54,33 @@
} t; // expected-note {{has no default constructor}}
};
}
+
+namespace ImplicitDtorExceptionSpec {
+ struct A {
+ virtual ~A();
+
+ struct Inner {
+ ~Inner() throw();
+ };
+ Inner inner;
+ };
+
+ struct B {
+ virtual ~B() {} // expected-note {{here}}
+ };
+
+ struct C : B {
+ virtual ~C() {}
+ A a;
+ };
+
+ struct D : B {
+ ~D(); // expected-error {{more lax than base}}
+ struct E {
+ ~E();
+ struct F {
+ ~F() throw(A);
+ } f;
+ } e;
+ };
+}
More information about the cfe-commits
mailing list