summaryrefslogtreecommitdiff
path: root/lib/Sema/SemaExceptionSpec.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-10-20 08:26:51 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-10-20 08:26:51 +0000
commit444d384a969ce05ae534bf8be3174e308dc8c58b (patch)
treefe1544626770716ea91fbde7c6e1c2259ffe4ae6 /lib/Sema/SemaExceptionSpec.cpp
parented1d5d8ee17f639563dc0397bd9af1b482f17295 (diff)
downloadclang-444d384a969ce05ae534bf8be3174e308dc8c58b.tar.gz
Rework implementation of DR1492: Apply the resolution to operator delete too,
since it also has an implicit exception specification. Downgrade the error to an extwarn, since at least for operator delete, system headers like to declare it as 'noexcept' whereas the implicit definition does not have an explicit exception specification. Move the exception specification for user-declared 'operator delete' functions from the type-as-written into the type, to reflect reality and to allow us to detect whether there was an implicit exception spec or not. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@166372 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExceptionSpec.cpp')
-rw-r--r--lib/Sema/SemaExceptionSpec.cpp55
1 files changed, 37 insertions, 18 deletions
diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp
index e35badc9f3..e1f4888d63 100644
--- a/lib/Sema/SemaExceptionSpec.cpp
+++ b/lib/Sema/SemaExceptionSpec.cpp
@@ -120,21 +120,22 @@ Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT) {
return SourceDecl->getType()->castAs<FunctionProtoType>();
}
-/// Get the type that a function had prior to adjustment of the exception
+/// Determine whether a function has an implicitly-generated exception
/// specification.
-static const FunctionProtoType *getUnadjustedFunctionType(FunctionDecl *Decl) {
- if (isa<CXXDestructorDecl>(Decl) && Decl->getTypeSourceInfo()) {
- const FunctionProtoType *Ty =
- Decl->getTypeSourceInfo()->getType()->getAs<FunctionProtoType>();
- if (!Ty->hasExceptionSpec())
- // The type will be adjusted. Use the EST_None exception specification
- // from the type as written.
- return Ty;
- }
+static bool hasImplicitExceptionSpec(FunctionDecl *Decl) {
+ if (!isa<CXXDestructorDecl>(Decl) &&
+ Decl->getDeclName().getCXXOverloadedOperator() != OO_Delete &&
+ Decl->getDeclName().getCXXOverloadedOperator() != OO_Array_Delete)
+ return false;
+
+ // If the user didn't declare the function, its exception specification must
+ // be implicit.
+ if (!Decl->getTypeSourceInfo())
+ return true;
- // Use whatever type the function now has. The TypeSourceInfo does not contain
- // an instantiated exception specification for a function template,
- return Decl->getType()->getAs<FunctionProtoType>();
+ const FunctionProtoType *Ty =
+ Decl->getTypeSourceInfo()->getType()->getAs<FunctionProtoType>();
+ return !Ty->hasExceptionSpec();
}
bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
@@ -150,18 +151,31 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
// specification adjustment is applied.
if (!CheckEquivalentExceptionSpec(
PDiag(DiagID), PDiag(diag::note_previous_declaration),
- getUnadjustedFunctionType(Old), Old->getLocation(),
- getUnadjustedFunctionType(New), New->getLocation(),
+ Old->getType()->getAs<FunctionProtoType>(), Old->getLocation(),
+ New->getType()->getAs<FunctionProtoType>(), New->getLocation(),
&MissingExceptionSpecification, &MissingEmptyExceptionSpecification,
- /*AllowNoexceptAllMatchWithNoSpec=*/true, IsOperatorNew))
+ /*AllowNoexceptAllMatchWithNoSpec=*/true, IsOperatorNew)) {
+ // C++11 [except.spec]p4 [DR1492]:
+ // If a declaration of a function has an implicit
+ // exception-specification, other declarations of the function shall
+ // not specify an exception-specification.
+ if (getLangOpts().CPlusPlus0x &&
+ hasImplicitExceptionSpec(Old) != hasImplicitExceptionSpec(New)) {
+ Diag(New->getLocation(), diag::ext_implicit_exception_spec_mismatch)
+ << hasImplicitExceptionSpec(Old);
+ if (!Old->getLocation().isInvalid())
+ Diag(Old->getLocation(), diag::note_previous_declaration);
+ }
return false;
+ }
// The failure was something other than an empty exception
// specification; return an error.
if (!MissingExceptionSpecification && !MissingEmptyExceptionSpecification)
return true;
- const FunctionProtoType *NewProto = getUnadjustedFunctionType(New);
+ const FunctionProtoType *NewProto =
+ New->getType()->getAs<FunctionProtoType>();
// The new function declaration is only missing an empty exception
// specification "throw()". If the throw() specification came from a
@@ -186,7 +200,8 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
}
if (MissingExceptionSpecification && NewProto) {
- const FunctionProtoType *OldProto = getUnadjustedFunctionType(Old);
+ const FunctionProtoType *OldProto =
+ Old->getType()->getAs<FunctionProtoType>();
FunctionProtoType::ExtProtoInfo EPI = NewProto->getExtProtoInfo();
EPI.ExceptionSpecType = OldProto->getExceptionSpecType();
@@ -310,6 +325,10 @@ bool Sema::CheckEquivalentExceptionSpec(
/// CheckEquivalentExceptionSpec - Check if the two types have compatible
/// exception specifications. See C++ [except.spec]p3.
+///
+/// \return \c false if the exception specifications match, \c true if there is
+/// a problem. If \c true is returned, either a diagnostic has already been
+/// produced or \c *MissingExceptionSpecification is set to \c true.
bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
const PartialDiagnostic & NoteID,
const FunctionProtoType *Old,