[clang] [Clang] raise extension warning for unknown namespaced attributes (PR #120925)

Oleksandr T. via cfe-commits cfe-commits at lists.llvm.org
Thu Jan 23 15:16:17 PST 2025


https://github.com/a-tarasyuk updated https://github.com/llvm/llvm-project/pull/120925

>From bce88b1bb464438828fc177c978ad2b99957530f Mon Sep 17 00:00:00 2001
From: Oleksandr T <oleksandr.tarasiuk at outlook.com>
Date: Mon, 23 Dec 2024 02:35:07 +0200
Subject: [PATCH 1/9] [Clang] raise extension warning for unknown namespaced
 attributes

---
 clang/docs/ReleaseNotes.rst                            |  2 ++
 clang/include/clang/Basic/DiagnosticCommonKinds.td     |  2 ++
 clang/lib/Sema/SemaDeclAttr.cpp                        |  2 ++
 .../CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p2-1z.cpp    |  4 ++--
 clang/test/CXX/module/module.interface/p3.cpp          |  2 +-
 clang/test/Lexer/cxx2a-spaceship.cpp                   |  2 +-
 clang/test/OpenMP/openmp_attribute_parsing.cpp         |  2 +-
 clang/test/Parser/c2x-attributes.c                     |  2 +-
 clang/test/Parser/cxx0x-attributes.cpp                 |  2 +-
 clang/test/Sema/patchable-function-entry-attr.cpp      |  2 +-
 clang/test/Sema/unknown-attributes.c                   | 10 ++++++++++
 clang/test/SemaCXX/cxx2a-ms-no-unique-address.cpp      |  4 ++--
 12 files changed, 26 insertions(+), 10 deletions(-)
 create mode 100644 clang/test/Sema/unknown-attributes.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 6b9e1109f3906e..e2cf90aecf3666 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -552,6 +552,8 @@ Attribute Changes in Clang
 - Clang now permits the usage of the placement new operator in ``[[msvc::constexpr]]``
   context outside of the std namespace. (#GH74924)
 
+- Clang now raises warnings for unknown namespaced attributes only in pedantic mode (#GH120875).
+
 Improvements to Clang's diagnostics
 -----------------------------------
 
diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td
index f4a155bb00bb37..85653429aa5332 100644
--- a/clang/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td
@@ -179,6 +179,8 @@ def err_opencl_unknown_type_specifier : Error<
 
 def warn_unknown_attribute_ignored : Warning<
   "unknown attribute %0 ignored">, InGroup<UnknownAttributes>;
+def ext_unknown_attribute_ignored : Extension<
+  "unknown attribute %0 ignored">, InGroup<UnknownAttributes>;
 def warn_attribute_ignored : Warning<"%0 attribute ignored">,
   InGroup<IgnoredAttributes>;
 def err_keyword_not_supported_on_target : Error<
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index bb4d33560b93b8..9b1ffebe0804a5 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -6548,6 +6548,8 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
                ? (unsigned)diag::err_keyword_not_supported_on_target
            : AL.isDeclspecAttribute()
                ? (unsigned)diag::warn_unhandled_ms_attribute_ignored
+           : AL.getScopeName()
+               ? (unsigned)diag::ext_unknown_attribute_ignored
                : (unsigned)diag::warn_unknown_attribute_ignored)
         << AL << AL.getRange();
     return;
diff --git a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p2-1z.cpp b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p2-1z.cpp
index 192fa126109873..c7e66649fb7b22 100644
--- a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p2-1z.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p2-1z.cpp
@@ -12,5 +12,5 @@
 [[using clang:]] extern int n; // ok
 [[using blah: clang::optnone]] extern int n; // expected-error {{attribute with scope specifier cannot follow}} expected-warning {{only applies to functions}}
 
-[[using clang: unknown_attr]] extern int n; // expected-warning {{unknown attribute}}
-[[using unknown_ns: something]] extern int n; // expected-warning {{unknown attribute}}
+[[using clang: unknown_attr]] extern int n;
+[[using unknown_ns: something]] extern int n;
diff --git a/clang/test/CXX/module/module.interface/p3.cpp b/clang/test/CXX/module/module.interface/p3.cpp
index 32819b2dccb11d..3cde92c1a2cf34 100644
--- a/clang/test/CXX/module/module.interface/p3.cpp
+++ b/clang/test/CXX/module/module.interface/p3.cpp
@@ -40,7 +40,7 @@ export { // No diagnostic after P2615R1 DR
   extern "C++" {} // No diagnostic after P2615R1 DR
 }
 export [[]]; // No diagnostic after P2615R1 DR
-export [[example::attr]]; // expected-warning {{unknown attribute 'attr'}}
+export [[example::attr]]; // expected-error {{unknown attribute 'attr'}}
 
 // [...] shall not declare a name with internal linkage
 export static int a; // expected-error {{declaration of 'a' with internal linkage cannot be exported}}
diff --git a/clang/test/Lexer/cxx2a-spaceship.cpp b/clang/test/Lexer/cxx2a-spaceship.cpp
index 2163a0bf190f90..505f2f47c8ffb8 100644
--- a/clang/test/Lexer/cxx2a-spaceship.cpp
+++ b/clang/test/Lexer/cxx2a-spaceship.cpp
@@ -61,7 +61,7 @@ static_assert(__builtin_strcmp(b, "<=>") == 0);
 // CXX20: preprocess8: <=>=
 
 #define ID(x) x
-[[some_vendor::some_attribute( // expected-warning {{unknown attribute}}
+[[some_vendor::some_attribute(
 preprocess1: ID(<)ID(=>),
 preprocess2: ID(<=)ID(>),
 preprocess3: ID(<)ID(=)ID(>),
diff --git a/clang/test/OpenMP/openmp_attribute_parsing.cpp b/clang/test/OpenMP/openmp_attribute_parsing.cpp
index e273702dfadcb3..4a3a885e407a75 100644
--- a/clang/test/OpenMP/openmp_attribute_parsing.cpp
+++ b/clang/test/OpenMP/openmp_attribute_parsing.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++17 -fopenmp -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++17 -Wunknown-attributes -fopenmp -fsyntax-only -verify %s
 
 // This file tests the custom parsing logic for the OpenMP 5.1 attribute
 // syntax. It does not test actual OpenMP directive syntax, just the attribute
diff --git a/clang/test/Parser/c2x-attributes.c b/clang/test/Parser/c2x-attributes.c
index be039e40f98ef1..30653e2e6f67a6 100644
--- a/clang/test/Parser/c2x-attributes.c
+++ b/clang/test/Parser/c2x-attributes.c
@@ -133,7 +133,7 @@ void f11(void) {
 }
 
 [[attr]] void f12(void); // expected-warning {{unknown attribute 'attr' ignored}}
-[[vendor::attr]] void f13(void); // expected-warning {{unknown attribute 'attr' ignored}}
+[[vendor::attr]] void f13(void);
 
 // Ensure that asm statements properly handle double colons.
 void test_asm(void) {
diff --git a/clang/test/Parser/cxx0x-attributes.cpp b/clang/test/Parser/cxx0x-attributes.cpp
index fad3010c98b9c2..41e4ac4907ef54 100644
--- a/clang/test/Parser/cxx0x-attributes.cpp
+++ b/clang/test/Parser/cxx0x-attributes.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fcxx-exceptions -fdeclspec -fexceptions -fsyntax-only -verify -std=c++11 -Wc++14-compat -Wc++14-extensions -Wc++17-extensions %s
+// RUN: %clang_cc1 -fcxx-exceptions -fdeclspec -fexceptions -fsyntax-only -verify -std=c++11 -Wc++14-compat -Wc++14-extensions -Wc++17-extensions -Wunknown-attributes %s
 
 // Need std::initializer_list
 namespace std {
diff --git a/clang/test/Sema/patchable-function-entry-attr.cpp b/clang/test/Sema/patchable-function-entry-attr.cpp
index bd4d57a7e30936..8c988b453749e9 100644
--- a/clang/test/Sema/patchable-function-entry-attr.cpp
+++ b/clang/test/Sema/patchable-function-entry-attr.cpp
@@ -8,7 +8,7 @@
 // RUN: %clang_cc1 -triple riscv64 -fsyntax-only -verify=silence %s
 // RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu -fsyntax-only -verify=silence %s
 // RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -fsyntax-only -verify=silence %s
-// RUN: %clang_cc1 -triple ppc64le -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple ppc64le -fsyntax-only -verify=silence %s
 // RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -fsyntax-only -verify=AIX %s
 // RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -fsyntax-only -verify=AIX %s
 
diff --git a/clang/test/Sema/unknown-attributes.c b/clang/test/Sema/unknown-attributes.c
new file mode 100644
index 00000000000000..26fa0258302a38
--- /dev/null
+++ b/clang/test/Sema/unknown-attributes.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c23 -verify=pedantic -pedantic %s
+// RUN: %clang_cc1 -fsyntax-only -std=c23 -verify %s
+
+// expected-no-diagnostics
+
+[[unknown::a(b((c)) d(e((f)))), unknown::g(h k)]] // pedantic-warning {{unknown attribute 'a' ignored}} \
+                                                  // pedantic-warning {{unknown attribute 'g' ignored}}
+int main(void) {
+    return 0;
+}
diff --git a/clang/test/SemaCXX/cxx2a-ms-no-unique-address.cpp b/clang/test/SemaCXX/cxx2a-ms-no-unique-address.cpp
index 822ed752fa9c75..90c814a6a7774a 100644
--- a/clang/test/SemaCXX/cxx2a-ms-no-unique-address.cpp
+++ b/clang/test/SemaCXX/cxx2a-ms-no-unique-address.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -std=c++2a %s -verify=unsupported -triple x86_64-linux-gnu
-// RUN: %clang_cc1 -std=c++2a %s -verify -triple x86_64-windows -fms-compatibility
+// RUN: %clang_cc1 -std=c++2a %s -verify=unsupported -triple x86_64-linux-gnu -Wunknown-attributes
+// RUN: %clang_cc1 -std=c++2a %s -verify -triple x86_64-windows -fms-compatibility -Wunknown-attributes
 
 [[msvc::no_unique_address]] int a; // expected-error {{only applies to non-bit-field non-static data members}} unsupported-warning {{unknown}}
 [[msvc::no_unique_address]] void f(); // expected-error {{only applies to non-bit-field non-static data members}} unsupported-warning {{unknown}}

>From 83eac2ed3b8679da9fc6d65f4f36f91b61666bb7 Mon Sep 17 00:00:00 2001
From: Oleksandr T <oleksandr.tarasiuk at outlook.com>
Date: Mon, 23 Dec 2024 14:32:04 +0200
Subject: [PATCH 2/9] fix formatting

---
 clang/lib/Sema/SemaDeclAttr.cpp | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 9b1ffebe0804a5..520508a2c9dff6 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -6548,9 +6548,8 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
                ? (unsigned)diag::err_keyword_not_supported_on_target
            : AL.isDeclspecAttribute()
                ? (unsigned)diag::warn_unhandled_ms_attribute_ignored
-           : AL.getScopeName()
-               ? (unsigned)diag::ext_unknown_attribute_ignored
-               : (unsigned)diag::warn_unknown_attribute_ignored)
+           : AL.getScopeName() ? (unsigned)diag::ext_unknown_attribute_ignored
+                               : (unsigned)diag::warn_unknown_attribute_ignored)
         << AL << AL.getRange();
     return;
   }

>From 4b1baec265612a5b347c064eee4cb18856a7a457 Mon Sep 17 00:00:00 2001
From: Oleksandr T <oleksandr.tarasiuk at outlook.com>
Date: Fri, 3 Jan 2025 03:19:23 +0200
Subject: [PATCH 3/9] check attrs in known scopes

---
 .../include/clang/Basic/AttributeCommonInfo.h  |  2 ++
 .../clang/Basic/DiagnosticCommonKinds.td       |  2 --
 clang/lib/Basic/Attributes.cpp                 |  8 +++++++-
 clang/lib/Sema/SemaDeclAttr.cpp                | 18 ++++++++++--------
 .../dcl.attr/dcl.attr.grammar/p2-1z.cpp        |  2 +-
 clang/test/CXX/module/module.interface/p3.cpp  |  2 +-
 clang/test/Parser/cxx0x-attributes.cpp         |  7 +++----
 .../Sema/patchable-function-entry-attr.cpp     |  2 +-
 clang/test/Sema/unknown-attributes.c           | 12 +++++++-----
 9 files changed, 32 insertions(+), 23 deletions(-)

diff --git a/clang/include/clang/Basic/AttributeCommonInfo.h b/clang/include/clang/Basic/AttributeCommonInfo.h
index 11c64547721739..c08e3b2a6a6155 100644
--- a/clang/include/clang/Basic/AttributeCommonInfo.h
+++ b/clang/include/clang/Basic/AttributeCommonInfo.h
@@ -241,6 +241,8 @@ class AttributeCommonInfo {
   static Kind getParsedKind(const IdentifierInfo *Name,
                             const IdentifierInfo *Scope, Syntax SyntaxUsed);
 
+  bool isKnownScopeName() const;
+
 private:
   /// Get an index into the attribute spelling list
   /// defined in Attr.td. This index is used by an attribute
diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td
index 85653429aa5332..f4a155bb00bb37 100644
--- a/clang/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td
@@ -179,8 +179,6 @@ def err_opencl_unknown_type_specifier : Error<
 
 def warn_unknown_attribute_ignored : Warning<
   "unknown attribute %0 ignored">, InGroup<UnknownAttributes>;
-def ext_unknown_attribute_ignored : Extension<
-  "unknown attribute %0 ignored">, InGroup<UnknownAttributes>;
 def warn_attribute_ignored : Warning<"%0 attribute ignored">,
   InGroup<IgnoredAttributes>;
 def err_keyword_not_supported_on_target : Error<
diff --git a/clang/lib/Basic/Attributes.cpp b/clang/lib/Basic/Attributes.cpp
index fa26cc584b724a..640c3d54fce3ee 100644
--- a/clang/lib/Basic/Attributes.cpp
+++ b/clang/lib/Basic/Attributes.cpp
@@ -166,7 +166,8 @@ getScopeFromNormalizedScopeName(StringRef ScopeName) {
       .Case("hlsl", AttributeCommonInfo::Scope::HLSL)
       .Case("msvc", AttributeCommonInfo::Scope::MSVC)
       .Case("omp", AttributeCommonInfo::Scope::OMP)
-      .Case("riscv", AttributeCommonInfo::Scope::RISCV);
+      .Case("riscv", AttributeCommonInfo::Scope::RISCV)
+      .Default(AttributeCommonInfo::Scope::NONE);
 }
 
 unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const {
@@ -181,3 +182,8 @@ unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const {
 
 #include "clang/Sema/AttrSpellingListIndex.inc"
 }
+
+bool AttributeCommonInfo::isKnownScopeName() const {
+  return getScopeFromNormalizedScopeName(normalizeAttrScopeName(
+             getScopeName(), getSyntax())) != AttributeCommonInfo::Scope::NONE;
+}
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 520508a2c9dff6..229c1832bea405 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -6543,14 +6543,16 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
   // though they were unknown attributes.
   if (AL.getKind() == ParsedAttr::UnknownAttribute ||
       !AL.existsInTarget(S.Context.getTargetInfo())) {
-    S.Diag(AL.getLoc(),
-           AL.isRegularKeywordAttribute()
-               ? (unsigned)diag::err_keyword_not_supported_on_target
-           : AL.isDeclspecAttribute()
-               ? (unsigned)diag::warn_unhandled_ms_attribute_ignored
-           : AL.getScopeName() ? (unsigned)diag::ext_unknown_attribute_ignored
-                               : (unsigned)diag::warn_unknown_attribute_ignored)
-        << AL << AL.getRange();
+
+    unsigned DiagID = diag::warn_unknown_attribute_ignored;
+    if (AL.isRegularKeywordAttribute())
+      DiagID = diag::err_keyword_not_supported_on_target;
+    else if (AL.isDeclspecAttribute())
+      DiagID = diag::warn_unhandled_ms_attribute_ignored;
+    else if (AL.getScopeName() && !AL.isKnownScopeName())
+      return;
+
+    S.Diag(AL.getLoc(), DiagID) << AL << AL.getRange();
     return;
   }
 
diff --git a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p2-1z.cpp b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p2-1z.cpp
index c7e66649fb7b22..b44ffba8f2fc35 100644
--- a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p2-1z.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p2-1z.cpp
@@ -12,5 +12,5 @@
 [[using clang:]] extern int n; // ok
 [[using blah: clang::optnone]] extern int n; // expected-error {{attribute with scope specifier cannot follow}} expected-warning {{only applies to functions}}
 
-[[using clang: unknown_attr]] extern int n;
+[[using clang: unknown_attr]] extern int n; // expected-warning {{unknown attribute 'unknown_attr' ignored}}
 [[using unknown_ns: something]] extern int n;
diff --git a/clang/test/CXX/module/module.interface/p3.cpp b/clang/test/CXX/module/module.interface/p3.cpp
index 3cde92c1a2cf34..b7ff925e165991 100644
--- a/clang/test/CXX/module/module.interface/p3.cpp
+++ b/clang/test/CXX/module/module.interface/p3.cpp
@@ -40,7 +40,7 @@ export { // No diagnostic after P2615R1 DR
   extern "C++" {} // No diagnostic after P2615R1 DR
 }
 export [[]]; // No diagnostic after P2615R1 DR
-export [[example::attr]]; // expected-error {{unknown attribute 'attr'}}
+export [[example::attr]];
 
 // [...] shall not declare a name with internal linkage
 export static int a; // expected-error {{declaration of 'a' with internal linkage cannot be exported}}
diff --git a/clang/test/Parser/cxx0x-attributes.cpp b/clang/test/Parser/cxx0x-attributes.cpp
index 41e4ac4907ef54..fd4bcc6bfc5078 100644
--- a/clang/test/Parser/cxx0x-attributes.cpp
+++ b/clang/test/Parser/cxx0x-attributes.cpp
@@ -46,15 +46,14 @@ int & [[noreturn]] ref_attr_3 = after_attr; // expected-error {{'noreturn' attri
 int && [[]] rref_attr = 0;
 int array_attr [1] [[]];
 alignas(8) int aligned_attr;
-[[test::valid(for 42 [very] **** '+' symbols went on a trip and had a "good"_time; the end.)]] int garbage_attr; // expected-warning {{unknown attribute 'valid' ignored}}
+[[test::valid(for 42 [very] **** '+' symbols went on a trip and had a "good"_time; the end.)]] int garbage_attr;
 [[,,,static, class, namespace,, inline, constexpr, mutable,, bitand, bitor::compl(!.*_ Cx.!U^*R),,,]] int more_garbage_attr; // expected-warning {{unknown attribute 'static' ignored}} \
     // expected-warning {{unknown attribute 'class' ignored}} \
     // expected-warning {{unknown attribute 'namespace' ignored}} \
     // expected-warning {{unknown attribute 'inline' ignored}} \
     // expected-warning {{unknown attribute 'constexpr' ignored}} \
     // expected-warning {{unknown attribute 'mutable' ignored}} \
-    // expected-warning {{unknown attribute 'bitand' ignored}} \
-    // expected-warning {{unknown attribute 'compl' ignored}}
+    // expected-warning {{unknown attribute 'bitand' ignored}}
 [[u8"invalid!"]] int invalid_string_attr; // expected-error {{expected ']'}}
 void fn_attr () [[]];
 void noexcept_fn_attr () noexcept [[]];
@@ -269,7 +268,7 @@ template <int... Is> void variadic_nttp() {
   void baz [[clang::no_sanitize(Is...)]] ();          // expected-error {{expected string literal as argument of 'no_sanitize' attribute}}
   void bor [[clang::annotate("A", "V" ...)]] ();      // expected-error {{pack expansion does not contain any unexpanded parameter packs}}
   void bir [[clang::annotate("B", {1, 2, 3, 4})]] (); // expected-error {{'annotate' attribute requires parameter 1 to be a constant expression}} expected-note {{subexpression not valid in a constant expression}}
-  void boo [[unknown::foo(Is...)]] ();                // expected-warning {{unknown attribute 'foo' ignored}}
+  void boo [[unknown::foo(Is...)]] ();
   void faz [[clang::annotate("C", (Is + ...))]] ();   // expected-warning {{pack fold expression is a C++17 extension}}
   void far [[clang::annotate("D", Is...)]] ();
   void foz [[clang::annotate("E", 1, 2, 3, Is...)]] ();
diff --git a/clang/test/Sema/patchable-function-entry-attr.cpp b/clang/test/Sema/patchable-function-entry-attr.cpp
index 8c988b453749e9..bd4d57a7e30936 100644
--- a/clang/test/Sema/patchable-function-entry-attr.cpp
+++ b/clang/test/Sema/patchable-function-entry-attr.cpp
@@ -8,7 +8,7 @@
 // RUN: %clang_cc1 -triple riscv64 -fsyntax-only -verify=silence %s
 // RUN: %clang_cc1 -triple powerpc-unknown-linux-gnu -fsyntax-only -verify=silence %s
 // RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -fsyntax-only -verify=silence %s
-// RUN: %clang_cc1 -triple ppc64le -fsyntax-only -verify=silence %s
+// RUN: %clang_cc1 -triple ppc64le -fsyntax-only -verify %s
 // RUN: %clang_cc1 -triple powerpc64-ibm-aix-xcoff -fsyntax-only -verify=AIX %s
 // RUN: %clang_cc1 -triple powerpc-ibm-aix-xcoff -fsyntax-only -verify=AIX %s
 
diff --git a/clang/test/Sema/unknown-attributes.c b/clang/test/Sema/unknown-attributes.c
index 26fa0258302a38..a232653ac4ac8d 100644
--- a/clang/test/Sema/unknown-attributes.c
+++ b/clang/test/Sema/unknown-attributes.c
@@ -1,10 +1,12 @@
-// RUN: %clang_cc1 -fsyntax-only -std=c23 -verify=pedantic -pedantic %s
 // RUN: %clang_cc1 -fsyntax-only -std=c23 -verify %s
 
-// expected-no-diagnostics
+[[unknown::a(b((c)) d(e((f)))), unknown::g(h k)]]
+int a(void) {
+    return 0;
+}
 
-[[unknown::a(b((c)) d(e((f)))), unknown::g(h k)]] // pedantic-warning {{unknown attribute 'a' ignored}} \
-                                                  // pedantic-warning {{unknown attribute 'g' ignored}}
-int main(void) {
+[[clang::a(b((c)) d(e((f)))), clang::g(h k)]] // expected-warning {{unknown attribute 'a' ignored}} \
+                                              // expected-warning {{unknown attribute 'g' ignored}}
+int b(void) {
     return 0;
 }

>From 802efe62d65e14608471adfffaf0e686ecfeb81d Mon Sep 17 00:00:00 2001
From: Oleksandr T <oleksandr.tarasiuk at outlook.com>
Date: Wed, 22 Jan 2025 14:05:43 +0200
Subject: [PATCH 4/9] add unknown-attribute-namespace option to specify allowed
 unknown attribute names

---
 clang/include/clang/Basic/DiagnosticGroups.td |  3 +-
 clang/include/clang/Basic/DiagnosticOptions.h |  5 ++++
 clang/include/clang/Driver/Options.td         |  5 ++++
 clang/lib/Frontend/CompilerInvocation.cpp     |  3 ++
 clang/lib/Sema/SemaDeclAttr.cpp               |  9 ++++--
 .../DependencyScanning/ModuleDepCollector.cpp |  1 +
 .../dcl.attr/dcl.attr.grammar/p2-1z.cpp       |  4 +--
 clang/test/CXX/module/module.interface/p3.cpp |  2 +-
 clang/test/Lexer/cxx2a-spaceship.cpp          |  4 +--
 .../test/OpenMP/openmp_attribute_parsing.cpp  |  2 +-
 clang/test/Parser/c2x-attributes.c            |  2 +-
 clang/test/Parser/cxx0x-attributes.cpp        |  7 +++--
 clang/test/Sema/unknown-attributes.c          | 29 +++++++++++++++----
 .../SemaCXX/cxx2a-ms-no-unique-address.cpp    |  4 +--
 14 files changed, 59 insertions(+), 21 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 3ac490d30371b1..87ba45f6d15ae5 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -820,8 +820,9 @@ def NSobjectAttribute : DiagGroup<"NSObject-attribute">;
 def NSConsumedMismatch : DiagGroup<"nsconsumed-mismatch">;
 def NSReturnsMismatch : DiagGroup<"nsreturns-mismatch">;
 
+def UnknownAttributeNamespace : DiagGroup<"unknown-attribute-namespace">;
 def IndependentClassAttribute : DiagGroup<"IndependentClass-attribute">;
-def UnknownAttributes : DiagGroup<"unknown-attributes">;
+def UnknownAttributes : DiagGroup<"unknown-attributes", [UnknownAttributeNamespace]>;
 def IgnoredAttributes : DiagGroup<"ignored-attributes">;
 def Attributes : DiagGroup<"attributes", [UnknownAttributes,
                                           IgnoredAttributes]>;
diff --git a/clang/include/clang/Basic/DiagnosticOptions.h b/clang/include/clang/Basic/DiagnosticOptions.h
index e2faf3d0df95cb..864e7ee1535473 100644
--- a/clang/include/clang/Basic/DiagnosticOptions.h
+++ b/clang/include/clang/Basic/DiagnosticOptions.h
@@ -131,6 +131,11 @@ class DiagnosticOptions : public RefCountedBase<DiagnosticOptions>{
   /// whether -Wsystem-headers is enabled on a per-module basis.
   std::vector<std::string> SystemHeaderWarningsModules;
 
+  /// The list of namespaces from -Wunknown-attribute-namespace=... used to
+  /// specify the allowed unknown attribute namespaces. Any attribute namespace
+  /// not in this list will trigger a warning.
+  std::vector<std::string> UnknownAttributeNamespaces;
+
 public:
   // Define accessors/mutators for diagnostic options of enumeration type.
 #define DIAGOPT(Name, Bits, Default)
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 9e81c39f6869bd..b418cb87d682bc 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1114,6 +1114,11 @@ defm cx_fortran_rules: BoolOptionWithoutMarshalling<"f", "cx-fortran-rules",
   NegFlag<SetFalse, [], [ClangOption, CC1Option], "Range reduction is disabled "
   "for complex arithmetic operations">>;
 
+def Wunknown_attribute_namespace_EQ : CommaJoined<["-"], "Wunknown-attribute-namespace=">,
+  Group<W_value_Group>, Flags<[HelpHidden]>, Visibility<[ClangOption, CC1Option]>,
+  HelpText<"Specify a comma-separated list of allowed unknown attribute namespaces">,
+  MarshallingInfoStringVector<DiagnosticOpts<"UnknownAttributeNamespaces">>;
+
 // OpenCL-only Options
 def cl_opt_disable : Flag<["-"], "cl-opt-disable">, Group<opencl_Group>,
   Visibility<[ClangOption, CC1Option]>,
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 348c56cc37da3f..30b0ee0cdb70de 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -2539,6 +2539,9 @@ void CompilerInvocationBase::GenerateDiagnosticArgs(
     // This option is automatically generated from CheckConstexprFunctionBodies.
     if (Warning == "invalid-constexpr" || Warning == "no-invalid-constexpr")
       continue;
+    // This option is automatically generated from UnknownAttributeNamespaces.
+    if (Warning == "unknown-attribute-namespace")
+      continue;
     Consumer(StringRef("-W") + Warning);
   }
 
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 229c1832bea405..2ef04ef37f274f 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -6549,8 +6549,13 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
       DiagID = diag::err_keyword_not_supported_on_target;
     else if (AL.isDeclspecAttribute())
       DiagID = diag::warn_unhandled_ms_attribute_ignored;
-    else if (AL.getScopeName() && !AL.isKnownScopeName())
-      return;
+    else if (AL.hasScope() && !AL.isKnownScopeName()) {
+      const std::vector<std::string> UnknownAttributeNamespaces =
+          S.getDiagnostics().getDiagnosticOptions().UnknownAttributeNamespaces;
+      if (llvm::is_contained(UnknownAttributeNamespaces,
+                             AL.getScopeName()->getName()))
+        return;
+    }
 
     S.Diag(AL.getLoc(), DiagID) << AL << AL.getRange();
     return;
diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
index 2e97cac0796cee..7bdc7634c3801e 100644
--- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
+++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
@@ -127,6 +127,7 @@ static void optimizeDiagnosticOpts(DiagnosticOptions &Opts,
   Opts.Warnings.clear();
   Opts.UndefPrefixes.clear();
   Opts.Remarks.clear();
+  Opts.UnknownAttributeNamespaces.clear();
 }
 
 static std::vector<std::string> splitString(std::string S, char Separator) {
diff --git a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p2-1z.cpp b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p2-1z.cpp
index b44ffba8f2fc35..fcb6170905f7b3 100644
--- a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p2-1z.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p2-1z.cpp
@@ -12,5 +12,5 @@
 [[using clang:]] extern int n; // ok
 [[using blah: clang::optnone]] extern int n; // expected-error {{attribute with scope specifier cannot follow}} expected-warning {{only applies to functions}}
 
-[[using clang: unknown_attr]] extern int n; // expected-warning {{unknown attribute 'unknown_attr' ignored}}
-[[using unknown_ns: something]] extern int n;
+[[using clang: unknown_attr]] extern int n;   // expected-warning {{unknown attribute 'unknown_attr' ignored}}
+[[using unknown_ns: something]] extern int n; // expected-warning {{unknown attribute 'something' ignored}}
diff --git a/clang/test/CXX/module/module.interface/p3.cpp b/clang/test/CXX/module/module.interface/p3.cpp
index b7ff925e165991..28826e435b1290 100644
--- a/clang/test/CXX/module/module.interface/p3.cpp
+++ b/clang/test/CXX/module/module.interface/p3.cpp
@@ -40,7 +40,7 @@ export { // No diagnostic after P2615R1 DR
   extern "C++" {} // No diagnostic after P2615R1 DR
 }
 export [[]]; // No diagnostic after P2615R1 DR
-export [[example::attr]];
+export [[example::attr]]; // expected-warning {{unknown attribute 'attr' ignored}}
 
 // [...] shall not declare a name with internal linkage
 export static int a; // expected-error {{declaration of 'a' with internal linkage cannot be exported}}
diff --git a/clang/test/Lexer/cxx2a-spaceship.cpp b/clang/test/Lexer/cxx2a-spaceship.cpp
index 505f2f47c8ffb8..396bb7479366e3 100644
--- a/clang/test/Lexer/cxx2a-spaceship.cpp
+++ b/clang/test/Lexer/cxx2a-spaceship.cpp
@@ -61,13 +61,13 @@ static_assert(__builtin_strcmp(b, "<=>") == 0);
 // CXX20: preprocess8: <=>=
 
 #define ID(x) x
-[[some_vendor::some_attribute(
+[[some_vendor::some_attribute( // expected-warning {{unknown attribute 'some_attribute' ignored}}
 preprocess1: ID(<)ID(=>),
 preprocess2: ID(<=)ID(>),
 preprocess3: ID(<)ID(=)ID(>),
 preprocess4: ID(<=)ID(>=),
 preprocess5: ID(<=)ID(>>),
 preprocess6: ID(<=)ID(>>=),
-preprocess7: ID(<=>) // expected-warning 0-1{{'<=>'}}
+preprocess7: ID(<=>)  // expected-warning 0-1{{'<=>'}}
 preprocess8: ID(<=>=) // expected-warning 0-1{{'<=>'}}
 )]];
diff --git a/clang/test/OpenMP/openmp_attribute_parsing.cpp b/clang/test/OpenMP/openmp_attribute_parsing.cpp
index 4a3a885e407a75..e273702dfadcb3 100644
--- a/clang/test/OpenMP/openmp_attribute_parsing.cpp
+++ b/clang/test/OpenMP/openmp_attribute_parsing.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++17 -Wunknown-attributes -fopenmp -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++17 -fopenmp -fsyntax-only -verify %s
 
 // This file tests the custom parsing logic for the OpenMP 5.1 attribute
 // syntax. It does not test actual OpenMP directive syntax, just the attribute
diff --git a/clang/test/Parser/c2x-attributes.c b/clang/test/Parser/c2x-attributes.c
index 30653e2e6f67a6..be039e40f98ef1 100644
--- a/clang/test/Parser/c2x-attributes.c
+++ b/clang/test/Parser/c2x-attributes.c
@@ -133,7 +133,7 @@ void f11(void) {
 }
 
 [[attr]] void f12(void); // expected-warning {{unknown attribute 'attr' ignored}}
-[[vendor::attr]] void f13(void);
+[[vendor::attr]] void f13(void); // expected-warning {{unknown attribute 'attr' ignored}}
 
 // Ensure that asm statements properly handle double colons.
 void test_asm(void) {
diff --git a/clang/test/Parser/cxx0x-attributes.cpp b/clang/test/Parser/cxx0x-attributes.cpp
index fd4bcc6bfc5078..d9fdedc3ab6d62 100644
--- a/clang/test/Parser/cxx0x-attributes.cpp
+++ b/clang/test/Parser/cxx0x-attributes.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fcxx-exceptions -fdeclspec -fexceptions -fsyntax-only -verify -std=c++11 -Wc++14-compat -Wc++14-extensions -Wc++17-extensions -Wunknown-attributes %s
+// RUN: %clang_cc1 -fcxx-exceptions -fdeclspec -fexceptions -fsyntax-only -verify -std=c++11 -Wc++14-compat -Wc++14-extensions -Wc++17-extensions %s
 
 // Need std::initializer_list
 namespace std {
@@ -46,8 +46,9 @@ int & [[noreturn]] ref_attr_3 = after_attr; // expected-error {{'noreturn' attri
 int && [[]] rref_attr = 0;
 int array_attr [1] [[]];
 alignas(8) int aligned_attr;
-[[test::valid(for 42 [very] **** '+' symbols went on a trip and had a "good"_time; the end.)]] int garbage_attr;
+[[test::valid(for 42 [very] **** '+' symbols went on a trip and had a "good"_time; the end.)]] int garbage_attr; // expected-warning {{unknown attribute 'valid' ignored}}
 [[,,,static, class, namespace,, inline, constexpr, mutable,, bitand, bitor::compl(!.*_ Cx.!U^*R),,,]] int more_garbage_attr; // expected-warning {{unknown attribute 'static' ignored}} \
+    // expected-warning {{unknown attribute 'compl' ignored}} \
     // expected-warning {{unknown attribute 'class' ignored}} \
     // expected-warning {{unknown attribute 'namespace' ignored}} \
     // expected-warning {{unknown attribute 'inline' ignored}} \
@@ -268,7 +269,7 @@ template <int... Is> void variadic_nttp() {
   void baz [[clang::no_sanitize(Is...)]] ();          // expected-error {{expected string literal as argument of 'no_sanitize' attribute}}
   void bor [[clang::annotate("A", "V" ...)]] ();      // expected-error {{pack expansion does not contain any unexpanded parameter packs}}
   void bir [[clang::annotate("B", {1, 2, 3, 4})]] (); // expected-error {{'annotate' attribute requires parameter 1 to be a constant expression}} expected-note {{subexpression not valid in a constant expression}}
-  void boo [[unknown::foo(Is...)]] ();
+  void boo [[unknown::foo(Is...)]] ();                // expected-warning {{unknown attribute 'foo' ignored}}
   void faz [[clang::annotate("C", (Is + ...))]] ();   // expected-warning {{pack fold expression is a C++17 extension}}
   void far [[clang::annotate("D", Is...)]] ();
   void foz [[clang::annotate("E", 1, 2, 3, Is...)]] ();
diff --git a/clang/test/Sema/unknown-attributes.c b/clang/test/Sema/unknown-attributes.c
index a232653ac4ac8d..16e1032d94ce60 100644
--- a/clang/test/Sema/unknown-attributes.c
+++ b/clang/test/Sema/unknown-attributes.c
@@ -1,12 +1,29 @@
-// RUN: %clang_cc1 -fsyntax-only -std=c23 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wunknown-attribute-namespace=foo,bar -std=c23 -verify %s
 
-[[unknown::a(b((c)) d(e((f)))), unknown::g(h k)]]
-int a(void) {
-    return 0;
+[[foo::a(b((c)) d(e((f)))), foo::g(h k)]]
+int f1(void) {
+  return 0;
 }
 
+[[bar::a(b((c)) d(e((f)))), bar::g(h k)]]
+int f2(void) {
+  return 0;
+}
+
+[[baz::a(b((c)) d(e((f)))), baz::g(h k)]] // expected-warning {{unknown attribute 'a' ignored}} \
+                                          // expected-warning {{unknown attribute 'g' ignored}}
+int f3(void) {
+  return 0;
+}
+
+
 [[clang::a(b((c)) d(e((f)))), clang::g(h k)]] // expected-warning {{unknown attribute 'a' ignored}} \
                                               // expected-warning {{unknown attribute 'g' ignored}}
-int b(void) {
-    return 0;
+int f4(void) {
+  return 0;
+}
+
+[[clang::noinline]]
+int f5(void) {
+  return 0;
 }
diff --git a/clang/test/SemaCXX/cxx2a-ms-no-unique-address.cpp b/clang/test/SemaCXX/cxx2a-ms-no-unique-address.cpp
index 90c814a6a7774a..822ed752fa9c75 100644
--- a/clang/test/SemaCXX/cxx2a-ms-no-unique-address.cpp
+++ b/clang/test/SemaCXX/cxx2a-ms-no-unique-address.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -std=c++2a %s -verify=unsupported -triple x86_64-linux-gnu -Wunknown-attributes
-// RUN: %clang_cc1 -std=c++2a %s -verify -triple x86_64-windows -fms-compatibility -Wunknown-attributes
+// RUN: %clang_cc1 -std=c++2a %s -verify=unsupported -triple x86_64-linux-gnu
+// RUN: %clang_cc1 -std=c++2a %s -verify -triple x86_64-windows -fms-compatibility
 
 [[msvc::no_unique_address]] int a; // expected-error {{only applies to non-bit-field non-static data members}} unsupported-warning {{unknown}}
 [[msvc::no_unique_address]] void f(); // expected-error {{only applies to non-bit-field non-static data members}} unsupported-warning {{unknown}}

>From d87fc6c980b5a703d2bdfdad4902faf6228409fa Mon Sep 17 00:00:00 2001
From: Oleksandr T <oleksandr.tarasiuk at outlook.com>
Date: Thu, 23 Jan 2025 00:18:19 +0200
Subject: [PATCH 5/9] rename option and add new diagnostic message

---
 .../include/clang/Basic/AttributeCommonInfo.h |  4 ++--
 .../clang/Basic/DiagnosticCommonKinds.td      |  3 +++
 clang/include/clang/Basic/DiagnosticGroups.td |  4 ++--
 clang/include/clang/Driver/Options.td         |  4 ++--
 clang/lib/Basic/Attributes.cpp                |  9 ++++----
 clang/lib/Frontend/CompilerInvocation.cpp     |  2 +-
 clang/lib/Sema/SemaDeclAttr.cpp               | 23 ++++++++++++-------
 .../dcl.attr/dcl.attr.grammar/p2-1z.cpp       |  2 +-
 clang/test/CXX/module/module.interface/p3.cpp |  2 +-
 clang/test/Lexer/cxx2a-spaceship.cpp          |  2 +-
 clang/test/Parser/c2x-attributes.c            |  2 +-
 clang/test/Parser/cxx0x-attributes.cpp        |  6 ++---
 clang/test/Sema/unknown-attributes.c          | 14 +++++++----
 13 files changed, 46 insertions(+), 31 deletions(-)

diff --git a/clang/include/clang/Basic/AttributeCommonInfo.h b/clang/include/clang/Basic/AttributeCommonInfo.h
index c08e3b2a6a6155..30c44cd0600456 100644
--- a/clang/include/clang/Basic/AttributeCommonInfo.h
+++ b/clang/include/clang/Basic/AttributeCommonInfo.h
@@ -67,7 +67,7 @@ class AttributeCommonInfo {
     IgnoredAttribute,
     UnknownAttribute,
   };
-  enum class Scope { NONE, CLANG, GNU, MSVC, OMP, HLSL, GSL, RISCV };
+  enum class Scope { NONE, CLANG, GNU, MSVC, OMP, HLSL, GSL, RISCV, UNKNOWN };
 
 private:
   const IdentifierInfo *AttrName = nullptr;
@@ -241,7 +241,7 @@ class AttributeCommonInfo {
   static Kind getParsedKind(const IdentifierInfo *Name,
                             const IdentifierInfo *Scope, Syntax SyntaxUsed);
 
-  bool isKnownScopeName() const;
+  bool isUnknownScopeName() const;
 
 private:
   /// Get an index into the attribute spelling list
diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td b/clang/include/clang/Basic/DiagnosticCommonKinds.td
index f4a155bb00bb37..4968f50858a431 100644
--- a/clang/include/clang/Basic/DiagnosticCommonKinds.td
+++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td
@@ -177,6 +177,9 @@ def err_opencl_unknown_type_specifier : Error<
   "%0 does not support the '%1' "
   "%select{type qualifier|storage class specifier}2">;
 
+def warn_unknown_attribute_namespace : Warning<
+  "unknown attribute namespace '%0'; attribute '%0::%1' ignored">,
+  InGroup<UnknownAttributeNamespaces>;
 def warn_unknown_attribute_ignored : Warning<
   "unknown attribute %0 ignored">, InGroup<UnknownAttributes>;
 def warn_attribute_ignored : Warning<"%0 attribute ignored">,
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index bf219fcb11d45a..bb599427dd826b 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -822,9 +822,9 @@ def NSobjectAttribute : DiagGroup<"NSObject-attribute">;
 def NSConsumedMismatch : DiagGroup<"nsconsumed-mismatch">;
 def NSReturnsMismatch : DiagGroup<"nsreturns-mismatch">;
 
-def UnknownAttributeNamespace : DiagGroup<"unknown-attribute-namespace">;
+def UnknownAttributeNamespaces : DiagGroup<"unknown-attribute-namespaces">;
 def IndependentClassAttribute : DiagGroup<"IndependentClass-attribute">;
-def UnknownAttributes : DiagGroup<"unknown-attributes", [UnknownAttributeNamespace]>;
+def UnknownAttributes : DiagGroup<"unknown-attributes">;
 def IgnoredAttributes : DiagGroup<"ignored-attributes">;
 def Attributes : DiagGroup<"attributes", [UnknownAttributes,
                                           IgnoredAttributes]>;
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 6ec6bcda93b440..b9bd98a716091e 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1115,8 +1115,8 @@ defm cx_fortran_rules: BoolOptionWithoutMarshalling<"f", "cx-fortran-rules",
   NegFlag<SetFalse, [], [ClangOption, CC1Option], "Range reduction is disabled "
   "for complex arithmetic operations">>;
 
-def Wunknown_attribute_namespace_EQ : CommaJoined<["-"], "Wunknown-attribute-namespace=">,
-  Group<W_value_Group>, Flags<[HelpHidden]>, Visibility<[ClangOption, CC1Option]>,
+def Wunknown_attribute_namespaces_EQ : CommaJoined<["-"], "Wunknown-attribute-namespaces=">,
+  Flags<[HelpHidden]>, Group<W_value_Group>, Visibility<[ClangOption, CC1Option]>,
   HelpText<"Specify a comma-separated list of allowed unknown attribute namespaces">,
   MarshallingInfoStringVector<DiagnosticOpts<"UnknownAttributeNamespaces">>;
 
diff --git a/clang/lib/Basic/Attributes.cpp b/clang/lib/Basic/Attributes.cpp
index 640c3d54fce3ee..b7cfe9ec9155a5 100644
--- a/clang/lib/Basic/Attributes.cpp
+++ b/clang/lib/Basic/Attributes.cpp
@@ -167,7 +167,7 @@ getScopeFromNormalizedScopeName(StringRef ScopeName) {
       .Case("msvc", AttributeCommonInfo::Scope::MSVC)
       .Case("omp", AttributeCommonInfo::Scope::OMP)
       .Case("riscv", AttributeCommonInfo::Scope::RISCV)
-      .Default(AttributeCommonInfo::Scope::NONE);
+      .Default(AttributeCommonInfo::Scope::UNKNOWN);
 }
 
 unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const {
@@ -183,7 +183,8 @@ unsigned AttributeCommonInfo::calculateAttributeSpellingListIndex() const {
 #include "clang/Sema/AttrSpellingListIndex.inc"
 }
 
-bool AttributeCommonInfo::isKnownScopeName() const {
-  return getScopeFromNormalizedScopeName(normalizeAttrScopeName(
-             getScopeName(), getSyntax())) != AttributeCommonInfo::Scope::NONE;
+bool AttributeCommonInfo::isUnknownScopeName() const {
+  return getScopeFromNormalizedScopeName(
+             normalizeAttrScopeName(getScopeName(), getSyntax())) ==
+         AttributeCommonInfo::Scope::UNKNOWN;
 }
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 34575e9ed21485..c7efc45af0e25a 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -2578,7 +2578,7 @@ void CompilerInvocationBase::GenerateDiagnosticArgs(
     if (Warning == "invalid-constexpr" || Warning == "no-invalid-constexpr")
       continue;
     // This option is automatically generated from UnknownAttributeNamespaces.
-    if (Warning == "unknown-attribute-namespace")
+    if (Warning == "unknown-attribute-namespaces")
       continue;
     Consumer(StringRef("-W") + Warning);
   }
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 99cb1797ae6d5e..f4293dda69640e 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -6545,20 +6545,27 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
   if (AL.getKind() == ParsedAttr::UnknownAttribute ||
       !AL.existsInTarget(S.Context.getTargetInfo())) {
 
-    unsigned DiagID = diag::warn_unknown_attribute_ignored;
-    if (AL.isRegularKeywordAttribute())
-      DiagID = diag::err_keyword_not_supported_on_target;
-    else if (AL.isDeclspecAttribute())
-      DiagID = diag::warn_unhandled_ms_attribute_ignored;
-    else if (AL.hasScope() && !AL.isKnownScopeName()) {
+    if (AL.isUnknownScopeName()) {
       const std::vector<std::string> UnknownAttributeNamespaces =
           S.getDiagnostics().getDiagnosticOptions().UnknownAttributeNamespaces;
+
       if (llvm::is_contained(UnknownAttributeNamespaces,
                              AL.getScopeName()->getName()))
         return;
-    }
 
-    S.Diag(AL.getLoc(), DiagID) << AL << AL.getRange();
+      SourceLocation BeginLoc = AL.getScopeLoc();
+      SourceLocation EndLoc = AL.getRange().getEnd();
+      S.Diag(BeginLoc, diag::warn_unknown_attribute_namespace)
+          << AL.getScopeName()->getName() << AL.getAttrName()->getName()
+          << SourceRange(BeginLoc, EndLoc);
+    } else {
+      S.Diag(AL.getLoc(), AL.isRegularKeywordAttribute()
+                              ? diag::err_keyword_not_supported_on_target
+                          : AL.isDeclspecAttribute()
+                              ? diag::warn_unhandled_ms_attribute_ignored
+                              : diag::warn_unknown_attribute_ignored)
+          << AL << AL.getRange();
+    }
     return;
   }
 
diff --git a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p2-1z.cpp b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p2-1z.cpp
index fcb6170905f7b3..afa48c83660620 100644
--- a/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p2-1z.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.grammar/p2-1z.cpp
@@ -13,4 +13,4 @@
 [[using blah: clang::optnone]] extern int n; // expected-error {{attribute with scope specifier cannot follow}} expected-warning {{only applies to functions}}
 
 [[using clang: unknown_attr]] extern int n;   // expected-warning {{unknown attribute 'unknown_attr' ignored}}
-[[using unknown_ns: something]] extern int n; // expected-warning {{unknown attribute 'something' ignored}}
+[[using unknown_ns: something]] extern int n; // expected-warning {{unknown attribute namespace 'unknown_ns'; attribute 'unknown_ns::something' ignored}}
diff --git a/clang/test/CXX/module/module.interface/p3.cpp b/clang/test/CXX/module/module.interface/p3.cpp
index 28826e435b1290..18758edaf1be71 100644
--- a/clang/test/CXX/module/module.interface/p3.cpp
+++ b/clang/test/CXX/module/module.interface/p3.cpp
@@ -40,7 +40,7 @@ export { // No diagnostic after P2615R1 DR
   extern "C++" {} // No diagnostic after P2615R1 DR
 }
 export [[]]; // No diagnostic after P2615R1 DR
-export [[example::attr]]; // expected-warning {{unknown attribute 'attr' ignored}}
+export [[example::attr]]; // expected-warning {{unknown attribute namespace 'example'; attribute 'example::attr' ignored}}
 
 // [...] shall not declare a name with internal linkage
 export static int a; // expected-error {{declaration of 'a' with internal linkage cannot be exported}}
diff --git a/clang/test/Lexer/cxx2a-spaceship.cpp b/clang/test/Lexer/cxx2a-spaceship.cpp
index 396bb7479366e3..d54dddfb9658e9 100644
--- a/clang/test/Lexer/cxx2a-spaceship.cpp
+++ b/clang/test/Lexer/cxx2a-spaceship.cpp
@@ -61,7 +61,7 @@ static_assert(__builtin_strcmp(b, "<=>") == 0);
 // CXX20: preprocess8: <=>=
 
 #define ID(x) x
-[[some_vendor::some_attribute( // expected-warning {{unknown attribute 'some_attribute' ignored}}
+[[some_vendor::some_attribute( // expected-warning {{unknown attribute namespace 'some_vendor'; attribute 'some_vendor::some_attribute' ignored}}
 preprocess1: ID(<)ID(=>),
 preprocess2: ID(<=)ID(>),
 preprocess3: ID(<)ID(=)ID(>),
diff --git a/clang/test/Parser/c2x-attributes.c b/clang/test/Parser/c2x-attributes.c
index be039e40f98ef1..b5f502c5790d34 100644
--- a/clang/test/Parser/c2x-attributes.c
+++ b/clang/test/Parser/c2x-attributes.c
@@ -133,7 +133,7 @@ void f11(void) {
 }
 
 [[attr]] void f12(void); // expected-warning {{unknown attribute 'attr' ignored}}
-[[vendor::attr]] void f13(void); // expected-warning {{unknown attribute 'attr' ignored}}
+[[vendor::attr]] void f13(void); // expected-warning {{unknown attribute namespace 'vendor'; attribute 'vendor::attr' ignored}}
 
 // Ensure that asm statements properly handle double colons.
 void test_asm(void) {
diff --git a/clang/test/Parser/cxx0x-attributes.cpp b/clang/test/Parser/cxx0x-attributes.cpp
index d9fdedc3ab6d62..7727915f8e62be 100644
--- a/clang/test/Parser/cxx0x-attributes.cpp
+++ b/clang/test/Parser/cxx0x-attributes.cpp
@@ -46,9 +46,9 @@ int & [[noreturn]] ref_attr_3 = after_attr; // expected-error {{'noreturn' attri
 int && [[]] rref_attr = 0;
 int array_attr [1] [[]];
 alignas(8) int aligned_attr;
-[[test::valid(for 42 [very] **** '+' symbols went on a trip and had a "good"_time; the end.)]] int garbage_attr; // expected-warning {{unknown attribute 'valid' ignored}}
+[[test::valid(for 42 [very] **** '+' symbols went on a trip and had a "good"_time; the end.)]] int garbage_attr; // expected-warning {{unknown attribute namespace 'test'; attribute 'test::valid' ignored}}
 [[,,,static, class, namespace,, inline, constexpr, mutable,, bitand, bitor::compl(!.*_ Cx.!U^*R),,,]] int more_garbage_attr; // expected-warning {{unknown attribute 'static' ignored}} \
-    // expected-warning {{unknown attribute 'compl' ignored}} \
+    // expected-warning {{unknown attribute namespace 'bitor'; attribute 'bitor::compl' ignored}} \
     // expected-warning {{unknown attribute 'class' ignored}} \
     // expected-warning {{unknown attribute 'namespace' ignored}} \
     // expected-warning {{unknown attribute 'inline' ignored}} \
@@ -269,7 +269,7 @@ template <int... Is> void variadic_nttp() {
   void baz [[clang::no_sanitize(Is...)]] ();          // expected-error {{expected string literal as argument of 'no_sanitize' attribute}}
   void bor [[clang::annotate("A", "V" ...)]] ();      // expected-error {{pack expansion does not contain any unexpanded parameter packs}}
   void bir [[clang::annotate("B", {1, 2, 3, 4})]] (); // expected-error {{'annotate' attribute requires parameter 1 to be a constant expression}} expected-note {{subexpression not valid in a constant expression}}
-  void boo [[unknown::foo(Is...)]] ();                // expected-warning {{unknown attribute 'foo' ignored}}
+  void boo [[unknown::foo(Is...)]] ();                // expected-warning {{unknown attribute namespace 'unknown'; attribute 'unknown::foo' ignored}}
   void faz [[clang::annotate("C", (Is + ...))]] ();   // expected-warning {{pack fold expression is a C++17 extension}}
   void far [[clang::annotate("D", Is...)]] ();
   void foz [[clang::annotate("E", 1, 2, 3, Is...)]] ();
diff --git a/clang/test/Sema/unknown-attributes.c b/clang/test/Sema/unknown-attributes.c
index 16e1032d94ce60..49552a6391a21a 100644
--- a/clang/test/Sema/unknown-attributes.c
+++ b/clang/test/Sema/unknown-attributes.c
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -fsyntax-only -Wunknown-attribute-namespace=foo,bar -std=c23 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -Wunknown-attribute-namespaces=foo,bar -std=c23 %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -x c++ -fsyntax-only -Wunknown-attribute-namespaces=foo,bar -std=c++2b %s 2>&1 | FileCheck %s
 
 [[foo::a(b((c)) d(e((f)))), foo::g(h k)]]
 int f1(void) {
@@ -10,15 +11,18 @@ int f2(void) {
   return 0;
 }
 
-[[baz::a(b((c)) d(e((f)))), baz::g(h k)]] // expected-warning {{unknown attribute 'a' ignored}} \
-                                          // expected-warning {{unknown attribute 'g' ignored}}
+// CHECK: 17:3: warning: unknown attribute namespace 'baz'; attribute 'baz::a' ignored [-Wunknown-attribute-namespaces]
+// CHECK: 17:29: warning: unknown attribute namespace 'baz'; attribute 'baz::g' ignored [-Wunknown-attribute-namespaces]
+
+[[baz::a(b((c)) d(e((f)))), baz::g(h k)]]
 int f3(void) {
   return 0;
 }
 
+// CHECK: 25:3: warning: unknown attribute 'a' ignored [-Wunknown-attributes]
+// CHECK: 25:31: warning: unknown attribute 'g' ignored [-Wunknown-attributes]
 
-[[clang::a(b((c)) d(e((f)))), clang::g(h k)]] // expected-warning {{unknown attribute 'a' ignored}} \
-                                              // expected-warning {{unknown attribute 'g' ignored}}
+[[clang::a(b((c)) d(e((f)))), clang::g(h k)]]
 int f4(void) {
   return 0;
 }

>From 9030801e7c7691ea0267427af5e21b985f5f708b Mon Sep 17 00:00:00 2001
From: Oleksandr T <oleksandr.tarasiuk at outlook.com>
Date: Fri, 24 Jan 2025 00:44:16 +0200
Subject: [PATCH 6/9] add additional tests

---
 clang/test/Sema/no-unknown-attributes.c |  9 ++++++
 clang/test/Sema/unknown-attributes.c    | 42 ++++++++++++++++++++-----
 2 files changed, 43 insertions(+), 8 deletions(-)
 create mode 100644 clang/test/Sema/no-unknown-attributes.c

diff --git a/clang/test/Sema/no-unknown-attributes.c b/clang/test/Sema/no-unknown-attributes.c
new file mode 100644
index 00000000000000..d7690c63cf5535
--- /dev/null
+++ b/clang/test/Sema/no-unknown-attributes.c
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -fsyntax-only -Wno-unknown-attributes -std=c23 -verify %s
+// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unknown-attributes -std=c++2b -verify %s
+
+// expected-no-diagnostics
+
+[[unknown_ns::a]][[gnu::b]]
+int f(void) {
+  return 0;
+}
diff --git a/clang/test/Sema/unknown-attributes.c b/clang/test/Sema/unknown-attributes.c
index 49552a6391a21a..21eb413fd67dd1 100644
--- a/clang/test/Sema/unknown-attributes.c
+++ b/clang/test/Sema/unknown-attributes.c
@@ -1,5 +1,14 @@
-// RUN: %clang_cc1 -fsyntax-only -Wunknown-attribute-namespaces=foo,bar -std=c23 %s 2>&1 | FileCheck %s
-// RUN: %clang_cc1 -x c++ -fsyntax-only -Wunknown-attribute-namespaces=foo,bar -std=c++2b %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -fsyntax-only -Wunknown-attribute-namespaces=foo,bar -std=c23 %s 2>&1 | FileCheck %s --check-prefixes=CHECK_UNKNOWN_ATTR_NS
+// RUN: %clang_cc1 -x c++ -fsyntax-only -Wunknown-attribute-namespaces=foo,bar -std=c++2b %s 2>&1 | FileCheck %s --check-prefixes=CHECK_UNKNOWN_ATTR_NS
+
+// RUN: %clang_cc1 -fsyntax-only -Wunknown-attributes -std=c23 %s 2>&1 | FileCheck %s --check-prefixes=CHECK_UNKNOWN_ATTRS
+// RUN: %clang_cc1 -x c++ -fsyntax-only -Wunknown-attributes -std=c++2b %s 2>&1 | FileCheck %s --check-prefixes=CHECK_UNKNOWN_ATTRS
+
+// RUN: %clang_cc1 -fsyntax-only -Wunknown-attributes -Wno-unknown-attribute-namespaces -std=c23 %s 2>&1 | FileCheck %s --check-prefixes=CHECK_UNKNOWN_ATTRS_AND_NO_UNKNOWN_ATTR_NS
+// RUN: %clang_cc1 -x c++ -fsyntax-only -Wunknown-attributes -Wno-unknown-attribute-namespaces -std=c++2b %s 2>&1 | FileCheck %s --check-prefixes=CHECK_UNKNOWN_ATTRS_AND_NO_UNKNOWN_ATTR_NS
+
+// RUN: %clang_cc1 -fsyntax-only -Wno-unknown-attributes -Wunknown-attribute-namespaces -std=c23 %s 2>&1 | FileCheck %s --check-prefixes=CHECK_NO_UNKNOWN_ATTRS_AND_UNKNOWN_ATTR_NS
+// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unknown-attributes -Wunknown-attribute-namespaces -std=c++2b %s 2>&1 | FileCheck %s --check-prefixes=CHECK_NO_UNKNOWN_ATTRS_AND_UNKNOWN_ATTR_NS
 
 [[foo::a(b((c)) d(e((f)))), foo::g(h k)]]
 int f1(void) {
@@ -11,17 +20,15 @@ int f2(void) {
   return 0;
 }
 
-// CHECK: 17:3: warning: unknown attribute namespace 'baz'; attribute 'baz::a' ignored [-Wunknown-attribute-namespaces]
-// CHECK: 17:29: warning: unknown attribute namespace 'baz'; attribute 'baz::g' ignored [-Wunknown-attribute-namespaces]
-
+// CHECK_UNKNOWN_ATTR_NS: 25:3: warning: unknown attribute namespace 'baz'; attribute 'baz::a' ignored [-Wunknown-attribute-namespaces]
+// CHECK_UNKNOWN_ATTR_NS: 25:29: warning: unknown attribute namespace 'baz'; attribute 'baz::g' ignored [-Wunknown-attribute-namespaces]
 [[baz::a(b((c)) d(e((f)))), baz::g(h k)]]
 int f3(void) {
   return 0;
 }
 
-// CHECK: 25:3: warning: unknown attribute 'a' ignored [-Wunknown-attributes]
-// CHECK: 25:31: warning: unknown attribute 'g' ignored [-Wunknown-attributes]
-
+// CHECK_UNKNOWN_ATTR_NS: 32:3: warning: unknown attribute 'a' ignored [-Wunknown-attributes]
+// CHECK_UNKNOWN_ATTR_NS: 32:31: warning: unknown attribute 'g' ignored [-Wunknown-attributes]
 [[clang::a(b((c)) d(e((f)))), clang::g(h k)]]
 int f4(void) {
   return 0;
@@ -31,3 +38,22 @@ int f4(void) {
 int f5(void) {
   return 0;
 }
+
+// CHECK_UNKNOWN_ATTRS: 44:20: warning: unknown attribute 'b' ignored [-Wunknown-attributes]
+// CHECK_UNKNOWN_ATTRS: 44:3: warning: unknown attribute namespace 'unknown_ns'; attribute 'unknown_ns::a' ignored [-Wunknown-attribute-namespaces]
+[[unknown_ns::a]][[gnu::b]]
+int f6(void) {
+  return 0;
+}
+
+// CHECK_UNKNOWN_ATTRS_AND_NO_UNKNOWN_ATTR_NS: 50:20: warning: unknown attribute 'b' ignored [-Wunknown-attributes]
+[[unknown_ns::a]][[gnu::b]]
+int f7(void) {
+  return 0;
+}
+
+// CHECK_NO_UNKNOWN_ATTRS_AND_UNKNOWN_ATTR_NS: 56:3: warning: unknown attribute namespace 'unknown_ns'; attribute 'unknown_ns::a' ignored [-Wunknown-attribute-namespaces]
+[[unknown_ns::a]][[gnu::b]]
+int f8(void) {
+  return 0;
+}

>From 60b8406215090bd0a0d50aa38acc8c242a43ae90 Mon Sep 17 00:00:00 2001
From: Oleksandr T <oleksandr.tarasiuk at outlook.com>
Date: Fri, 24 Jan 2025 00:44:58 +0200
Subject: [PATCH 7/9] include unknown-attribute-namespaces to
 unknown-attributes group

---
 clang/include/clang/Basic/DiagnosticGroups.td | 2 +-
 clang/lib/Frontend/CompilerInvocation.cpp     | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index bb599427dd826b..ce034c8a6e85b5 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -824,7 +824,7 @@ def NSReturnsMismatch : DiagGroup<"nsreturns-mismatch">;
 
 def UnknownAttributeNamespaces : DiagGroup<"unknown-attribute-namespaces">;
 def IndependentClassAttribute : DiagGroup<"IndependentClass-attribute">;
-def UnknownAttributes : DiagGroup<"unknown-attributes">;
+def UnknownAttributes : DiagGroup<"unknown-attributes", [UnknownAttributeNamespaces]>;
 def IgnoredAttributes : DiagGroup<"ignored-attributes">;
 def Attributes : DiagGroup<"attributes", [UnknownAttributes,
                                           IgnoredAttributes]>;
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index c7efc45af0e25a..ad8dc4c9906af0 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -2578,7 +2578,8 @@ void CompilerInvocationBase::GenerateDiagnosticArgs(
     if (Warning == "invalid-constexpr" || Warning == "no-invalid-constexpr")
       continue;
     // This option is automatically generated from UnknownAttributeNamespaces.
-    if (Warning == "unknown-attribute-namespaces")
+    if (Warning == "unknown-attribute-namespaces" &&
+        Opts.UnknownAttributeNamespaces.size())
       continue;
     Consumer(StringRef("-W") + Warning);
   }

>From 5fcfd2331ca893c17d3b2a341f4a29b62db64703 Mon Sep 17 00:00:00 2001
From: Oleksandr T <oleksandr.tarasiuk at outlook.com>
Date: Fri, 24 Jan 2025 00:45:15 +0200
Subject: [PATCH 8/9] update release notes

---
 clang/docs/ReleaseNotes.rst | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 632e5dc04912b1..19bf19b1dcfb95 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -606,7 +606,8 @@ Attribute Changes in Clang
 
 - Clang now disallows the use of attributes after the namespace name. (#GH121407)
 
-- Clang now raises warnings for unknown namespaced attributes only in pedantic mode (#GH120875).
+- Clang now diagnoses unknown attribute namespaces. Added the ``-Wunknown-namespace-attributes=`` option to
+  specify a comma-separated list of allowed unknown attribute namespaces (#GH120875).
 
 Improvements to Clang's diagnostics
 -----------------------------------

>From eea9f753bbc37f1cc442f7b842dae63856c513a6 Mon Sep 17 00:00:00 2001
From: Oleksandr T <oleksandr.tarasiuk at outlook.com>
Date: Fri, 24 Jan 2025 01:15:10 +0200
Subject: [PATCH 9/9] format test

---
 clang/test/Sema/unknown-attributes.c | 40 +++++++++++++++++-----------
 1 file changed, 24 insertions(+), 16 deletions(-)

diff --git a/clang/test/Sema/unknown-attributes.c b/clang/test/Sema/unknown-attributes.c
index 21eb413fd67dd1..dd5b820ecbe62d 100644
--- a/clang/test/Sema/unknown-attributes.c
+++ b/clang/test/Sema/unknown-attributes.c
@@ -1,14 +1,22 @@
-// RUN: %clang_cc1 -fsyntax-only -Wunknown-attribute-namespaces=foo,bar -std=c23 %s 2>&1 | FileCheck %s --check-prefixes=CHECK_UNKNOWN_ATTR_NS
-// RUN: %clang_cc1 -x c++ -fsyntax-only -Wunknown-attribute-namespaces=foo,bar -std=c++2b %s 2>&1 | FileCheck %s --check-prefixes=CHECK_UNKNOWN_ATTR_NS
+// RUN: %clang_cc1 -fsyntax-only -Wunknown-attribute-namespaces=foo,bar -std=c23 \
+// RUN:   %s 2>&1 | FileCheck %s --check-prefixes=CHECK_UNKNOWN_ATTR_NS
+// RUN: %clang_cc1 -x c++ -fsyntax-only -Wunknown-attribute-namespaces=foo,bar -std=c++2b \
+// RUN:   %s 2>&1 | FileCheck %s --check-prefixes=CHECK_UNKNOWN_ATTR_NS
 
-// RUN: %clang_cc1 -fsyntax-only -Wunknown-attributes -std=c23 %s 2>&1 | FileCheck %s --check-prefixes=CHECK_UNKNOWN_ATTRS
-// RUN: %clang_cc1 -x c++ -fsyntax-only -Wunknown-attributes -std=c++2b %s 2>&1 | FileCheck %s --check-prefixes=CHECK_UNKNOWN_ATTRS
+// RUN: %clang_cc1 -fsyntax-only -Wunknown-attributes -std=c23 \
+// RUN:   %s 2>&1 | FileCheck %s --check-prefixes=CHECK_UNKNOWN_ATTRS
+// RUN: %clang_cc1 -x c++ -fsyntax-only -Wunknown-attributes -std=c++2b \
+// RUN:   %s 2>&1 | FileCheck %s --check-prefixes=CHECK_UNKNOWN_ATTRS
 
-// RUN: %clang_cc1 -fsyntax-only -Wunknown-attributes -Wno-unknown-attribute-namespaces -std=c23 %s 2>&1 | FileCheck %s --check-prefixes=CHECK_UNKNOWN_ATTRS_AND_NO_UNKNOWN_ATTR_NS
-// RUN: %clang_cc1 -x c++ -fsyntax-only -Wunknown-attributes -Wno-unknown-attribute-namespaces -std=c++2b %s 2>&1 | FileCheck %s --check-prefixes=CHECK_UNKNOWN_ATTRS_AND_NO_UNKNOWN_ATTR_NS
+// RUN: %clang_cc1 -fsyntax-only -Wunknown-attributes -Wno-unknown-attribute-namespaces -std=c23 \
+// RUN:   %s 2>&1 | FileCheck %s --check-prefixes=CHECK_UNKNOWN_ATTRS_AND_NO_UNKNOWN_ATTR_NS
+// RUN: %clang_cc1 -x c++ -fsyntax-only -Wunknown-attributes -Wno-unknown-attribute-namespaces -std=c++2b \
+// RUN:   %s 2>&1 | FileCheck %s --check-prefixes=CHECK_UNKNOWN_ATTRS_AND_NO_UNKNOWN_ATTR_NS
 
-// RUN: %clang_cc1 -fsyntax-only -Wno-unknown-attributes -Wunknown-attribute-namespaces -std=c23 %s 2>&1 | FileCheck %s --check-prefixes=CHECK_NO_UNKNOWN_ATTRS_AND_UNKNOWN_ATTR_NS
-// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unknown-attributes -Wunknown-attribute-namespaces -std=c++2b %s 2>&1 | FileCheck %s --check-prefixes=CHECK_NO_UNKNOWN_ATTRS_AND_UNKNOWN_ATTR_NS
+// RUN: %clang_cc1 -fsyntax-only -Wno-unknown-attributes -Wunknown-attribute-namespaces -std=c23 \
+// RUN:   %s 2>&1 | FileCheck %s --check-prefixes=CHECK_NO_UNKNOWN_ATTRS_AND_UNKNOWN_ATTR_NS
+// RUN: %clang_cc1 -x c++ -fsyntax-only -Wno-unknown-attributes -Wunknown-attribute-namespaces -std=c++2b \
+// RUN:   %s 2>&1 | FileCheck %s --check-prefixes=CHECK_NO_UNKNOWN_ATTRS_AND_UNKNOWN_ATTR_NS
 
 [[foo::a(b((c)) d(e((f)))), foo::g(h k)]]
 int f1(void) {
@@ -20,15 +28,15 @@ int f2(void) {
   return 0;
 }
 
-// CHECK_UNKNOWN_ATTR_NS: 25:3: warning: unknown attribute namespace 'baz'; attribute 'baz::a' ignored [-Wunknown-attribute-namespaces]
-// CHECK_UNKNOWN_ATTR_NS: 25:29: warning: unknown attribute namespace 'baz'; attribute 'baz::g' ignored [-Wunknown-attribute-namespaces]
+// CHECK_UNKNOWN_ATTR_NS: 33:3: warning: unknown attribute namespace 'baz'; attribute 'baz::a' ignored [-Wunknown-attribute-namespaces]
+// CHECK_UNKNOWN_ATTR_NS: 33:29: warning: unknown attribute namespace 'baz'; attribute 'baz::g' ignored [-Wunknown-attribute-namespaces]
 [[baz::a(b((c)) d(e((f)))), baz::g(h k)]]
 int f3(void) {
   return 0;
 }
 
-// CHECK_UNKNOWN_ATTR_NS: 32:3: warning: unknown attribute 'a' ignored [-Wunknown-attributes]
-// CHECK_UNKNOWN_ATTR_NS: 32:31: warning: unknown attribute 'g' ignored [-Wunknown-attributes]
+// CHECK_UNKNOWN_ATTR_NS: 40:3: warning: unknown attribute 'a' ignored [-Wunknown-attributes]
+// CHECK_UNKNOWN_ATTR_NS: 40:31: warning: unknown attribute 'g' ignored [-Wunknown-attributes]
 [[clang::a(b((c)) d(e((f)))), clang::g(h k)]]
 int f4(void) {
   return 0;
@@ -39,20 +47,20 @@ int f5(void) {
   return 0;
 }
 
-// CHECK_UNKNOWN_ATTRS: 44:20: warning: unknown attribute 'b' ignored [-Wunknown-attributes]
-// CHECK_UNKNOWN_ATTRS: 44:3: warning: unknown attribute namespace 'unknown_ns'; attribute 'unknown_ns::a' ignored [-Wunknown-attribute-namespaces]
+// CHECK_UNKNOWN_ATTRS: 52:20: warning: unknown attribute 'b' ignored [-Wunknown-attributes]
+// CHECK_UNKNOWN_ATTRS: 52:3: warning: unknown attribute namespace 'unknown_ns'; attribute 'unknown_ns::a' ignored [-Wunknown-attribute-namespaces]
 [[unknown_ns::a]][[gnu::b]]
 int f6(void) {
   return 0;
 }
 
-// CHECK_UNKNOWN_ATTRS_AND_NO_UNKNOWN_ATTR_NS: 50:20: warning: unknown attribute 'b' ignored [-Wunknown-attributes]
+// CHECK_UNKNOWN_ATTRS_AND_NO_UNKNOWN_ATTR_NS: 58:20: warning: unknown attribute 'b' ignored [-Wunknown-attributes]
 [[unknown_ns::a]][[gnu::b]]
 int f7(void) {
   return 0;
 }
 
-// CHECK_NO_UNKNOWN_ATTRS_AND_UNKNOWN_ATTR_NS: 56:3: warning: unknown attribute namespace 'unknown_ns'; attribute 'unknown_ns::a' ignored [-Wunknown-attribute-namespaces]
+// CHECK_NO_UNKNOWN_ATTRS_AND_UNKNOWN_ATTR_NS: 64:3: warning: unknown attribute namespace 'unknown_ns'; attribute 'unknown_ns::a' ignored [-Wunknown-attribute-namespaces]
 [[unknown_ns::a]][[gnu::b]]
 int f8(void) {
   return 0;



More information about the cfe-commits mailing list