Index: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td @@ -1407,6 +1407,10 @@ "argument to noexcept specifier must be a constant expression">; def err_exception_spec_not_parsed : Error< "exception specification is not available until end of class definition">; +def warn_nothrow_attr_disagrees_with_exception_specification + : ExtWarn<"attribute 'nothrow' ignored due to conflicting exception " + "specification">, + InGroup; // C++ access checking def err_class_redeclared_with_different_access : Error< Index: cfe/trunk/lib/Sema/SemaDeclAttr.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaDeclAttr.cpp +++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp @@ -1985,6 +1985,25 @@ Attrs.getRange(), S.Context, Attrs.getAttributeSpellingListIndex())); } +static void handleNoThrowAttr(Sema &S, Decl *D, const AttributeList &Attrs) { + assert(isa(D) && "attribute nothrow only valid on functions"); + + auto *FD = cast(D); + const auto *FPT = FD->getType()->getAs(); + + if (FPT && FPT->hasExceptionSpec() && + FPT->getExceptionSpecType() != EST_BasicNoexcept) { + S.Diag(Attrs.getLoc(), + diag::warn_nothrow_attr_disagrees_with_exception_specification); + S.Diag(FD->getExceptionSpecSourceRange().getBegin(), + diag::note_previous_decl) + << "exception specification"; + } + + D->addAttr(::new (S.Context) NoThrowAttr( + Attrs.getRange(), S.Context, Attrs.getAttributeSpellingListIndex())); +} + static void handleNoCallerSavedRegsAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (S.CheckNoCallerSavedRegsAttr(Attr)) @@ -6211,7 +6230,7 @@ handleNoReturnAttr(S, D, Attr); break; case AttributeList::AT_NoThrow: - handleSimpleAttribute(S, D, Attr); + handleNoThrowAttr(S, D, Attr); break; case AttributeList::AT_CUDAShared: handleSharedAttr(S, D, Attr); Index: cfe/trunk/test/SemaCXX/warn-conflicting-nothrow-attr-exception-spec.cpp =================================================================== --- cfe/trunk/test/SemaCXX/warn-conflicting-nothrow-attr-exception-spec.cpp +++ cfe/trunk/test/SemaCXX/warn-conflicting-nothrow-attr-exception-spec.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 %s -fcxx-exceptions -fsyntax-only -Wexceptions -verify -std=c++14 + +struct S { + //expected-warning@+2 {{attribute 'nothrow' ignored due to conflicting exception specification}} + //expected-note@+1 {{exception specification declared here}} + __attribute__((nothrow)) S() noexcept(true); + //expected-warning@+2 {{attribute 'nothrow' ignored due to conflicting exception specification}} + //expected-note@+1 {{exception specification declared here}} + __attribute__((nothrow)) void Func1() noexcept(false); + __attribute__((nothrow)) void Func3() noexcept; +}; + +void throwing() noexcept(false); +void non_throwing(bool b = true) noexcept; + +template +struct T { + __attribute__((nothrow)) void f(Fn) noexcept(Fn()); +}; + +//expected-warning@-3 {{attribute 'nothrow' ignored due to conflicting exception specification}} +//expected-note@-4 {{exception specification declared here}} +template struct T; +template struct T;