Index: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -4418,19 +4418,34 @@ // resolution point. if (isa(ND)) continue; - const CXXConstructorDecl *Constructor = cast(ND); - if (Constructor->isCopyConstructor(FoundTQs)) { - FoundConstructor = true; - const FunctionProtoType *CPT - = Constructor->getType()->getAs(); - CPT = Self.ResolveExceptionSpec(KeyLoc, CPT); - if (!CPT) - return false; - // TODO: check whether evaluating default arguments can throw. - // For now, we'll be conservative and assume that they can throw. - if (!CPT->isNothrow(C) || CPT->getNumParams() > 1) - return false; - } + + auto const HandleConstructor = + [&](const CXXConstructorDecl *Constructor) { + if (Constructor->isCopyConstructor(FoundTQs)) { + FoundConstructor = true; + const FunctionProtoType *CPT = + Constructor->getType()->getAs(); + CPT = Self.ResolveExceptionSpec(KeyLoc, CPT); + if (!CPT) + return false; + // TODO: check whether evaluating default arguments can throw. + // For now, we'll be conservative and assume that they can + // throw. + if (!CPT->isNothrow(C) || CPT->getNumParams() > 1) + return false; + } + return true; + }; + + // handle inherited constructors + if (isa(ND)) { + const auto *UD = cast(ND); + for (const auto &C : UD->shadows()) + if (!HandleConstructor( + cast(C->getTargetDecl()))) + return false; + } else if (!HandleConstructor(cast(ND))) + return false; } return FoundConstructor; Index: test/CXX/special/class.copy/p34-cxx11.cpp =================================================================== --- /dev/null +++ test/CXX/special/class.copy/p34-cxx11.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s +// expected-no-diagnostics + +struct A { + A(A const &) noexcept(false) {} + A(A&&) noexcept(true) {} +}; + +struct B : public A { + using A::A; +}; + +static_assert(!__has_nothrow_copy(B), "has_nothrow_copy fails");