mboehme created this revision.
Herald added a reviewer: aaron.ballman.
Herald added a project: All.
mboehme requested review of this revision.
Herald added a reviewer: jdoerfert.
Herald added subscribers: cfe-commits, sstefan1.
Herald added a project: clang.

DRAFT -- do not review.

Depends On D111548 <https://reviews.llvm.org/D111548>


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D124083

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/ParsedAttr.h
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseExprCXX.cpp
  clang/lib/Parse/ParseObjc.cpp
  clang/lib/Parse/ParseOpenMP.cpp
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Parse/ParseStmt.cpp
  clang/lib/Parse/ParseTemplate.cpp
  clang/lib/Parse/Parser.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/lib/Sema/SemaStmtAttr.cpp
  clang/test/Sema/annotate-type.c
  clang/test/SemaCXX/annotate-type.cpp
  clang/utils/TableGen/ClangAttrEmitter.cpp

Index: clang/utils/TableGen/ClangAttrEmitter.cpp
===================================================================
--- clang/utils/TableGen/ClangAttrEmitter.cpp
+++ clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -3728,7 +3728,7 @@
     if (!StmtSubjects.empty()) {
       OS << "bool diagAppertainsToDecl(Sema &S, const ParsedAttr &AL, ";
       OS << "const Decl *D) const override {\n";
-      OS << "  S.Diag(AL.getLoc(), diag::err_stmt_attribute_invalid_on_decl)\n";
+      OS << "  S.Diag(AL.getLoc(), diag::err_attribute_invalid_on_decl)\n";
       OS << "    << AL << D->getLocation();\n";
       OS << "  return false;\n";
       OS << "}\n\n";
@@ -3772,7 +3772,7 @@
     if (!DeclSubjects.empty()) {
       OS << "bool diagAppertainsToStmt(Sema &S, const ParsedAttr &AL, ";
       OS << "const Stmt *St) const override {\n";
-      OS << "  S.Diag(AL.getLoc(), diag::err_decl_attribute_invalid_on_stmt)\n";
+      OS << "  S.Diag(AL.getLoc(), diag::err_attribute_invalid_on_stmt)\n";
       OS << "    << AL << St->getBeginLoc();\n";
       OS << "  return false;\n";
       OS << "}\n\n";
@@ -4220,6 +4220,9 @@
     OS << "    /*IsStmt=*/";
     OS << (Attr.isSubClassOf("StmtAttr") || Attr.isSubClassOf("DeclOrStmtAttr"))
        << ",\n";
+    OS << "    /*IsDecl=*/";
+    OS << (!Attr.isSubClassOf("TypeAttr") && !Attr.isSubClassOf("StmtAttr"))
+       << ",\n";
     OS << "    /*IsKnownToGCC=*/";
     OS << IsKnownToGCC(Attr) << ",\n";
     OS << "    /*IsSupportedByPragmaAttribute=*/";
Index: clang/test/SemaCXX/annotate-type.cpp
===================================================================
--- clang/test/SemaCXX/annotate-type.cpp
+++ clang/test/SemaCXX/annotate-type.cpp
@@ -2,10 +2,7 @@
 
 struct S1 {
   void f() [[clang::annotate_type("foo")]];
-  // FIXME: We would want to prohibit the attribute in the following location.
-  // However, Clang currently generally doesn't prohibit type-only C++11
-  // attributes on declarations. This should be fixed more generally.
-  [[clang::annotate_type("foo")]] void g();
+  [[clang::annotate_type("foo")]] void g(); // expected-error {{'annotate_type' attribute cannot be applied to a declaration}}
 };
 
 template <typename T1, typename T2> struct is_same {
@@ -52,8 +49,8 @@
 // Different declarations hit different code paths, so they need separate tests.
 // FIXME: Clang currently generally doesn't prohibit type-only C++11
 // attributes on declarations.
-namespace [[clang::annotate_type("foo")]] my_namespace {}
-struct [[clang::annotate_type("foo")]] S3{};
+namespace [[clang::annotate_type("foo")]] my_namespace {} // expected-error {{'annotate_type' attribute cannot be applied to a declaration}}
+struct [[clang::annotate_type("foo")]] S3{}; // expected-error {{'annotate_type' attribute cannot be applied to a declaration}}
 void f4() {
-  for ([[clang::annotate_type("foo")]] int i = 0; i < 42; ++i) {}
+  for ([[clang::annotate_type("foo")]] int i = 0; i < 42; ++i) {} // expected-error {{'annotate_type' attribute cannot be applied to a declaration}}
 }
Index: clang/test/Sema/annotate-type.c
===================================================================
--- clang/test/Sema/annotate-type.c
+++ clang/test/Sema/annotate-type.c
@@ -17,10 +17,7 @@
   int *__attribute__((annotate_type("bar"))) y2; // expected-warning {{unknown attribute 'annotate_type' ignored}}
 
   // Various error cases
-  // FIXME: We would want to prohibit the attribute in the following location.
-  // However, Clang currently generally doesn't prohibit type-only C++11
-  // attributes on declarations. This should be fixed more generally.
-  [[clang::annotate_type("bar")]] int *z1;
+  [[clang::annotate_type("bar")]] int *z1; // expected-error {{'annotate_type' attribute cannot be applied to a declaration}}
   int *z2 [[clang::annotate_type("bar")]]; // expected-error {{'annotate_type' attribute cannot be applied to a declaration}}
   [[clang::annotate_type("bar")]]; // expected-error {{'annotate_type' attribute cannot be applied to a statement}}
   int *[[clang::annotate_type(1)]] z3; // expected-error {{'annotate_type' attribute requires a string}}
@@ -33,7 +30,5 @@
 }
 // More error cases: Prohibit adding the attribute to declarations.
 // Different declarations hit different code paths, so they need separate tests.
-// FIXME: Clang currently generally doesn't prohibit type-only C++11
-// attributes on declarations.
-[[clang::annotate_type("bar")]] int *global;
-void g([[clang::annotate_type("bar")]] int);
+[[clang::annotate_type("bar")]] int *global; // expected-error {{'annotate_type' attribute cannot be applied to a declaration}}
+void g([[clang::annotate_type("bar")]] int); // expected-error {{'annotate_type' attribute cannot be applied to a declaration}}
Index: clang/lib/Sema/SemaStmtAttr.cpp
===================================================================
--- clang/lib/Sema/SemaStmtAttr.cpp
+++ clang/lib/Sema/SemaStmtAttr.cpp
@@ -489,7 +489,7 @@
     // 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)
+    S.Diag(A.getRange().getBegin(), diag::err_attribute_invalid_on_stmt)
         << A << St->getBeginLoc();
     return nullptr;
   }
Index: clang/lib/Sema/SemaDeclAttr.cpp
===================================================================
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -8209,7 +8209,7 @@
     // N.B., ClangAttrEmitter.cpp emits a diagnostic helper that ensures a
     // statement attribute is not written on a declaration, but this code is
     // needed for attributes in Attr.td that do not list any subjects.
-    S.Diag(AL.getLoc(), diag::err_stmt_attribute_invalid_on_decl)
+    S.Diag(AL.getLoc(), diag::err_attribute_invalid_on_decl)
         << AL << D->getLocation();
     break;
   case ParsedAttr::AT_Interrupt:
Index: clang/lib/Parse/Parser.cpp
===================================================================
--- clang/lib/Parse/Parser.cpp
+++ clang/lib/Parse/Parser.cpp
@@ -722,7 +722,7 @@
   }
 
   ParsedAttributesWithRange attrs(AttrFactory);
-  MaybeParseCXX11Attributes(attrs);
+  MaybeParseCXX11Attributes(attrs, AppertainsToDecl);
 
   Result = ParseExternalDeclaration(attrs);
   // An empty Result might mean a line with ';' or some parsing error, ignore
@@ -2293,7 +2293,7 @@
   // FIXME: Support module import within __if_exists?
   while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
     ParsedAttributesWithRange attrs(AttrFactory);
-    MaybeParseCXX11Attributes(attrs);
+    MaybeParseCXX11Attributes(attrs, AppertainsToDecl);
     DeclGroupPtrTy Result = ParseExternalDeclaration(attrs);
     if (Result && !getCurScope()->getParent())
       Actions.getASTConsumer().HandleTopLevelDecl(Result.get());
@@ -2381,7 +2381,7 @@
 
   // We don't support any module attributes yet; just parse them and diagnose.
   ParsedAttributesWithRange Attrs(AttrFactory);
-  MaybeParseCXX11Attributes(Attrs);
+  MaybeParseCXX11Attributes(Attrs, AppertainsToDecl);
   ProhibitCXX11Attributes(Attrs, diag::err_attribute_not_module_attr);
 
   ExpectAndConsumeSemi(diag::err_module_expected_semi);
@@ -2447,7 +2447,7 @@
   }
 
   ParsedAttributesWithRange Attrs(AttrFactory);
-  MaybeParseCXX11Attributes(Attrs);
+  MaybeParseCXX11Attributes(Attrs, AppertainsToDecl);
   // We don't support any module import attributes yet.
   ProhibitCXX11Attributes(Attrs, diag::err_attribute_not_import_attr);
 
Index: clang/lib/Parse/ParseTemplate.cpp
===================================================================
--- clang/lib/Parse/ParseTemplate.cpp
+++ clang/lib/Parse/ParseTemplate.cpp
@@ -205,7 +205,7 @@
   }
 
   ParsedAttributesWithRange prefixAttrs(AttrFactory);
-  MaybeParseCXX11Attributes(prefixAttrs);
+  MaybeParseCXX11Attributes(prefixAttrs, AppertainsToDecl);
 
   if (Tok.is(tok::kw_using)) {
     auto usingDeclPtr = ParseUsingDirectiveOrDeclaration(Context, TemplateInfo, DeclEnd,
Index: clang/lib/Parse/ParseStmt.cpp
===================================================================
--- clang/lib/Parse/ParseStmt.cpp
+++ clang/lib/Parse/ParseStmt.cpp
@@ -106,7 +106,11 @@
   // at the start of the statement. Thus, we're not using MaybeParseAttributes
   // here because we don't want to allow arbitrary orderings.
   ParsedAttributesWithRange Attrs(AttrFactory);
-  MaybeParseCXX11Attributes(Attrs, /*MightBeObjCMessageSend*/ true);
+  // TODO: Oops -- don't know what to pass here! So we need to be able to do
+  // either-or and then process this further in
+  // ParseStatementOrDeclarationAfterAttributes(). Phew, this is complicated.
+  MaybeParseCXX11Attributes(Attrs, AppertainsToUnknown,
+                            /*MightBeObjCMessageSend*/ true);
   if (getLangOpts().OpenCL)
     MaybeParseGNUAttributes(Attrs);
 
@@ -223,6 +227,7 @@
          isDeclarationStatement())) {
       SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
       DeclGroupPtrTy Decl;
+      DiagnoseAppertainsTo(Attrs, AppertainsToDecl);
       if (GNUAttributeLoc.isValid()) {
         DeclStart = GNUAttributeLoc;
         Decl = ParseDeclaration(DeclaratorContext::Block, DeclEnd, Attrs,
@@ -1119,7 +1124,8 @@
         ConsumeToken();
 
       ParsedAttributesWithRange attrs(AttrFactory);
-      MaybeParseCXX11Attributes(attrs, /*MightBeObjCMessageSend*/ true);
+      MaybeParseCXX11Attributes(attrs, AppertainsToUnknown,
+                                /*MightBeObjCMessageSend*/ true);
 
       // If this is the start of a declaration, parse it as such.
       if (isDeclarationStatement()) {
@@ -1925,7 +1931,7 @@
   }
 
   ParsedAttributesWithRange attrs(AttrFactory);
-  MaybeParseCXX11Attributes(attrs);
+  MaybeParseCXX11Attributes(attrs, AppertainsToDecl);
 
   SourceLocation EmptyInitStmtSemiLoc;
 
@@ -1942,7 +1948,7 @@
     ProhibitAttributes(attrs);
     IdentifierInfo *Name = Tok.getIdentifierInfo();
     SourceLocation Loc = ConsumeToken();
-    MaybeParseCXX11Attributes(attrs);
+    MaybeParseCXX11Attributes(attrs, AppertainsToDecl);
 
     ForRangeInfo.ColonLoc = ConsumeToken();
     if (Tok.is(tok::l_brace))
@@ -2345,7 +2351,7 @@
   }
 
   // Get the next statement.
-  MaybeParseCXX11Attributes(Attrs);
+  MaybeParseCXX11Attributes(Attrs, AppertainsToUnknown);
 
   StmtResult S = ParseStatementOrDeclarationAfterAttributes(
       Stmts, StmtCtx, TrailingElseLoc, Attrs);
@@ -2581,7 +2587,7 @@
   Decl *ExceptionDecl = nullptr;
   if (Tok.isNot(tok::ellipsis)) {
     ParsedAttributesWithRange Attributes(AttrFactory);
-    MaybeParseCXX11Attributes(Attributes);
+    MaybeParseCXX11Attributes(Attributes, AppertainsToDecl);
 
     DeclSpec DS(AttrFactory);
     DS.takeAttributesFrom(Attributes);
Index: clang/lib/Parse/ParsePragma.cpp
===================================================================
--- clang/lib/Parse/ParsePragma.cpp
+++ clang/lib/Parse/ParsePragma.cpp
@@ -1651,7 +1651,7 @@
 
   if (Tok.is(tok::l_square) && NextToken().is(tok::l_square)) {
     // Parse the CXX11 style attribute.
-    ParseCXX11AttributeSpecifier(Attrs);
+    ParseCXX11AttributeSpecifier(Attrs, AppertainsToUnknown);
   } else if (Tok.is(tok::kw___attribute)) {
     ConsumeToken();
     if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
Index: clang/lib/Parse/ParseOpenMP.cpp
===================================================================
--- clang/lib/Parse/ParseOpenMP.cpp
+++ clang/lib/Parse/ParseOpenMP.cpp
@@ -2280,7 +2280,7 @@
       // Here we expect to see some function declaration.
       if (AS == AS_none) {
         assert(TagType == DeclSpec::TST_unspecified);
-        MaybeParseCXX11Attributes(Attrs);
+        MaybeParseCXX11Attributes(Attrs, AppertainsToDecl);
         ParsingDeclSpec PDS(*this);
         Ptr = ParseExternalDeclaration(Attrs, &PDS);
       } else {
Index: clang/lib/Parse/ParseObjc.cpp
===================================================================
--- clang/lib/Parse/ParseObjc.cpp
+++ clang/lib/Parse/ParseObjc.cpp
@@ -1358,7 +1358,7 @@
   // If attributes exist before the method, parse them.
   ParsedAttributes methodAttrs(AttrFactory);
   MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0),
-                       methodAttrs);
+                       methodAttrs, AppertainsToDecl);
 
   if (Tok.is(tok::code_completion)) {
     cutOffParsing();
@@ -1384,7 +1384,7 @@
   if (Tok.isNot(tok::colon)) {
     // If attributes exist after the method, parse them.
     MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0),
-                         methodAttrs);
+                         methodAttrs, AppertainsToDecl);
 
     Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent);
     Decl *Result = Actions.ActOnMethodDeclaration(
@@ -1418,7 +1418,7 @@
     // If attributes exist before the argument name, parse them.
     // Regardless, collect all the attributes we've parsed so far.
     MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0),
-                         paramAttrs);
+                         paramAttrs, AppertainsToDecl);
     ArgInfo.ArgAttrs = paramAttrs;
 
     // Code completion for the next piece of the selector.
@@ -1501,7 +1501,7 @@
   // FIXME: Add support for optional parameter list...
   // If attributes exist after the method, parse them.
   MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0),
-                       methodAttrs);
+                       methodAttrs, AppertainsToDecl);
 
   if (KeyIdents.size() == 0)
     return nullptr;
