summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaExceptionSpec.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2016-11-30 00:13:55 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2016-11-30 00:13:55 +0000
commit13b40bcc0322e27eaa61b459dec8f898ea1f069d (patch)
tree51a5ed63dc1f7c26db52b4132d2246b35693d45c /clang/lib/Sema/SemaExceptionSpec.cpp
parentf9b191f1356d29fa44f631a1b8454a80d28763a6 (diff)
downloadbcm5719-llvm-13b40bcc0322e27eaa61b459dec8f898ea1f069d.tar.gz
bcm5719-llvm-13b40bcc0322e27eaa61b459dec8f898ea1f069d.zip
[c++1z] Improve support for -fno-exceptions: we can't just ignore exception
specifications in this mode in C++17, since they're part of the function type, so check and diagnose them like we would if exceptions were enabled. Better ideas welcome. llvm-svn: 288220
Diffstat (limited to 'clang/lib/Sema/SemaExceptionSpec.cpp')
-rw-r--r--clang/lib/Sema/SemaExceptionSpec.cpp87
1 files changed, 55 insertions, 32 deletions
diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp
index ae728422abc..e95482679b7 100644
--- a/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -207,6 +207,14 @@ Sema::UpdateExceptionSpec(FunctionDecl *FD,
Context.adjustExceptionSpec(cast<FunctionDecl>(Redecl), ESI);
}
+static bool CheckEquivalentExceptionSpecImpl(
+ Sema &S, const PartialDiagnostic &DiagID, const PartialDiagnostic &NoteID,
+ const FunctionProtoType *Old, SourceLocation OldLoc,
+ const FunctionProtoType *New, SourceLocation NewLoc,
+ bool *MissingExceptionSpecification = nullptr,
+ bool *MissingEmptyExceptionSpecification = nullptr,
+ bool AllowNoexceptAllMatchWithNoSpec = false, bool IsOperatorNew = false);
+
/// Determine whether a function has an implicitly-generated exception
/// specification.
static bool hasImplicitExceptionSpec(FunctionDecl *Decl) {
@@ -229,6 +237,12 @@ static bool hasImplicitExceptionSpec(FunctionDecl *Decl) {
}
bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
+ // Just completely ignore this under -fno-exceptions prior to C++1z.
+ // In C++1z onwards, the exception specification is part of the type and
+ // we will diagnose mismatches anyway, so it's better to check for them here.
+ if (!getLangOpts().CXXExceptions && !getLangOpts().CPlusPlus1z)
+ return false;
+
OverloadedOperatorKind OO = New->getDeclName().getCXXOverloadedOperator();
bool IsOperatorNew = OO == OO_New || OO == OO_Array_New;
bool MissingExceptionSpecification = false;
@@ -243,8 +257,8 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
// Check the types as written: they must match before any exception
// specification adjustment is applied.
- if (!CheckEquivalentExceptionSpec(
- PDiag(DiagID), PDiag(diag::note_previous_declaration),
+ if (!CheckEquivalentExceptionSpecImpl(
+ *this, PDiag(DiagID), PDiag(diag::note_previous_declaration),
Old->getType()->getAs<FunctionProtoType>(), Old->getLocation(),
New->getType()->getAs<FunctionProtoType>(), New->getLocation(),
&MissingExceptionSpecification, &MissingEmptyExceptionSpecification,
@@ -395,11 +409,15 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
bool Sema::CheckEquivalentExceptionSpec(
const FunctionProtoType *Old, SourceLocation OldLoc,
const FunctionProtoType *New, SourceLocation NewLoc) {
+ if (!getLangOpts().CXXExceptions)
+ return false;
+
unsigned DiagID = diag::err_mismatched_exception_spec;
if (getLangOpts().MicrosoftExt)
DiagID = diag::ext_mismatched_exception_spec;
- bool Result = CheckEquivalentExceptionSpec(PDiag(DiagID),
- PDiag(diag::note_previous_declaration), Old, OldLoc, New, NewLoc);
+ bool Result = CheckEquivalentExceptionSpecImpl(
+ *this, PDiag(DiagID), PDiag(diag::note_previous_declaration),
+ Old, OldLoc, New, NewLoc);
// In Microsoft mode, mismatching exception specifications just cause a warning.
if (getLangOpts().MicrosoftExt)
@@ -413,30 +431,23 @@ bool Sema::CheckEquivalentExceptionSpec(
/// \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,
- SourceLocation OldLoc,
- const FunctionProtoType *New,
- SourceLocation NewLoc,
- bool *MissingExceptionSpecification,
- bool*MissingEmptyExceptionSpecification,
- bool AllowNoexceptAllMatchWithNoSpec,
- bool IsOperatorNew) {
- // Just completely ignore this under -fno-exceptions.
- if (!getLangOpts().CXXExceptions)
- return false;
-
+static bool CheckEquivalentExceptionSpecImpl(
+ Sema &S, const PartialDiagnostic &DiagID, const PartialDiagnostic &NoteID,
+ const FunctionProtoType *Old, SourceLocation OldLoc,
+ const FunctionProtoType *New, SourceLocation NewLoc,
+ bool *MissingExceptionSpecification,
+ bool *MissingEmptyExceptionSpecification,
+ bool AllowNoexceptAllMatchWithNoSpec, bool IsOperatorNew) {
if (MissingExceptionSpecification)
*MissingExceptionSpecification = false;
if (MissingEmptyExceptionSpecification)
*MissingEmptyExceptionSpecification = false;
- Old = ResolveExceptionSpec(NewLoc, Old);
+ Old = S.ResolveExceptionSpec(NewLoc, Old);
if (!Old)
return false;
- New = ResolveExceptionSpec(NewLoc, New);
+ New = S.ResolveExceptionSpec(NewLoc, New);
if (!New)
return false;
@@ -470,8 +481,8 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
if (OldEST == EST_None && NewEST == EST_None)
return false;
- FunctionProtoType::NoexceptResult OldNR = Old->getNoexceptSpec(Context);
- FunctionProtoType::NoexceptResult NewNR = New->getNoexceptSpec(Context);
+ FunctionProtoType::NoexceptResult OldNR = Old->getNoexceptSpec(S.Context);
+ FunctionProtoType::NoexceptResult NewNR = New->getNoexceptSpec(S.Context);
if (OldNR == FunctionProtoType::NR_BadNoexcept ||
NewNR == FunctionProtoType::NR_BadNoexcept)
return false;
@@ -486,9 +497,9 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
if (OldNR != NewNR &&
OldNR != FunctionProtoType::NR_NoNoexcept &&
NewNR != FunctionProtoType::NR_NoNoexcept) {
- Diag(NewLoc, DiagID);
+ S.Diag(NewLoc, DiagID);
if (NoteID.getDiagID() != 0 && OldLoc.isValid())
- Diag(OldLoc, NoteID);
+ S.Diag(OldLoc, NoteID);
return true;
}
@@ -526,7 +537,7 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
// As a special compatibility feature, under C++0x we accept no spec and
// throw(std::bad_alloc) as equivalent for operator new and operator new[].
// This is because the implicit declaration changed, but old code would break.
- if (getLangOpts().CPlusPlus11 && IsOperatorNew) {
+ if (S.getLangOpts().CPlusPlus11 && IsOperatorNew) {
const FunctionProtoType *WithExceptions = nullptr;
if (OldEST == EST_None && NewEST == EST_Dynamic)
WithExceptions = New;
@@ -567,9 +578,9 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
return true;
}
- Diag(NewLoc, DiagID);
+ S.Diag(NewLoc, DiagID);
if (NoteID.getDiagID() != 0 && OldLoc.isValid())
- Diag(OldLoc, NoteID);
+ S.Diag(OldLoc, NoteID);
return true;
}
@@ -581,11 +592,11 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
// to the second.
llvm::SmallPtrSet<CanQualType, 8> OldTypes, NewTypes;
for (const auto &I : Old->exceptions())
- OldTypes.insert(Context.getCanonicalType(I).getUnqualifiedType());
+ OldTypes.insert(S.Context.getCanonicalType(I).getUnqualifiedType());
for (const auto &I : New->exceptions()) {
- CanQualType TypePtr = Context.getCanonicalType(I).getUnqualifiedType();
- if(OldTypes.count(TypePtr))
+ CanQualType TypePtr = S.Context.getCanonicalType(I).getUnqualifiedType();
+ if (OldTypes.count(TypePtr))
NewTypes.insert(TypePtr);
else
Success = false;
@@ -596,12 +607,24 @@ bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
if (Success) {
return false;
}
- Diag(NewLoc, DiagID);
+ S.Diag(NewLoc, DiagID);
if (NoteID.getDiagID() != 0 && OldLoc.isValid())
- Diag(OldLoc, NoteID);
+ S.Diag(OldLoc, NoteID);
return true;
}
+bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID,
+ const PartialDiagnostic &NoteID,
+ const FunctionProtoType *Old,
+ SourceLocation OldLoc,
+ const FunctionProtoType *New,
+ SourceLocation NewLoc) {
+ if (!getLangOpts().CXXExceptions)
+ return false;
+ return CheckEquivalentExceptionSpecImpl(*this, DiagID, NoteID, Old, OldLoc,
+ New, NewLoc);
+}
+
/// CheckExceptionSpecSubset - Check whether the second function type's
/// exception specification is a subset (or equivalent) of the first function
/// type. This is used by override and pointer assignment checks.
OpenPOWER on IntegriCloud