summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2014-11-22 03:09:05 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2014-11-22 03:09:05 +0000
commit88f45490a0beeebd69856b6099a23ce41b909fdd (patch)
tree124920b4304d960a0df979b9cc7963ed27e3aaf5 /clang/lib/Sema
parent54166af611bdc90ca2ed2974316218712fcc107d (diff)
downloadbcm5719-llvm-88f45490a0beeebd69856b6099a23ce41b909fdd.tar.gz
bcm5719-llvm-88f45490a0beeebd69856b6099a23ce41b909fdd.zip
Delay checking overrides for exception specifications if the overridden
specification has not yet been parsed. llvm-svn: 222603
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/Sema.cpp2
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp22
-rw-r--r--clang/lib/Sema/SemaExceptionSpec.cpp19
3 files changed, 22 insertions, 21 deletions
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 61ee7702c07..b9aaf1616d6 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -680,7 +680,7 @@ void Sema::ActOnEndOfTranslationUnit() {
// 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 90ca97b5ca0..ec625346e82 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -5340,27 +5340,21 @@ void Sema::CheckExplicitlyDefaultedMemberExceptionSpec(
}
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 @@ void Sema::ActOnFinishCXXMemberDecls() {
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 7175c016734..2387325be43 100644
--- a/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -801,6 +801,11 @@ bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType) {
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 @@ bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
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;
OpenPOWER on IntegriCloud