Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ 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, it disagrees with language specified " + "exception specification">, + InGroup; // C++ access checking def err_class_redeclared_with_different_access : Error< Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -1969,6 +1969,25 @@ attr.getRange(), S.Context, attr.getAttributeSpellingListIndex())); } +static void handleNoThrowAttr(Sema &S, Decl *D, const AttributeList &attr) { + 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(attr.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( + attr.getRange(), S.Context, attr.getAttributeSpellingListIndex())); +} + static void handleNoCallerSavedRegsAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (S.CheckNoCallerSavedRegsAttr(Attr)) @@ -6192,7 +6211,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: test/SemaCXX/warn-conflicting-nothrow-attr-exception-spec.cpp =================================================================== --- /dev/null +++ test/SemaCXX/warn-conflicting-nothrow-attr-exception-spec.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 %s -fcxx-exceptions -fsyntax-only -Wexceptions -verify -std=c++14 + +struct S { + //expected-warning@+2 {{Attribute nothrow ignored, it disagrees with}} + ///expected-note@+1 {{exception specification declared here}} + __attribute__((nothrow)) S() noexcept(true); + //expected-warning@+2 {{Attribute nothrow ignored, it disagrees with}} + ///expected-note@+1 {{exception specification declared here}} + __attribute__((nothrow)) void Func1() noexcept(false); + __attribute__((nothrow)) void Func3() noexcept; +};