@@ -2218,7 +2218,7 @@
     ObjCImplParsingDataRAII ObjCImplParsing(*this, ObjCImpDecl);
     while (!ObjCImplParsing.isFinished() && !isEofOrEom()) {
       ParsedAttributesWithRange attrs(AttrFactory);
-      MaybeParseCXX11Attributes(attrs);
+      MaybeParseCXX11Attributes(attrs, AppertainsToDecl);
       if (DeclGroupPtrTy DGP = ParseExternalDeclaration(attrs)) {
         DeclGroupRef DG = DGP.get();
         DeclsInGroup.append(DG.begin(), DG.end());
Index: clang/lib/Parse/ParseExprCXX.cpp
===================================================================
--- clang/lib/Parse/ParseExprCXX.cpp
+++ clang/lib/Parse/ParseExprCXX.cpp
@@ -1328,7 +1328,7 @@
         // GNU-style attributes must be parsed before the mutable specifier to
         // be compatible with GCC. MSVC-style attributes must be parsed before
         // the mutable specifier to be compatible with MSVC.
-        MaybeParseAttributes(PAKM_GNU | PAKM_Declspec, Attr);
+        MaybeParseAttributes(PAKM_GNU | PAKM_Declspec, Attr, AppertainsToDecl);
 
         // Parse mutable-opt and/or constexpr-opt or consteval-opt, and update
         // the DeclEndLoc.
@@ -1355,7 +1355,8 @@
           DeclEndLoc = ESpecRange.getEnd();
 
         // Parse attribute-specifier[opt].
-        if (MaybeParseCXX11Attributes(Attr))
+        // TODO: Correct?
+        if (MaybeParseCXX11Attributes(Attr, AppertainsToType))
           DeclEndLoc = Attr.Range.getEnd();
 
         // Parse OpenCL addr space attribute.
@@ -1993,7 +1994,7 @@
   }
 
   ParsedAttributesWithRange attrs(AttrFactory);
-  MaybeParseCXX11Attributes(attrs);
+  MaybeParseCXX11Attributes(attrs, AppertainsToDecl);
 
   const auto WarnOnInit = [this, &CK] {
     Diag(Tok.getLocation(), getLangOpts().CPlusPlus17
@@ -3244,7 +3245,7 @@
 
     // Attributes here appertain to the array type. C++11 [expr.new]p5.
     ParsedAttributes Attrs(AttrFactory);
-    MaybeParseCXX11Attributes(Attrs);
+    MaybeParseCXX11Attributes(Attrs, AppertainsToType);
 
     D.AddTypeInfo(DeclaratorChunk::getArray(0,
                                             /*isStatic=*/false, /*isStar=*/false,
Index: clang/lib/Parse/ParseDeclCXX.cpp
===================================================================
--- clang/lib/Parse/ParseDeclCXX.cpp
+++ clang/lib/Parse/ParseDeclCXX.cpp
@@ -10,7 +10,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "clang/Parse/Parser.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/PrettyDeclStackTrace.h"
@@ -19,10 +18,12 @@
 #include "clang/Basic/OperatorKinds.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/Parser.h"
 #include "clang/Parse/RAIIObjectsForParser.h"
 #include "clang/Sema/DeclSpec.h"
 #include "clang/Sema/ParsedTemplate.h"
 #include "clang/Sema/Scope.h"
+#include "clang/Sema/SemaDiagnostic.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Support/TimeProfiler.h"
 
@@ -88,7 +89,7 @@
                                     ? diag::warn_cxx14_compat_ns_enum_attribute
                                     : diag::ext_ns_enum_attribute)
             << 0 /*namespace*/;
-        ParseCXX11Attributes(attrs);
+        ParseCXX11Attributes(attrs, AppertainsToDecl);
         MoreToParse = true;
       }
     } while (MoreToParse);
@@ -252,7 +253,7 @@
     while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
            Tok.isNot(tok::eof)) {
       ParsedAttributesWithRange attrs(AttrFactory);
-      MaybeParseCXX11Attributes(attrs);
+      MaybeParseCXX11Attributes(attrs, AppertainsToDecl);
       ParseExternalDeclaration(attrs);
     }
 
@@ -355,7 +356,7 @@
                 Tok.is(tok::l_brace) ? Tok.getLocation() : SourceLocation());
 
   ParsedAttributesWithRange attrs(AttrFactory);
-  MaybeParseCXX11Attributes(attrs);
+  MaybeParseCXX11Attributes(attrs, AppertainsToDecl);
 
   if (Tok.isNot(tok::l_brace)) {
     // Reset the source range in DS, as the leading "extern"
@@ -405,7 +406,7 @@
       LLVM_FALLTHROUGH;
     default:
       ParsedAttributesWithRange attrs(AttrFactory);
-      MaybeParseCXX11Attributes(attrs);
+      MaybeParseCXX11Attributes(attrs, AppertainsToDecl);
       ParseExternalDeclaration(attrs);
       continue;
     }
