Index: lib/Sema/SemaExceptionSpec.cpp =================================================================== --- lib/Sema/SemaExceptionSpec.cpp +++ lib/Sema/SemaExceptionSpec.cpp @@ -899,11 +899,28 @@ bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New, const CXXMethodDecl *Old) { - // If the new exception specification hasn't been parsed yet, skip the check. + // If the new exception spec hasn't been determined yet, skip the check. // We'll get called again once it's been parsed. - if (New->getType()->castAs()->getExceptionSpecType() == - EST_Unparsed) + switch (New->getType()->castAs()->getExceptionSpecType()) { + case EST_Unparsed: + case EST_Unevaluated: return false; + default: + ; + } + + // If the old exception spec hasn't been determined yet, remember that + // we need to perform this check when we get to the end of the outermost + // lexically-surrounding class. + switch (New->getType()->castAs()->getExceptionSpecType()) { + case EST_Unparsed: + case EST_Unevaluated: + DelayedExceptionSpecChecks.push_back(std::make_pair(New, Old)); + return false; + default: + ; + } + if (getLangOpts().CPlusPlus11 && isa(New)) { // Don't check uninstantiated template destructors at all. We can only // synthesize correct specs after the template is instantiated. @@ -916,17 +933,11 @@ return false; } } - // 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()->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; + return CheckExceptionSpecSubset(PDiag(DiagID), PDiag(diag::err_deep_exception_specs_differ), PDiag(diag::note_overridden_virtual_function), Index: test/Modules/Inputs/lax-base-except/a.h =================================================================== --- /dev/null +++ test/Modules/Inputs/lax-base-except/a.h @@ -0,0 +1,19 @@ +class A { + public: + virtual ~A() = default; +}; + +class B { + public: + virtual ~B() { + c.func(); + } + + struct C{ + void func() {} + friend B::~B(); + }; + + C c; +}; + Index: test/Modules/Inputs/lax-base-except/module.modulemap =================================================================== --- /dev/null +++ test/Modules/Inputs/lax-base-except/module.modulemap @@ -0,0 +1,3 @@ +module a { + header "a.h" +} Index: test/Modules/lax-base-except.cpp =================================================================== --- /dev/null +++ test/Modules/lax-base-except.cpp @@ -0,0 +1,10 @@ +// RUN: rm -rf %t +// RUN: %clang -c -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs/lax-base-except %s -o %t2.o +// expected-no-diagnostics + +#include "a.h" + +class D : public A, public B { + public: + virtual ~D() override = default; +};