diff --git a/clang/examples/Attribute/Attribute.cpp b/clang/examples/Attribute/Attribute.cpp index 3b90724ad22205..625f1645afbff6 100644 --- a/clang/examples/Attribute/Attribute.cpp +++ b/clang/examples/Attribute/Attribute.cpp @@ -42,8 +42,8 @@ struct ExampleAttrInfo : public ParsedAttrInfo { const Decl *D) const override { // This attribute appertains to functions only. if (!isa(D)) { - S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str) - << Attr << Attr.isRegularKeywordAttribute() << "functions"; + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr << Attr.isRegularKeywordAttribute() << ExpectedFunction; return false; } return true; @@ -99,8 +99,9 @@ struct ExampleAttrInfo : public ParsedAttrInfo { const Stmt *St) const override { // This attribute appertains to for loop statements only. if (!isa(St)) { - S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str) - << Attr << Attr.isRegularKeywordAttribute() << "for loop statements"; + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr << Attr.isRegularKeywordAttribute() + << ExpectedForLoopStatement; return false; } return true; diff --git a/clang/examples/CallSuperAttribute/CallSuperAttrInfo.cpp b/clang/examples/CallSuperAttribute/CallSuperAttrInfo.cpp index 12d4c311586e6f..f206a84ab1311d 100644 --- a/clang/examples/CallSuperAttribute/CallSuperAttrInfo.cpp +++ b/clang/examples/CallSuperAttribute/CallSuperAttrInfo.cpp @@ -168,8 +168,9 @@ struct CallSuperAttrInfo : public ParsedAttrInfo { const Decl *D) const override { const auto *TheMethod = dyn_cast_or_null(D); if (!TheMethod || !TheMethod->isVirtual()) { - S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str) - << Attr << Attr.isRegularKeywordAttribute() << "virtual functions"; + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << Attr << Attr.isRegularKeywordAttribute() + << ExpectedVirtualFunction; return false; } MarkedMethods.insert(TheMethod); diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index f04381a32a4158..8be4f946dce1cc 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3799,7 +3799,14 @@ def warn_attribute_wrong_decl_type : Warning< "|types and namespaces" "|variables, functions and classes" "|kernel functions" - "|non-K&R-style functions}2">, + "|non-K&R-style functions" + "|for loop statements" + "|virtual functions" + "|parameters and implicit object parameters" + "|non-member functions" + "|functions, classes, or enumerations" + "|classes" + "|typedefs}2">, InGroup; def err_attribute_wrong_decl_type : Error; def warn_type_attribute_wrong_type : Warning< diff --git a/clang/include/clang/Sema/ParsedAttr.h b/clang/include/clang/Sema/ParsedAttr.h index 4fa5fbdb5a7f63..e1faab205f647a 100644 --- a/clang/include/clang/Sema/ParsedAttr.h +++ b/clang/include/clang/Sema/ParsedAttr.h @@ -1099,6 +1099,13 @@ enum AttributeDeclKind { ExpectedFunctionVariableOrClass, ExpectedKernelFunction, ExpectedFunctionWithProtoType, + ExpectedForLoopStatement, + ExpectedVirtualFunction, + ExpectedParameterOrImplicitObjectParameter, + ExpectedNonMemberFunction, + ExpectedFunctionOrClassOrEnum, + ExpectedClass, + ExpectedTypedef, }; inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 7f3f6d568e28cf..f136d5007e8a5f 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -24,6 +24,7 @@ #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Lookup.h" +#include "clang/Sema/ParsedAttr.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "clang/Sema/SemaCUDA.h" @@ -3708,9 +3709,9 @@ void Parser::ParseDeclarationSpecifiers( continue; if (PA.getKind() == ParsedAttr::AT_LifetimeBound) - Diag(PA.getLoc(), diag::err_attribute_wrong_decl_type_str) + Diag(PA.getLoc(), diag::err_attribute_wrong_decl_type) << PA << PA.isRegularKeywordAttribute() - << "parameters and implicit object parameters"; + << ExpectedParameterOrImplicitObjectParameter; else Diag(PA.getLoc(), diag::err_attribute_not_type_attr) << PA << PA.isRegularKeywordAttribute(); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index bb4d33560b93b8..c1663f2d15c88b 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -1868,8 +1868,8 @@ static void handleNakedAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // This form is not allowed to be written on a member function (static or // nonstatic) when in Microsoft compatibility mode. if (S.getLangOpts().MSVCCompat && isa(D)) { - S.Diag(AL.getLoc(), diag::err_attribute_wrong_decl_type_str) - << AL << AL.isRegularKeywordAttribute() << "non-member functions"; + S.Diag(AL.getLoc(), diag::err_attribute_wrong_decl_type) + << AL << AL.isRegularKeywordAttribute() << ExpectedNonMemberFunction; return; } } @@ -2761,9 +2761,9 @@ static void handleWarnUnusedResult(Sema &S, Decl *D, const ParsedAttr &AL) { // The standard attribute cannot be applied to variable declarations such // as a function pointer. if (isa(D)) - S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type_str) + S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) << AL << AL.isRegularKeywordAttribute() - << "functions, classes, or enumerations"; + << ExpectedFunctionOrClassOrEnum; // If this is spelled as the standard C++17 attribute, but not in C++17, // warn about using it as an extension. If there are attribute arguments, @@ -5555,8 +5555,8 @@ static void handleNullableTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (auto *CRD = dyn_cast(D); !CRD || !(CRD->isClass() || CRD->isStruct())) { - S.Diag(AL.getRange().getBegin(), diag::err_attribute_wrong_decl_type_str) - << AL << AL.isRegularKeywordAttribute() << "classes"; + S.Diag(AL.getRange().getBegin(), diag::err_attribute_wrong_decl_type) + << AL << AL.isRegularKeywordAttribute() << ExpectedClass; return; } diff --git a/clang/lib/Sema/SemaSwift.cpp b/clang/lib/Sema/SemaSwift.cpp index 24fdfb8e57dc34..fe72d6c85c37a3 100644 --- a/clang/lib/Sema/SemaSwift.cpp +++ b/clang/lib/Sema/SemaSwift.cpp @@ -650,8 +650,8 @@ void SemaSwift::handleNewType(Decl *D, const ParsedAttr &AL) { } if (!isa(D)) { - Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type_str) - << AL << AL.isRegularKeywordAttribute() << "typedefs"; + Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type) + << AL << AL.isRegularKeywordAttribute() << ExpectedTypedef; return; } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index e3ec327c1b3644..2ccf5a8e1d6f31 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -7983,8 +7983,9 @@ static bool handleFunctionTypeAttr(TypeProcessingState &state, ParsedAttr &attr, if (!FnTy) { // SME ACLE attributes are not supported on K&R-style unprototyped C // functions. - S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type) << - attr << attr.isRegularKeywordAttribute() << ExpectedFunctionWithProtoType; + S.Diag(attr.getLoc(), diag::warn_attribute_wrong_decl_type) + << attr << attr.isRegularKeywordAttribute() + << ExpectedFunctionWithProtoType; attr.setInvalid(); return false; } @@ -8676,9 +8677,9 @@ static void HandleLifetimeBoundAttr(TypeProcessingState &State, CurType, CurType); return; } - State.getSema().Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type_str) + State.getSema().Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) << Attr << Attr.isRegularKeywordAttribute() - << "parameters and implicit object parameters"; + << ExpectedParameterOrImplicitObjectParameter; } static void HandleLifetimeCaptureByAttr(TypeProcessingState &State,