diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-07-27 04:22:15 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-07-27 04:22:15 +0000 |
commit | b9d0b76e42fd2d4cdfd135220302458d03ad09fe (patch) | |
tree | 1894c96cc5299fa61519ae10a53004eb6b8f7f66 /lib/Sema/SemaExceptionSpec.cpp | |
parent | 69a0e5021c5c49a34aa25cd89b1e613a52097e65 (diff) |
Final piece of core issue 1330: delay computing the exception specification of
a defaulted special member function until the exception specification is needed
(using the same criteria used for the delayed instantiation of exception
specifications for function temploids).
EST_Delayed is now EST_Unevaluated (using 1330's terminology), and, like
EST_Uninstantiated, carries a pointer to the FunctionDecl which will be used to
resolve the exception specification.
This is enabled for all C++ modes: it's a little faster in the case where the
exception specification isn't used, allows our C++11-in-C++98 extensions to
work, and is still correct for C++98, since in that mode the computation of the
exception specification can't fail.
The diagnostics here aren't great (in particular, we should include implicit
evaluation of exception specifications for defaulted special members in the
template instantiation backtraces), but they're not much worse than before.
Our approach to the problem of cycles between in-class initializers and the
exception specification for a defaulted default constructor is modified a
little by this change -- we now reject any odr-use of a defaulted default
constructor if that constructor uses an in-class initializer and the use is in
an in-class initialzer which is declared lexically earlier. This is a closer
approximation to the current draft solution in core issue 1351, but isn't an
exact match (but the current draft wording isn't reasonable, so that's to be
expected).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160847 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExceptionSpec.cpp')
-rw-r--r-- | lib/Sema/SemaExceptionSpec.cpp | 31 |
1 files changed, 12 insertions, 19 deletions
diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp index f88ead56f4..63bfa9dc2d 100644 --- a/lib/Sema/SemaExceptionSpec.cpp +++ b/lib/Sema/SemaExceptionSpec.cpp @@ -100,20 +100,22 @@ bool Sema::CheckDistantExceptionSpec(QualType T) { const FunctionProtoType * Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT) { - // FIXME: If FD is a special member, we should delay computing its exception - // specification until this point. - if (FPT->getExceptionSpecType() != EST_Uninstantiated) + if (!isUnresolvedExceptionSpec(FPT->getExceptionSpecType())) return FPT; FunctionDecl *SourceDecl = FPT->getExceptionSpecDecl(); const FunctionProtoType *SourceFPT = SourceDecl->getType()->castAs<FunctionProtoType>(); - if (SourceFPT->getExceptionSpecType() != EST_Uninstantiated) + // If the exception specification has already been resolved, just return it. + if (!isUnresolvedExceptionSpec(SourceFPT->getExceptionSpecType())) return SourceFPT; - // Instantiate the exception specification now. - InstantiateExceptionSpec(Loc, SourceDecl); + // Compute or instantiate the exception specification now. + if (FPT->getExceptionSpecType() == EST_Unevaluated) + EvaluateImplicitExceptionSpec(Loc, cast<CXXMethodDecl>(SourceDecl)); + else + InstantiateExceptionSpec(Loc, SourceDecl); return SourceDecl->getType()->castAs<FunctionProtoType>(); } @@ -346,8 +348,8 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID, ExceptionSpecificationType OldEST = Old->getExceptionSpecType(); ExceptionSpecificationType NewEST = New->getExceptionSpecType(); - assert(OldEST != EST_Delayed && NewEST != EST_Delayed && - OldEST != EST_Uninstantiated && NewEST != EST_Uninstantiated && + assert(!isUnresolvedExceptionSpec(OldEST) && + !isUnresolvedExceptionSpec(NewEST) && "Shouldn't see unknown exception specifications here"); // Shortcut the case where both have no spec. @@ -544,8 +546,8 @@ bool Sema::CheckExceptionSpecSubset( ExceptionSpecificationType SubEST = Subset->getExceptionSpecType(); - assert(SuperEST != EST_Delayed && SubEST != EST_Delayed && - SuperEST != EST_Uninstantiated && SubEST != EST_Uninstantiated && + assert(!isUnresolvedExceptionSpec(SuperEST) && + !isUnresolvedExceptionSpec(SubEST) && "Shouldn't see unknown exception specifications here"); // It does not. If the subset contains everything, we've failed. @@ -808,15 +810,6 @@ static CanThrowResult canCalleeThrow(Sema &S, const Expr *E, if (!FT) return CT_Can; - if (FT->getExceptionSpecType() == EST_Delayed) { - // FIXME: Try to resolve a delayed exception spec in ResolveExceptionSpec. - assert(isa<CXXConstructorDecl>(D) && - "only constructor exception specs can be unknown"); - S.Diag(E->getLocStart(), diag::err_exception_spec_unknown) - << E->getSourceRange(); - return CT_Can; - } - return FT->isNothrow(S.Context) ? CT_Cannot : CT_Can; } |