Delay checking overrides for exception specifications if the overridden
specification has not yet been parsed.
llvm-svn: 222603
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 61ee770..b9aaf16 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -680,7 +680,7 @@
// All delayed member exception specs should be checked or we end up accepting
// incompatible declarations.
assert(DelayedDefaultedMemberExceptionSpecs.empty());
- assert(DelayedDestructorExceptionSpecChecks.empty());
+ assert(DelayedExceptionSpecChecks.empty());
// Remove file scoped decls that turned out to be used.
UnusedFileScopedDecls.erase(
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 90ca97b..ec62534 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5340,27 +5340,21 @@
}
void Sema::CheckDelayedMemberExceptionSpecs() {
- SmallVector<std::pair<const CXXDestructorDecl *, const CXXDestructorDecl *>,
- 2> Checks;
- SmallVector<std::pair<CXXMethodDecl *, const FunctionProtoType *>, 2> Specs;
+ decltype(DelayedExceptionSpecChecks) Checks;
+ decltype(DelayedDefaultedMemberExceptionSpecs) Specs;
- std::swap(Checks, DelayedDestructorExceptionSpecChecks);
+ std::swap(Checks, DelayedExceptionSpecChecks);
std::swap(Specs, DelayedDefaultedMemberExceptionSpecs);
// Perform any deferred checking of exception specifications for virtual
// destructors.
- for (unsigned i = 0, e = Checks.size(); i != e; ++i) {
- const CXXDestructorDecl *Dtor = Checks[i].first;
- assert(!Dtor->getParent()->isDependentType() &&
- "Should not ever add destructors of templates into the list.");
- CheckOverridingFunctionExceptionSpec(Dtor, Checks[i].second);
- }
+ for (auto &Check : Checks)
+ CheckOverridingFunctionExceptionSpec(Check.first, Check.second);
// Check that any explicitly-defaulted methods have exception specifications
// compatible with their implicit exception specifications.
- for (unsigned I = 0, N = Specs.size(); I != N; ++I)
- CheckExplicitlyDefaultedMemberExceptionSpec(Specs[I].first,
- Specs[I].second);
+ for (auto &Spec : Specs)
+ CheckExplicitlyDefaultedMemberExceptionSpec(Spec.first, Spec.second);
}
namespace {
@@ -9298,7 +9292,7 @@
if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(CurContext)) {
if (Record->isInvalidDecl()) {
DelayedDefaultedMemberExceptionSpecs.clear();
- DelayedDestructorExceptionSpecChecks.clear();
+ DelayedExceptionSpecChecks.clear();
return;
}
}
diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp
index 7175c01..2387325 100644
--- a/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -801,6 +801,11 @@
bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
const CXXMethodDecl *Old) {
+ // If the new exception specification hasn't been parsed yet, skip the check.
+ // We'll get called again once it's been parsed.
+ if (New->getType()->castAs<FunctionProtoType>()->getExceptionSpecType() ==
+ EST_Unparsed)
+ return false;
if (getLangOpts().CPlusPlus11 && isa<CXXDestructorDecl>(New)) {
// Don't check uninstantiated template destructors at all. We can only
// synthesize correct specs after the template is instantiated.
@@ -809,16 +814,18 @@
if (New->getParent()->isBeingDefined()) {
// The destructor might be updated once the definition is finished. So
// remember it and check later.
- DelayedDestructorExceptionSpecChecks.push_back(std::make_pair(
- cast<CXXDestructorDecl>(New), cast<CXXDestructorDecl>(Old)));
+ DelayedExceptionSpecChecks.push_back(std::make_pair(New, Old));
return false;
}
}
- // If the exception specification hasn't been parsed yet, skip the check.
- // We'll get called again once it's been parsed.
- if (New->getType()->castAs<FunctionProtoType>()->getExceptionSpecType() ==
- EST_Unparsed)
+ // If the old exception specification hasn't been parsed yet, remember that
+ // we need to perform this check when we get to the end of the outermost
+ // lexically-surrounding class.
+ if (Old->getType()->castAs<FunctionProtoType>()->getExceptionSpecType() ==
+ EST_Unparsed) {
+ DelayedExceptionSpecChecks.push_back(std::make_pair(New, Old));
return false;
+ }
unsigned DiagID = diag::err_override_exception_spec;
if (getLangOpts().MicrosoftExt)
DiagID = diag::ext_override_exception_spec;