erichkeane updated this revision to Diff 116892. erichkeane marked 2 inline comments as done. erichkeane added a comment.
changes that were suggested by @aaron.ballman It DOES warn on the template correctly, however I'm not thrilled that it misses the 'warning' info. Any idea how I can get that information to give that 'note'? I'd like an "in instantiation of template ..." type note. https://reviews.llvm.org/D38205 Files: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDeclAttr.cpp test/SemaCXX/warn-conflicting-nothrow-attr-exception-spec.cpp Index: test/SemaCXX/warn-conflicting-nothrow-attr-exception-spec.cpp =================================================================== --- /dev/null +++ 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 <typename Fn> +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<decltype(throwing)>; +template struct T<decltype(non_throwing)>; Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -1985,6 +1985,25 @@ attr.getRange(), S.Context, attr.getAttributeSpellingListIndex())); } +static void handleNoThrowAttr(Sema &S, Decl *D, const AttributeList &Attrs) { + assert(isa<FunctionDecl>(D) && "attribute nothrow only valid on functions"); + + auto *FD = cast<FunctionDecl>(D); + const auto *FPT = FD->getType()->getAs<FunctionProtoType>(); + + 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<NoThrowAttr>(S, D, Attr); + handleNoThrowAttr(S, D, Attr); break; case AttributeList::AT_CUDAShared: handleSharedAttr(S, D, Attr); 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 due to conflicting exception " + "specification">, + InGroup<IgnoredAttributes>; // C++ access checking def err_class_redeclared_with_different_access : Error<
Index: test/SemaCXX/warn-conflicting-nothrow-attr-exception-spec.cpp =================================================================== --- /dev/null +++ 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 <typename Fn> +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<decltype(throwing)>; +template struct T<decltype(non_throwing)>; Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -1985,6 +1985,25 @@ attr.getRange(), S.Context, attr.getAttributeSpellingListIndex())); } +static void handleNoThrowAttr(Sema &S, Decl *D, const AttributeList &Attrs) { + assert(isa<FunctionDecl>(D) && "attribute nothrow only valid on functions"); + + auto *FD = cast<FunctionDecl>(D); + const auto *FPT = FD->getType()->getAs<FunctionProtoType>(); + + 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<NoThrowAttr>(S, D, Attr); + handleNoThrowAttr(S, D, Attr); break; case AttributeList::AT_CUDAShared: handleSharedAttr(S, D, Attr); 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 due to conflicting exception " + "specification">, + InGroup<IgnoredAttributes>; // C++ access checking def err_class_redeclared_with_different_access : Error<
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits