diff --git a/clang/include/clang/Sema/ParsedAttr.h b/clang/include/clang/Sema/ParsedAttr.h --- a/clang/include/clang/Sema/ParsedAttr.h +++ b/clang/include/clang/Sema/ParsedAttr.h @@ -117,6 +117,13 @@ const ParsedAttr &Attr) const { return NotHandled; } + /// If this ParsedAttrInfo knows how to handle this ParsedAttr applied to this + /// Stmt then do so and return either AttributeApplied if it was applied or + /// AttributeNotApplied if it wasn't. Otherwise return NotHandled. + virtual AttrHandling handleStmtAttribute(Sema &S, Stmt *St, + const ParsedAttr &Attr) const { + return NotHandled; + } static const ParsedAttrInfo &get(const AttributeCommonInfo &A); }; diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -430,11 +430,12 @@ case ParsedAttr::AT_Unlikely: return handleUnlikely(S, St, A, Range); default: - // N.B., ClangAttrEmitter.cpp emits a diagnostic helper that ensures a - // declaration attribute is not written on a statement, but this code is - // needed for attributes in Attr.td that do not list any subjects. - S.Diag(A.getRange().getBegin(), diag::err_decl_attribute_invalid_on_stmt) - << A << St->getBeginLoc(); + if (A.getInfo().handleStmtAttribute(S, St, A) == ParsedAttrInfo::NotHandled) + // N.B., ClangAttrEmitter.cpp emits a diagnostic helper that ensures a + // declaration attribute is not written on a statement, but this code is + // needed for attributes in Attr.td that do not list any subjects. + S.Diag(A.getRange().getBegin(), diag::err_decl_attribute_invalid_on_stmt) + << A << St->getBeginLoc(); return nullptr; } }