@@ -437,7 +438,7 @@
   if (Tok.isNot(tok::l_brace)) {
     // FIXME: Factor out a ParseExternalDeclarationWithAttrs.
     ParsedAttributesWithRange Attrs(AttrFactory);
-    MaybeParseCXX11Attributes(Attrs);
+    MaybeParseCXX11Attributes(Attrs, AppertainsToDecl);
     MaybeParseMicrosoftAttributes(Attrs);
     ParseExternalDeclaration(Attrs);
     return Actions.ActOnFinishExportDecl(getCurScope(), ExportDecl,
@@ -457,7 +458,7 @@
   while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
          Tok.isNot(tok::eof)) {
     ParsedAttributesWithRange Attrs(AttrFactory);
-    MaybeParseCXX11Attributes(Attrs);
+    MaybeParseCXX11Attributes(Attrs, AppertainsToDecl);
     MaybeParseMicrosoftAttributes(Attrs);
     ParseExternalDeclaration(Attrs);
   }
@@ -725,7 +726,7 @@
   // Check for misplaced attributes before the identifier in an
   // alias-declaration.
   ParsedAttributesWithRange MisplacedAttrs(AttrFactory);
-  MaybeParseCXX11Attributes(MisplacedAttrs);
+  MaybeParseCXX11Attributes(MisplacedAttrs, AppertainsToDecl);
 
   if (InInitStatement && Tok.isNot(tok::identifier))
     return nullptr;
@@ -734,7 +735,7 @@
   bool InvalidDeclarator = ParseUsingDeclarator(Context, D);
 
   ParsedAttributesWithRange Attrs(AttrFactory);
-  MaybeParseAttributes(PAKM_GNU | PAKM_CXX11, Attrs);
+  MaybeParseAttributes(PAKM_GNU | PAKM_CXX11, Attrs, AppertainsToDecl);
 
   // If we had any misplaced attributes from earlier, this is where they
   // should have been written.
@@ -781,7 +782,7 @@
   SmallVector<Decl *, 8> DeclsInGroup;
   while (true) {
     // Parse (optional) attributes.
-    MaybeParseAttributes(PAKM_GNU | PAKM_CXX11, Attrs);
+    MaybeParseAttributes(PAKM_GNU | PAKM_CXX11, Attrs, AppertainsToDecl);
     DiagnoseCXX11AttributeExtension(Attrs);
     Attrs.addAll(PrefixAttrs.begin(), PrefixAttrs.end());
 
@@ -1506,7 +1507,9 @@
 
   ParsedAttributesWithRange attrs(AttrFactory);
   // If attributes exist after tag, parse them.
-  MaybeParseAttributes(PAKM_CXX11 | PAKM_Declspec | PAKM_GNU, attrs);
+  // TODO: I think this doesn't really work -- could be a type too.
+  MaybeParseAttributes(PAKM_CXX11 | PAKM_Declspec | PAKM_GNU, attrs,
+                       AppertainsToDecl);
 
   // Parse inheritance specifiers.
   if (Tok.isOneOf(tok::kw___single_inheritance,
@@ -1515,7 +1518,9 @@
     ParseMicrosoftInheritanceClassAttributes(attrs);
 
   // Allow attributes to precede or succeed the inheritance specifiers.
-  MaybeParseAttributes(PAKM_CXX11 | PAKM_Declspec | PAKM_GNU, attrs);
+  // TODO: I think this doesn't really work -- could be a type too.
+  MaybeParseAttributes(PAKM_CXX11 | PAKM_Declspec | PAKM_GNU, attrs,
+                       AppertainsToDecl);
 
   // Source location used by FIXIT to insert misplaced
   // C++11 attributes
@@ -1752,7 +1757,7 @@
   // DeclSpecContext::DSC_alias_declaration.
 
   // If there are attributes after class name, parse them.
-  MaybeParseCXX11Attributes(Attributes);
+  MaybeParseCXX11Attributes(Attributes, AppertainsToDecl);
 
   const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
   Sema::TagUseKind TUK;
@@ -2164,7 +2169,7 @@
   SourceLocation StartLoc = Tok.getLocation();
 
   ParsedAttributesWithRange Attributes(AttrFactory);
-  MaybeParseCXX11Attributes(Attributes);
+  MaybeParseCXX11Attributes(Attributes, AppertainsToDecl);
 
   // Parse the 'virtual' keyword.
   if (TryConsumeToken(tok::kw_virtual))
@@ -2683,7 +2688,7 @@
   ParsedAttributesWithRange attrs(AttrFactory);
   ParsedAttributesViewWithRange FnAttrs;
   // Optional C++11 attribute-specifier
-  MaybeParseCXX11Attributes(attrs);
+  MaybeParseCXX11Attributes(attrs, AppertainsToDecl);
 
   // The next token may be an OpenMP pragma annotation token. That would
   // normally be handled from ParseCXXClassMemberDeclarationWithPragmas, but in
@@ -4370,6 +4375,68 @@
   return true;
 }
 
+void Parser::DiagnoseAppertainsTo(ParsedAttr &PA,
+                                  AttributeAppertainsTo appertainsTo) {
+  AttributeCommonInfo::Kind kind = PA.getKind();
+
+  if (kind == ParsedAttr::UnknownAttribute)
+    return;
+
+  switch (appertainsTo) {
+  case AppertainsToDecl:
+    if (!PA.getInfo().IsDecl && kind != ParsedAttr::AT_AddressSpace &&
+        kind != ParsedAttr::AT_CmseNSCall &&
+        kind != ParsedAttr::AT_OpenCLPrivateAddressSpace &&
+        kind != ParsedAttr::AT_OpenCLGlobalAddressSpace &&
+        kind != ParsedAttr::AT_OpenCLGlobalDeviceAddressSpace &&
+        kind != ParsedAttr::AT_OpenCLGlobalHostAddressSpace &&
+        kind != ParsedAttr::AT_OpenCLLocalAddressSpace &&
+        kind != ParsedAttr::AT_OpenCLConstantAddressSpace &&
+        kind != ParsedAttr::AT_OpenCLGenericAddressSpace &&
+        kind != ParsedAttr::AT_NeonPolyVectorType &&
+        kind != ParsedAttr::AT_NeonVectorType &&
+        kind != ParsedAttr::AT_ArmSveVectorBits &&
+        kind != ParsedAttr::AT_ArmMveStrictPolymorphism &&
+        kind != ParsedAttr::AT_BTFTypeTag &&
+        kind != ParsedAttr::AT_TypeNonNull &&
+        kind != ParsedAttr::AT_TypeNullable &&
+        kind != ParsedAttr::AT_TypeNullableResult &&
+        kind != ParsedAttr::AT_TypeNullUnspecified &&
+        kind != ParsedAttr::AT_ObjCInertUnsafeUnretained &&
+        kind != ParsedAttr::AT_Regparm && kind != ParsedAttr::AT_NoDeref &&
+        kind != ParsedAttr::AT_ObjCGC && kind != ParsedAttr::AT_VectorSize &&
+        kind != ParsedAttr::AT_MatrixType && kind != ParsedAttr::AT_Ptr32 &&
+        kind != ParsedAttr::AT_Ptr64 && kind != ParsedAttr::AT_SPtr &&
+        kind != ParsedAttr::AT_UPtr) {
+      Diag(PA.getLoc(), diag::err_attribute_invalid_on_decl) << PA;
+      PA.setInvalid();
+    }
+    break;
+  case AppertainsToType:
+    if (!PA.getInfo().IsType) {
+      Diag(PA.getLoc(), diag::err_attribute_not_type_attr) << PA;
+      PA.setInvalid();
+    }
+    break;
+  case AppertainsToStmt:
+    if (!PA.getInfo().IsStmt) {
+      Diag(PA.getLoc(), diag::err_attribute_invalid_on_stmt) << PA;
+      PA.setInvalid();
+    }
+    break;
+  case AppertainsToUnknown:
+    // No checking
+    break;
+  }
+}
+
+void Parser::DiagnoseAppertainsTo(ParsedAttributesView &Attrs,
+                                  AttributeAppertainsTo appertainsTo) {
+  for (ParsedAttr &PA : Attrs) {
+    DiagnoseAppertainsTo(PA, appertainsTo);
+  }
+}
+
 /// ParseCXX11AttributeSpecifier - Parse a C++11 or C2x attribute-specifier.
 ///
 /// [C++11] attribute-specifier:
@@ -4394,9 +4461,9 @@
 ///
 /// [C++11] attribute-namespace:
 ///         identifier
-void Parser::ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs,
-                                                  CachedTokens &OpenMPTokens,
-                                                  SourceLocation *EndLoc) {
+void Parser::ParseCXX11AttributeSpecifierInternal(
+    ParsedAttributes &Attrs, CachedTokens &OpenMPTokens,
+    AttributeAppertainsTo appertainsTo, SourceLocation *EndLoc) {
   if (Tok.is(tok::kw_alignas)) {
     Diag(Tok.getLocation(), diag::warn_cxx98_compat_alignas);
     ParseAlignmentSpecifier(Attrs, EndLoc);
@@ -4433,6 +4500,8 @@
 
   llvm::SmallDenseMap<IdentifierInfo*, SourceLocation, 4> SeenAttrs;
 
+  size_t NumAttributesExisting = Attrs.size();
+
   bool AttrParsed = false;
   while (!Tok.isOneOf(tok::r_square, tok::semi, tok::eof)) {
     if (AttrParsed) {
@@ -4501,6 +4570,10 @@
         << AttrName;
   }
 
+  for (size_t i = NumAttributesExisting; i < Attrs.size(); ++i) {
+    DiagnoseAppertainsTo(Attrs[i], appertainsTo);
+  }
+
   // If we hit an error and recovered by parsing up to a semicolon, eat the
   // semicolon and don't issue further diagnostics about missing brackets.
   if (Tok.is(tok::semi)) {
@@ -4523,14 +4596,15 @@
 ///
 /// attribute-specifier-seq:
 ///       attribute-specifier-seq[opt] attribute-specifier
-void Parser::ParseCXX11Attributes(ParsedAttributesWithRange &attrs) {
+void Parser::ParseCXX11Attributes(ParsedAttributesWithRange &attrs,
+                                  AttributeAppertainsTo appertainsTo) {
   assert(standardAttributesAllowed());
 
   SourceLocation StartLoc = Tok.getLocation();
   SourceLocation EndLoc = StartLoc;
 
   do {
-    ParseCXX11AttributeSpecifier(attrs, &EndLoc);
+    ParseCXX11AttributeSpecifier(attrs, appertainsTo, &EndLoc);
   } while (isCXX11AttributeSpecifier());
 
   attrs.Range = SourceRange(StartLoc, EndLoc);
Index: clang/lib/Parse/ParseDecl.cpp
===================================================================
--- clang/lib/Parse/ParseDecl.cpp
+++ clang/lib/Parse/ParseDecl.cpp
@@ -105,6 +105,7 @@
 
 void Parser::ParseAttributes(unsigned WhichAttrKinds,
                              ParsedAttributesWithRange &Attrs,
+                             AttributeAppertainsTo appertainsTo,
                              LateParsedAttrList *LateAttrs) {
   bool MoreToParse;
   do {
@@ -112,7 +113,8 @@
     // parsed, loop to ensure all specified attribute combinations are parsed.
     MoreToParse = false;
     if (WhichAttrKinds & PAKM_CXX11)
-      MoreToParse |= MaybeParseCXX11Attributes(Attrs);
+      // TODO: Need to plumb the right value in here
+      MoreToParse |= MaybeParseCXX11Attributes(Attrs, appertainsTo);
     if (WhichAttrKinds & PAKM_GNU)
       MoreToParse |= MaybeParseGNUAttributes(Attrs, LateAttrs);
     if (WhichAttrKinds & PAKM_Declspec)
@@ -1652,7 +1654,7 @@
 
   // Consume the attributes.
   SourceLocation Loc = Tok.getLocation();
-  ParseCXX11Attributes(Attrs);
+  ParseCXX11Attributes(Attrs, AppertainsToUnknown);
   CharSourceRange AttrRange(SourceRange(Loc, Attrs.Range.getEnd()), true);
   // FIXME: use err_attributes_misplaced
   Diag(Loc, diag::err_attributes_not_allowed)
@@ -3216,7 +3218,7 @@
       attrs.clear();
       attrs.Range = SourceRange();
 
-      ParseCXX11Attributes(attrs);
+      ParseCXX11Attributes(attrs, AppertainsToType);
       AttrsLastTime = true;
       continue;
 
@@ -3675,7 +3677,8 @@
     // Attributes support.
     case tok::kw___attribute:
     case tok::kw___declspec:
-      ParseAttributes(PAKM_GNU | PAKM_Declspec, DS.getAttributes(), LateAttrs);
+      ParseAttributes(PAKM_GNU | PAKM_Declspec, DS.getAttributes(),
+                      AppertainsToType, LateAttrs);
       continue;
 
     // Microsoft single token adornments.
@@ -4313,7 +4316,7 @@
 
   // Parse leading attributes.
   ParsedAttributesWithRange Attrs(AttrFactory);
-  MaybeParseCXX11Attributes(Attrs);
+  MaybeParseCXX11Attributes(Attrs, AppertainsToDecl);
   DS.takeAttributesFrom(Attrs);
 
   // Parse the common specifier-qualifiers-list piece.
@@ -4552,7 +4555,8 @@
 
   // If attributes exist after tag, parse them.
   ParsedAttributesWithRange attrs(AttrFactory);
-  MaybeParseAttributes(PAKM_GNU | PAKM_Declspec | PAKM_CXX11, attrs);
+  MaybeParseAttributes(PAKM_GNU | PAKM_Declspec | PAKM_CXX11, attrs,
+                       AppertainsToDecl);
 
   SourceLocation ScopedEnumKWLoc;
   bool IsScopedUsingClassTag = false;
@@ -4569,7 +4573,8 @@
     ProhibitAttributes(attrs);
 
     // They are allowed afterwards, though.
-    MaybeParseAttributes(PAKM_GNU | PAKM_Declspec | PAKM_CXX11, attrs);
+    MaybeParseAttributes(PAKM_GNU | PAKM_Declspec | PAKM_CXX11, attrs,
+                         AppertainsToDecl);
   }
 
   // C++11 [temp.explicit]p12:
@@ -4962,7 +4967,7 @@
                                     ? diag::warn_cxx14_compat_ns_enum_attribute
                                     : diag::ext_ns_enum_attribute)
             << 1 /*enumerator*/;
-      ParseCXX11Attributes(attrs);
+      ParseCXX11Attributes(attrs, AppertainsToDecl);
     }
 
     SourceLocation EqualLoc;
@@ -5636,7 +5641,7 @@
   if (standardAttributesAllowed() && (AttrReqs & AR_CXX11AttributesParsed) &&
       isCXX11AttributeSpecifier()) {
     ParsedAttributesWithRange attrs(AttrFactory);
-    ParseCXX11Attributes(attrs);
+    ParseCXX11Attributes(attrs, AppertainsToType);
     DS.takeAttributesFrom(attrs);
   }
 
@@ -6679,7 +6684,7 @@
 
     // If there are attributes following the identifier list, parse them and
     // prohibit them.
-    MaybeParseCXX11Attributes(FnAttrs);
+    MaybeParseCXX11Attributes(FnAttrs, AppertainsToDecl);
     ProhibitAttributes(FnAttrs);
   } else {
     if (Tok.isNot(tok::r_paren))
@@ -6755,7 +6760,7 @@
 
       // Parse attribute-specifier-seq[opt]. Per DR 979 and DR 1297, this goes
       // after the exception-specification.
-      MaybeParseCXX11Attributes(FnAttrs);
+      MaybeParseCXX11Attributes(FnAttrs, AppertainsToType);
 
       // Parse trailing-return-type[opt].
       LocalEndLoc = EndLoc;
@@ -6771,7 +6776,7 @@
         EndLoc = Range.getEnd();
       }
     } else if (standardAttributesAllowed()) {
-      MaybeParseCXX11Attributes(FnAttrs);
+      MaybeParseCXX11Attributes(FnAttrs, AppertainsToType);
     }
   }
 
@@ -6963,7 +6968,7 @@
     DeclSpec DS(AttrFactory);
 
     // Parse any C++11 attributes.
-    MaybeParseCXX11Attributes(DS.getAttributes());
+    MaybeParseCXX11Attributes(DS.getAttributes(), AppertainsToDecl);
 
     // Skip any Microsoft attributes before a param.
     MaybeParseMicrosoftAttributes(DS.getAttributes());
@@ -7169,7 +7174,7 @@
   if (Tok.getKind() == tok::r_square) {
     T.consumeClose();
     ParsedAttributes attrs(AttrFactory);
-    MaybeParseCXX11Attributes(attrs);
+    MaybeParseCXX11Attributes(attrs, AppertainsToType);
 
     // Remember that we parsed the empty array type.
     D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, nullptr,
@@ -7185,7 +7190,7 @@
 
     T.consumeClose();
     ParsedAttributes attrs(AttrFactory);
-    MaybeParseCXX11Attributes(attrs);
+    MaybeParseCXX11Attributes(attrs, AppertainsToType);
 
     // Remember that we parsed a array type, and remember its features.
     D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, ExprRes.get(),
@@ -7262,7 +7267,7 @@
 
   T.consumeClose();
 
-  MaybeParseCXX11Attributes(DS.getAttributes());
+  MaybeParseCXX11Attributes(DS.getAttributes(), AppertainsToType);
 
   // Remember that we parsed a array type, and remember its features.
   D.AddTypeInfo(
Index: clang/include/clang/Sema/ParsedAttr.h
===================================================================
--- clang/include/clang/Sema/ParsedAttr.h
+++ clang/include/clang/Sema/ParsedAttr.h
@@ -61,6 +61,8 @@
   unsigned IsType : 1;
   /// True if this attribute applies to statements.
   unsigned IsStmt : 1;
+  /// True if this attribute applies to declarations.
+  unsigned IsDecl : 1;
   /// True if this attribute has any spellings that are known to gcc.
   unsigned IsKnownToGCC : 1;
   /// True if this attribute is supported by #pragma clang attribute.
@@ -79,20 +81,23 @@
                                AttributeCommonInfo::NoSemaHandlerAttribute)
       : AttrKind(AttrKind), NumArgs(0), OptArgs(0), NumArgMembers(0),
         HasCustomParsing(0), AcceptsExprPack(0), IsTargetSpecific(0), IsType(0),
-        IsStmt(0), IsKnownToGCC(0), IsSupportedByPragmaAttribute(0) {}
+        IsStmt(0), IsDecl(0), IsKnownToGCC(0), IsSupportedByPragmaAttribute(0) {
+  }
 
   constexpr ParsedAttrInfo(AttributeCommonInfo::Kind AttrKind, unsigned NumArgs,
                            unsigned OptArgs, unsigned NumArgMembers,
                            unsigned HasCustomParsing, unsigned AcceptsExprPack,
                            unsigned IsTargetSpecific, unsigned IsType,
-                           unsigned IsStmt, unsigned IsKnownToGCC,
+                           unsigned IsStmt, unsigned IsDecl,
+                           unsigned IsKnownToGCC,
                            unsigned IsSupportedByPragmaAttribute,
                            ArrayRef<Spelling> Spellings,
                            ArrayRef<const char *> ArgNames)
       : AttrKind(AttrKind), NumArgs(NumArgs), OptArgs(OptArgs),
         NumArgMembers(NumArgMembers), HasCustomParsing(HasCustomParsing),
         AcceptsExprPack(AcceptsExprPack), IsTargetSpecific(IsTargetSpecific),
-        IsType(IsType), IsStmt(IsStmt), IsKnownToGCC(IsKnownToGCC),
+        IsType(IsType), IsStmt(IsStmt), IsDecl(IsDecl),
+        IsKnownToGCC(IsKnownToGCC),
         IsSupportedByPragmaAttribute(IsSupportedByPragmaAttribute),
         Spellings(Spellings), ArgNames(ArgNames) {}
 
@@ -1147,6 +1152,14 @@
   ExpectedFunctionWithProtoType,
 };
 
+// TODO: Document
+enum AttributeAppertainsTo {
+  AppertainsToDecl,
+  AppertainsToStmt,
+  AppertainsToType,
+  AppertainsToUnknown,
+};
+
 inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
                                              const ParsedAttr &At) {
   DB.AddTaggedVal(reinterpret_cast<uint64_t>(At.getAttrName()),
Index: clang/include/clang/Parse/Parser.h
===================================================================
--- clang/include/clang/Parse/Parser.h
+++ clang/include/clang/Parse/Parser.h
@@ -2686,30 +2686,34 @@
   /// Such situations should use the specific attribute parsing functionality.
   void ParseAttributes(unsigned WhichAttrKinds,
                        ParsedAttributesWithRange &Attrs,
+                       AttributeAppertainsTo appertainsTo,
                        LateParsedAttrList *LateAttrs = nullptr);
   void ParseAttributes(unsigned WhichAttrKinds, ParsedAttributes &Attrs,
+                       AttributeAppertainsTo appertainsTo,
                        LateParsedAttrList *LateAttrs = nullptr) {
     ParsedAttributesWithRange AttrsWithRange(AttrFactory);
-    ParseAttributes(WhichAttrKinds, AttrsWithRange, LateAttrs);
+    ParseAttributes(WhichAttrKinds, AttrsWithRange, appertainsTo, LateAttrs);
     Attrs.takeAllFrom(AttrsWithRange);
   }
   /// \brief Possibly parse attributes based on what syntaxes are desired,
   /// allowing for the order to vary.
   bool MaybeParseAttributes(unsigned WhichAttrKinds,
                             ParsedAttributesWithRange &Attrs,
+                            AttributeAppertainsTo appertainsTo,
                             LateParsedAttrList *LateAttrs = nullptr) {
     if (Tok.isOneOf(tok::kw___attribute, tok::kw___declspec) ||
         (standardAttributesAllowed() && isCXX11AttributeSpecifier())) {
-      ParseAttributes(WhichAttrKinds, Attrs, LateAttrs);
+      ParseAttributes(WhichAttrKinds, Attrs, appertainsTo, LateAttrs);
       return true;
     }
     return false;
   }
   bool MaybeParseAttributes(unsigned WhichAttrKinds, ParsedAttributes &Attrs,
+                            AttributeAppertainsTo appertainsTo,
                             LateParsedAttrList *LateAttrs = nullptr) {
     if (Tok.isOneOf(tok::kw___attribute, tok::kw___declspec) ||
         (standardAttributesAllowed() && isCXX11AttributeSpecifier())) {
-      ParseAttributes(WhichAttrKinds, Attrs, LateAttrs);
+      ParseAttributes(WhichAttrKinds, Attrs, appertainsTo, LateAttrs);
       return true;
     }
     return false;
@@ -2791,24 +2795,28 @@
   void MaybeParseCXX11Attributes(Declarator &D) {
     if (standardAttributesAllowed() && isCXX11AttributeSpecifier()) {
       ParsedAttributesWithRange attrs(AttrFactory);
-      ParseCXX11Attributes(attrs);
+      // TODO: Is this correct?
+      ParseCXX11Attributes(attrs, AppertainsToDecl);
       D.takeAttributes(attrs, attrs.Range.getEnd());
     }
   }
-  bool MaybeParseCXX11Attributes(ParsedAttributes &attrs) {
+  bool MaybeParseCXX11Attributes(ParsedAttributes &attrs,
+                                 AttributeAppertainsTo appertainsTo) {
     if (standardAttributesAllowed() && isCXX11AttributeSpecifier()) {
       ParsedAttributesWithRange attrsWithRange(AttrFactory);
-      ParseCXX11Attributes(attrsWithRange);
+      ParseCXX11Attributes(attrsWithRange, appertainsTo);
       attrs.takeAllFrom(attrsWithRange);
       return true;
     }
     return false;
   }
   bool MaybeParseCXX11Attributes(ParsedAttributesWithRange &attrs,
+                                 AttributeAppertainsTo appertainsTo,
                                  bool OuterMightBeMessageSend = false) {
     if (standardAttributesAllowed() &&
         isCXX11AttributeSpecifier(false, OuterMightBeMessageSend)) {
-      ParseCXX11Attributes(attrs);
+      // TODO: How to pass?
+      ParseCXX11Attributes(attrs, appertainsTo);
       return true;
     }
     return false;
@@ -2817,16 +2825,24 @@
   void ParseOpenMPAttributeArgs(IdentifierInfo *AttrName,
                                 CachedTokens &OpenMPTokens);
 
+  void DiagnoseAppertainsTo(ParsedAttr &PA, AttributeAppertainsTo appertainsTo);
+  void DiagnoseAppertainsTo(ParsedAttributesView &Attrs,
+                            AttributeAppertainsTo appertainsTo);
+
   void ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs,
                                             CachedTokens &OpenMPTokens,
+                                            AttributeAppertainsTo appertainsTo,
                                             SourceLocation *EndLoc = nullptr);
   void ParseCXX11AttributeSpecifier(ParsedAttributes &Attrs,
+                                    AttributeAppertainsTo appertainsTo,
                                     SourceLocation *EndLoc = nullptr) {
     CachedTokens OpenMPTokens;
-    ParseCXX11AttributeSpecifierInternal(Attrs, OpenMPTokens, EndLoc);
+    ParseCXX11AttributeSpecifierInternal(Attrs, OpenMPTokens, appertainsTo,
+                                         EndLoc);
     ReplayOpenMPAttributeTokens(OpenMPTokens);
   }
-  void ParseCXX11Attributes(ParsedAttributesWithRange &attrs);
+  void ParseCXX11Attributes(ParsedAttributesWithRange &attrs,
+                            AttributeAppertainsTo appertainsTo);
   /// Parses a C++11 (or C2x)-style attribute argument list. Returns true
   /// if this results in adding an attribute to the ParsedAttributes list.
   bool ParseCXX11AttributeArgs(IdentifierInfo *AttrName,
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3357,9 +3357,9 @@
    InGroup<IgnoredAttributes>;
 def note_attribute_has_no_effect_on_compile_time_if_here : Note<
   "annotating the 'if %select{constexpr|consteval}0' statement here">;
-def err_decl_attribute_invalid_on_stmt : Error<
+def err_attribute_invalid_on_stmt : Error<
   "%0 attribute cannot be applied to a statement">;
-def err_stmt_attribute_invalid_on_decl : Error<
+def err_attribute_invalid_on_decl : Error<
   "%0 attribute cannot be applied to a declaration">;
 def err_type_attribute_invalid_on_decl : Error<
   "%0 attribute cannot be applied to a declaration">;
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -2553,7 +2553,7 @@
   let Documentation = [SwiftAsyncErrorDocs];
 }
 
-def Suppress : StmtAttr {
+def Suppress : DeclOrStmtAttr {
   let Spellings = [CXX11<"gsl", "suppress">];
   let Args = [VariadicStringArgument<"DiagnosticIdentifiers">];
   let Documentation = [SuppressDocs];
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to