[clang] [clang] Centralize common checks for type attributes (PR #227421)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 12 06:54:36 PDT 2026
https://github.com/elizabethandrews updated https://github.com/llvm/llvm-project/pull/227421
>From e3784e1ab611390c17c6fd628b79f8b5900e601b Mon Sep 17 00:00:00 2001
From: Elizabeth Andrews <elizabeth.andrews at intel.com>
Date: Tue, 29 Sep 2026 11:00:58 -0700
Subject: [PATCH 1/3] [clang] Centralize common checks for type attributes
Type attributes were not run through the common attribute feature
checks in checkCommonAttributeFeatures(). As a result, the constraints
declared for a type attribute in Attr.td, such as LangOpts gating.
were not honored unless each attribute handler did it themselves.
This PR centralizes the checks and removes the now-redundant
per-handler checks.
Fixes : https://github.com/llvm/llvm-project/issues/225581
AI Use - I used claude to find redundant checks in handlers and
modify tests.
---
clang/include/clang/Sema/Sema.h | 2 +
clang/lib/Sema/SemaAttr.cpp | 41 ++++++++-----
clang/lib/Sema/SemaType.cpp | 59 ++-----------------
clang/test/Sema/attr-btf_tag.c | 4 +-
clang/test/Sema/attr-function-return.c | 2 +-
clang/test/Sema/ext_vector_casts.c | 3 +
.../test/SemaCXX/attr-unsafe-buffer-usage.cpp | 3 +-
clang/test/SemaCXX/matrix-type.cpp | 3 +
clang/test/SemaObjC/attr-objc-gc.m | 2 +-
.../sycl-address-space-attr-on-non-sycl.cpp | 21 +++++++
10 files changed, 67 insertions(+), 73 deletions(-)
create mode 100644 clang/test/SemaSYCL/sycl-address-space-attr-on-non-sycl.cpp
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index eb3b908351448..70cc92a06e271 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2447,6 +2447,8 @@ class Sema final : public SemaBase {
bool SkipArgCountCheck = false);
bool checkCommonAttributeFeatures(const Stmt *S, const ParsedAttr &A,
bool SkipArgCountCheck = false);
+ bool checkCommonAttributeFeatures(const ParsedAttr &A,
+ bool SkipArgCountCheck = false);
///@}
diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp
index 35d14a4444595..9b995059048c7 100644
--- a/clang/lib/Sema/SemaAttr.cpp
+++ b/clang/lib/Sema/SemaAttr.cpp
@@ -1620,28 +1620,16 @@ void Sema::PopPragmaVisibility(bool IsNamespaceEnd, SourceLocation EndLoc) {
FreeVisContext();
}
-template <typename Ty>
-static bool checkCommonAttributeFeatures(Sema &S, const Ty *Node,
- const ParsedAttr &A,
+static bool checkCommonAttributeFeatures(Sema &S, const ParsedAttr &A,
bool SkipArgCountCheck) {
- // Several attributes carry different semantics than the parsing requires, so
- // those are opted out of the common argument checks.
- //
- // We also bail on unknown and ignored attributes because those are handled
- // as part of the target-specific handling logic.
+ // We bail on unknown and ignored attributes because those are handled as
+ // part of the target-specific handling logic.
if (A.getKind() == ParsedAttr::UnknownAttribute)
return false;
// Check whether the attribute requires specific language extensions to be
// enabled.
if (!A.diagnoseLangOpts(S))
return true;
- // Check whether the attribute appertains to the given subject.
- if (!A.diagnoseAppertainsTo(S, Node))
- return true;
- // Check whether the attribute is mutually exclusive with other attributes
- // that have already been applied to the declaration.
- if (!A.diagnoseMutualExclusion(S, Node))
- return true;
// Check whether the attribute exists in the target architecture.
if (S.CheckAttrTarget(A))
return true;
@@ -1668,6 +1656,25 @@ static bool checkCommonAttributeFeatures(Sema &S, const Ty *Node,
return false;
}
+template <typename Ty>
+static bool checkCommonAttributeFeatures(Sema &S, const Ty *Node,
+ const ParsedAttr &A,
+ bool SkipArgCountCheck) {
+ // Run the checks shared with type attributes (language options, target, and
+ // argument count). This also bails on unknown and ignored attributes.
+ if (checkCommonAttributeFeatures(S, A, SkipArgCountCheck))
+ return true;
+ // Check whether the attribute appertains to the given subject.
+ if (!A.diagnoseAppertainsTo(S, Node))
+ return true;
+ // Check whether the attribute is mutually exclusive with other attributes
+ // that have already been applied to the declaration.
+ if (!A.diagnoseMutualExclusion(S, Node))
+ return true;
+
+ return false;
+}
+
bool Sema::checkCommonAttributeFeatures(const Decl *D, const ParsedAttr &A,
bool SkipArgCountCheck) {
return ::checkCommonAttributeFeatures(*this, D, A, SkipArgCountCheck);
@@ -1676,3 +1683,7 @@ bool Sema::checkCommonAttributeFeatures(const Stmt *S, const ParsedAttr &A,
bool SkipArgCountCheck) {
return ::checkCommonAttributeFeatures(*this, S, A, SkipArgCountCheck);
}
+bool Sema::checkCommonAttributeFeatures(const ParsedAttr &A,
+ bool SkipArgCountCheck) {
+ return ::checkCommonAttributeFeatures(*this, A, SkipArgCountCheck);
+}
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 2796ac2929f46..b6ccc52504e4f 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -6607,23 +6607,6 @@ static void HandleBTFTypeTagAttribute(QualType &Type, const ParsedAttr &Attr,
TypeProcessingState &State) {
Sema &S = State.getSema();
- // This attribute is only supported in C.
- // FIXME: we should implement checkCommonAttributeFeatures() in SemaAttr.cpp
- // such that it handles type attributes, and then call that from
- // processTypeAttrs() instead of one-off checks like this.
- if (!Attr.diagnoseLangOpts(S)) {
- Attr.setInvalid();
- return;
- }
-
- // Check the number of attribute arguments.
- if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr << 1;
- Attr.setInvalid();
- return;
- }
-
// Ensure the argument is a string.
auto *StrLiteral = dyn_cast<StringLiteral>(Attr.getArgAsExpr(0));
if (!StrLiteral) {
@@ -8531,13 +8514,6 @@ static void HandleVectorSizeAttr(QualType &CurType, const ParsedAttr &Attr,
/// a type.
static void HandleExtVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr,
Sema &S) {
- // check the attribute arguments.
- if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Attr
- << 1;
- return;
- }
-
Expr *SizeExpr = Attr.getArgAsExpr(0);
QualType T = S.BuildExtVectorType(CurType, SizeExpr, Attr.getLoc());
if (!T.isNull())
@@ -8639,13 +8615,6 @@ static void HandleNeonVectorTypeAttr(QualType &CurType, const ParsedAttr &Attr,
return;
}
- // Check the attribute arguments.
- if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr << 1;
- Attr.setInvalid();
- return;
- }
// The number of elements must be an ICE.
llvm::APSInt numEltsInt(32);
if (!verifyValidIntegerConstantExpr(S, Attr, numEltsInt))
@@ -8752,14 +8721,6 @@ static void HandleArmSveVectorBitsTypeAttr(QualType &CurType, ParsedAttr &Attr,
return;
}
- // Check the attribute arguments.
- if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr << 1;
- Attr.setInvalid();
- return;
- }
-
// The vector size must be an integer constant expression.
llvm::APSInt SveVectorSizeInBits(32);
if (!verifyValidIntegerConstantExpr(S, Attr, SveVectorSizeInBits))
@@ -8836,14 +8797,6 @@ static void HandleRISCVRVVVectorBitsTypeAttr(QualType &CurType,
return;
}
- // Check the attribute arguments.
- if (Attr.getNumArgs() != 1) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr << 1;
- Attr.setInvalid();
- return;
- }
-
// The vector size must be an integer constant expression.
llvm::APSInt RVVVectorSizeInBits(32);
if (!verifyValidIntegerConstantExpr(S, Attr, RVVVectorSizeInBits))
@@ -8965,12 +8918,6 @@ static void HandleMatrixTypeAttr(QualType &CurType, const ParsedAttr &Attr,
return;
}
- if (Attr.getNumArgs() != 2) {
- S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
- << Attr << 2;
- return;
- }
-
Expr *RowsExpr = Attr.getArgAsExpr(0);
Expr *ColsExpr = Attr.getArgAsExpr(1);
QualType T = S.BuildMatrixType(CurType, RowsExpr, ColsExpr, Attr.getLoc());
@@ -9096,6 +9043,12 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
}
}
+ if (attr.isTypeAttr() &&
+ state.getSema().checkCommonAttributeFeatures(attr)) {
+ attr.setInvalid();
+ continue;
+ }
+
// If this is an attribute we can handle, do so now,
// otherwise, add it to the FnAttrs list for rechaining.
switch (attr.getKind()) {
diff --git a/clang/test/Sema/attr-btf_tag.c b/clang/test/Sema/attr-btf_tag.c
index cbb21a5a88bb6..e58420e0dd277 100644
--- a/clang/test/Sema/attr-btf_tag.c
+++ b/clang/test/Sema/attr-btf_tag.c
@@ -29,11 +29,11 @@ enum e1 {
enum e2 {
E2
-} __tag_no_arg; // expected-error {{'btf_decl_tag' attribute only applies to variables, functions, structs, unions, classes, non-static data members, and typedefs}}
+} __tag_no_arg; // expected-error {{'btf_decl_tag' attribute takes one argument}}
enum e3 {
E3
-} __tag_2_arg; // expected-error {{'btf_decl_tag' attribute only applies to variables, functions, structs, unions, classes, non-static data members, and typedefs}}
+} __tag_2_arg; // expected-error {{'btf_decl_tag' attribute takes one argument}}
int __tag1 __tag2 foo(struct t1 *arg, struct t2 *arg2);
int __tag2 __tag3 foo(struct t1 *arg, struct t2 *arg2);
diff --git a/clang/test/Sema/attr-function-return.c b/clang/test/Sema/attr-function-return.c
index d2c9156da7ab6..be72a9916e9c6 100644
--- a/clang/test/Sema/attr-function-return.c
+++ b/clang/test/Sema/attr-function-return.c
@@ -20,4 +20,4 @@ __attribute__((function_return(5))) void a(void) {}
__attribute__((function_return)) void b(void) {}
// expected-warning at +1 {{'function_return' attribute only applies to functions}}
-__attribute__((function_return)) int c;
+__attribute__((function_return("keep"))) int c;
diff --git a/clang/test/Sema/ext_vector_casts.c b/clang/test/Sema/ext_vector_casts.c
index 8bf2737e0bfab..cdc482d548c72 100644
--- a/clang/test/Sema/ext_vector_casts.c
+++ b/clang/test/Sema/ext_vector_casts.c
@@ -127,3 +127,6 @@ static void splats(int i, long l, __uint128_t t, float f, double d) {
vd = l + vd; // expected-warning {{implicit conversion from 'long' to 'double2' (vector of 2 'double' values) may lose precision}}
vd = vd + t; // expected-warning {{implicit conversion from '__uint128_t' (aka 'unsigned __int128') to 'double2' (vector of 2 'double' values) may lose precision}}
}
+
+typedef int no_arg __attribute__((ext_vector_type())); // expected-error {{'ext_vector_type' attribute takes one argument}}
+typedef int two_args __attribute__((ext_vector_type(2, 4))); // expected-error {{'ext_vector_type' attribute takes one argument}}
diff --git a/clang/test/SemaCXX/attr-unsafe-buffer-usage.cpp b/clang/test/SemaCXX/attr-unsafe-buffer-usage.cpp
index cab67784d9075..fcadd706c4b40 100644
--- a/clang/test/SemaCXX/attr-unsafe-buffer-usage.cpp
+++ b/clang/test/SemaCXX/attr-unsafe-buffer-usage.cpp
@@ -3,4 +3,5 @@
// Function annotations.
[[clang::unsafe_buffer_usage]]
void f(int *buf, int size);
-void g(int *buffer [[clang::unsafe_buffer_usage("buffer")]], int size); // expected-warning {{'clang::unsafe_buffer_usage' attribute only applies to functions}}
+void g(int *buffer [[clang::unsafe_buffer_usage]], int size); // expected-warning {{'clang::unsafe_buffer_usage' attribute only applies to functions}}
+void h(int *buffer [[clang::unsafe_buffer_usage("buffer")]], int size); // expected-error {{'clang::unsafe_buffer_usage' attribute takes no arguments}}
diff --git a/clang/test/SemaCXX/matrix-type.cpp b/clang/test/SemaCXX/matrix-type.cpp
index 3b3b22dea741a..fc2d88f04073d 100644
--- a/clang/test/SemaCXX/matrix-type.cpp
+++ b/clang/test/SemaCXX/matrix-type.cpp
@@ -15,6 +15,9 @@ void matrix_var_dimensions(int Rows, unsigned Columns, char C) {
using matrix7_t = int __attribute__((matrix_type(char, 0))); // expected-error{{expected '(' for function-style cast or type construction}}
using matrix8_t = int __attribute__((matrix_type(1048576, 1))); // expected-error{{matrix row size too large}}
using matrix8_t = int __attribute__((matrix_type(1048576, 1048576))); // expected-error{{matrix row and column size too large}}
+ using matrix9_t = int __attribute__((matrix_type())); // expected-error{{'matrix_type' attribute requires exactly 2 arguments}}
+ using matrix10_t = int __attribute__((matrix_type(1))); // expected-error{{'matrix_type' attribute requires exactly 2 arguments}}
+ using matrix11_t = int __attribute__((matrix_type(1, 2, 3))); // expected-error{{'matrix_type' attribute requires exactly 2 arguments}}
}
struct S1 {};
diff --git a/clang/test/SemaObjC/attr-objc-gc.m b/clang/test/SemaObjC/attr-objc-gc.m
index c199df725cd9f..88d76e7316675 100644
--- a/clang/test/SemaObjC/attr-objc-gc.m
+++ b/clang/test/SemaObjC/attr-objc-gc.m
@@ -2,7 +2,7 @@
static id __attribute((objc_gc(weak))) a;
static id __attribute((objc_gc(strong))) b;
-static id __attribute((objc_gc())) c; // expected-error{{'objc_gc' attribute requires a string}}
+static id __attribute((objc_gc())) c; // expected-error{{'objc_gc' attribute takes one argument}}
static id __attribute((objc_gc(123))) d; // expected-error{{'objc_gc' attribute requires a string}}
static id __attribute((objc_gc(foo, 456))) e; // expected-error{{'objc_gc' attribute takes one argument}}
static id __attribute((objc_gc(hello))) f; // expected-warning{{'objc_gc' attribute argument not supported: 'hello'}}
diff --git a/clang/test/SemaSYCL/sycl-address-space-attr-on-non-sycl.cpp b/clang/test/SemaSYCL/sycl-address-space-attr-on-non-sycl.cpp
new file mode 100644
index 0000000000000..583bea7ac5c36
--- /dev/null
+++ b/clang/test/SemaSYCL/sycl-address-space-attr-on-non-sycl.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -fsyntax-only -fsycl-is-device -verify %s
+// RUN: %clang_cc1 -fsyntax-only -fsycl-is-host -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -x c++ %s
+
+// The SYCL address space attributes are only enabled in SYCL compilations.
+
+#ifndef SYCL_LANGUAGE_VERSION
+// expected-warning@#global {{'clang::sycl_global' attribute ignored}}
+// expected-warning@#local {{'clang::sycl_local' attribute ignored}}
+// expected-warning@#private {{'clang::sycl_private' attribute ignored}}
+// expected-warning@#generic {{'clang::sycl_generic' attribute ignored}}
+// expected-warning@#constant {{'clang::sycl_constant' attribute ignored}}
+#else
+// expected-no-diagnostics
+#endif
+
+using global_ptr = int [[clang::sycl_global]] *; // #global
+using local_ptr = int [[clang::sycl_local]] *; // #local
+using private_ptr = int [[clang::sycl_private]] *; // #private
+using generic_ptr = int [[clang::sycl_generic]] *; // #generic
+using constant_ptr = int [[clang::sycl_constant]] *; // #constant
>From 6570405a15d092e6b3a5ad691da3502bfc9b31b7 Mon Sep 17 00:00:00 2001
From: Elizabeth Andrews <elizabeth.andrews at intel.com>
Date: Mon, 5 Oct 2026 12:05:28 -0700
Subject: [PATCH 2/3] Apply review comments
---
clang/include/clang/Sema/ParsedAttr.h | 8 ++++
clang/include/clang/Sema/Sema.h | 2 +-
clang/lib/Sema/SemaAttr.cpp | 45 +++++++++----------
clang/lib/Sema/SemaType.cpp | 2 +-
clang/test/Sema/attr-btf_tag.c | 4 +-
clang/test/Sema/attr-function-return.c | 2 +-
.../test/SemaCXX/attr-unsafe-buffer-usage.cpp | 3 +-
.../sycl-address-space-attr-ignored.cpp | 21 +++++++++
.../sycl-address-space-attr-on-non-sycl.cpp | 21 ---------
9 files changed, 56 insertions(+), 52 deletions(-)
create mode 100644 clang/test/SemaSYCL/sycl-address-space-attr-ignored.cpp
delete mode 100644 clang/test/SemaSYCL/sycl-address-space-attr-on-non-sycl.cpp
diff --git a/clang/include/clang/Sema/ParsedAttr.h b/clang/include/clang/Sema/ParsedAttr.h
index a606d66ef34c3..568fb0420d1ed 100644
--- a/clang/include/clang/Sema/ParsedAttr.h
+++ b/clang/include/clang/Sema/ParsedAttr.h
@@ -518,6 +518,10 @@ class ParsedAttr final
void handleAttrWithDelayedArgs(Sema &S, Decl *D) const;
bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const;
bool diagnoseAppertainsTo(class Sema &S, const Stmt *St) const;
+ // This function stub exists for parity with the declaration and statement
+ // checking code so that checkCommonAttributeFeatures() can work generically
+ // on types.
+ bool diagnoseAppertainsTo(class Sema &S, QualType T) const { return true; }
bool diagnoseMutualExclusion(class Sema &S, const Decl *D) const;
// This function stub exists for parity with the declaration checking code so
// that checkCommonAttributeFeatures() can work generically on declarations
@@ -525,6 +529,10 @@ class ParsedAttr final
bool diagnoseMutualExclusion(class Sema &S, const Stmt *St) const {
return true;
}
+ // This function stub exists for parity with the declaration and statement
+ // checking code so that checkCommonAttributeFeatures() can work generically
+ // on types.
+ bool diagnoseMutualExclusion(class Sema &S, QualType T) const { return true; }
bool appliesToDecl(const Decl *D, attr::SubjectMatchRule MatchRule) const;
void getMatchRules(const LangOptions &LangOpts,
SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>>
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 70cc92a06e271..36e6d1e319e47 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -2447,7 +2447,7 @@ class Sema final : public SemaBase {
bool SkipArgCountCheck = false);
bool checkCommonAttributeFeatures(const Stmt *S, const ParsedAttr &A,
bool SkipArgCountCheck = false);
- bool checkCommonAttributeFeatures(const ParsedAttr &A,
+ bool checkCommonAttributeFeatures(QualType T, const ParsedAttr &A,
bool SkipArgCountCheck = false);
///@}
diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp
index 9b995059048c7..a25e9b591860b 100644
--- a/clang/lib/Sema/SemaAttr.cpp
+++ b/clang/lib/Sema/SemaAttr.cpp
@@ -1620,16 +1620,32 @@ void Sema::PopPragmaVisibility(bool IsNamespaceEnd, SourceLocation EndLoc) {
FreeVisContext();
}
-static bool checkCommonAttributeFeatures(Sema &S, const ParsedAttr &A,
+// 'Subject' is the entity the attribute appertains to: a Decl, a Stmt, or a
+// QualType. Attr.td subject lists currently only accept declarations and
+// statements, so the appertainment and mutual exclusion checks for a QualType
+// are stubs that always succeed.
+template <typename SubjectTy>
+static bool checkCommonAttributeFeatures(Sema &S, SubjectTy Subject,
+ const ParsedAttr &A,
bool SkipArgCountCheck) {
- // We bail on unknown and ignored attributes because those are handled as
- // part of the target-specific handling logic.
+ // Several attributes carry different semantics than the parsing requires, so
+ // those are opted out of the common argument checks.
+ //
+ // We also bail on unknown and ignored attributes because those are handled
+ // as part of the target-specific handling logic.
if (A.getKind() == ParsedAttr::UnknownAttribute)
return false;
// Check whether the attribute requires specific language extensions to be
// enabled.
if (!A.diagnoseLangOpts(S))
return true;
+ // Check whether the attribute appertains to the given subject.
+ if (!A.diagnoseAppertainsTo(S, Subject))
+ return true;
+ // Check whether the attribute is mutually exclusive with other attributes
+ // that have already been applied to the declaration.
+ if (!A.diagnoseMutualExclusion(S, Subject))
+ return true;
// Check whether the attribute exists in the target architecture.
if (S.CheckAttrTarget(A))
return true;
@@ -1656,25 +1672,6 @@ static bool checkCommonAttributeFeatures(Sema &S, const ParsedAttr &A,
return false;
}
-template <typename Ty>
-static bool checkCommonAttributeFeatures(Sema &S, const Ty *Node,
- const ParsedAttr &A,
- bool SkipArgCountCheck) {
- // Run the checks shared with type attributes (language options, target, and
- // argument count). This also bails on unknown and ignored attributes.
- if (checkCommonAttributeFeatures(S, A, SkipArgCountCheck))
- return true;
- // Check whether the attribute appertains to the given subject.
- if (!A.diagnoseAppertainsTo(S, Node))
- return true;
- // Check whether the attribute is mutually exclusive with other attributes
- // that have already been applied to the declaration.
- if (!A.diagnoseMutualExclusion(S, Node))
- return true;
-
- return false;
-}
-
bool Sema::checkCommonAttributeFeatures(const Decl *D, const ParsedAttr &A,
bool SkipArgCountCheck) {
return ::checkCommonAttributeFeatures(*this, D, A, SkipArgCountCheck);
@@ -1683,7 +1680,7 @@ bool Sema::checkCommonAttributeFeatures(const Stmt *S, const ParsedAttr &A,
bool SkipArgCountCheck) {
return ::checkCommonAttributeFeatures(*this, S, A, SkipArgCountCheck);
}
-bool Sema::checkCommonAttributeFeatures(const ParsedAttr &A,
+bool Sema::checkCommonAttributeFeatures(QualType T, const ParsedAttr &A,
bool SkipArgCountCheck) {
- return ::checkCommonAttributeFeatures(*this, A, SkipArgCountCheck);
+ return ::checkCommonAttributeFeatures(*this, T, A, SkipArgCountCheck);
}
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index b6ccc52504e4f..88f8bf6a5bcbe 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -9044,7 +9044,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type,
}
if (attr.isTypeAttr() &&
- state.getSema().checkCommonAttributeFeatures(attr)) {
+ state.getSema().checkCommonAttributeFeatures(type, attr)) {
attr.setInvalid();
continue;
}
diff --git a/clang/test/Sema/attr-btf_tag.c b/clang/test/Sema/attr-btf_tag.c
index e58420e0dd277..cbb21a5a88bb6 100644
--- a/clang/test/Sema/attr-btf_tag.c
+++ b/clang/test/Sema/attr-btf_tag.c
@@ -29,11 +29,11 @@ enum e1 {
enum e2 {
E2
-} __tag_no_arg; // expected-error {{'btf_decl_tag' attribute takes one argument}}
+} __tag_no_arg; // expected-error {{'btf_decl_tag' attribute only applies to variables, functions, structs, unions, classes, non-static data members, and typedefs}}
enum e3 {
E3
-} __tag_2_arg; // expected-error {{'btf_decl_tag' attribute takes one argument}}
+} __tag_2_arg; // expected-error {{'btf_decl_tag' attribute only applies to variables, functions, structs, unions, classes, non-static data members, and typedefs}}
int __tag1 __tag2 foo(struct t1 *arg, struct t2 *arg2);
int __tag2 __tag3 foo(struct t1 *arg, struct t2 *arg2);
diff --git a/clang/test/Sema/attr-function-return.c b/clang/test/Sema/attr-function-return.c
index be72a9916e9c6..d2c9156da7ab6 100644
--- a/clang/test/Sema/attr-function-return.c
+++ b/clang/test/Sema/attr-function-return.c
@@ -20,4 +20,4 @@ __attribute__((function_return(5))) void a(void) {}
__attribute__((function_return)) void b(void) {}
// expected-warning at +1 {{'function_return' attribute only applies to functions}}
-__attribute__((function_return("keep"))) int c;
+__attribute__((function_return)) int c;
diff --git a/clang/test/SemaCXX/attr-unsafe-buffer-usage.cpp b/clang/test/SemaCXX/attr-unsafe-buffer-usage.cpp
index fcadd706c4b40..cab67784d9075 100644
--- a/clang/test/SemaCXX/attr-unsafe-buffer-usage.cpp
+++ b/clang/test/SemaCXX/attr-unsafe-buffer-usage.cpp
@@ -3,5 +3,4 @@
// Function annotations.
[[clang::unsafe_buffer_usage]]
void f(int *buf, int size);
-void g(int *buffer [[clang::unsafe_buffer_usage]], int size); // expected-warning {{'clang::unsafe_buffer_usage' attribute only applies to functions}}
-void h(int *buffer [[clang::unsafe_buffer_usage("buffer")]], int size); // expected-error {{'clang::unsafe_buffer_usage' attribute takes no arguments}}
+void g(int *buffer [[clang::unsafe_buffer_usage("buffer")]], int size); // expected-warning {{'clang::unsafe_buffer_usage' attribute only applies to functions}}
diff --git a/clang/test/SemaSYCL/sycl-address-space-attr-ignored.cpp b/clang/test/SemaSYCL/sycl-address-space-attr-ignored.cpp
new file mode 100644
index 0000000000000..4857aaf000d9a
--- /dev/null
+++ b/clang/test/SemaSYCL/sycl-address-space-attr-ignored.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -x c++ %s
+// RUN: %clang_cc1 -fsyntax-only -verify -x clcpp %s
+// RUN: %clang_cc1 -fsyntax-only -verify -x cuda %s
+// RUN: %clang_cc1 -fsyntax-only -verify -x hip %s
+
+// The SYCL address space attributes are only enabled in SYCL compilations.
+
+// expected-warning at +1 {{'clang::sycl_global' attribute ignored}}
+using global_ptr = int [[clang::sycl_global]] *;
+
+// expected-warning at +1 {{'clang::sycl_local' attribute ignored}}
+using local_ptr = int [[clang::sycl_local]] *;
+
+// expected-warning at +1 {{'clang::sycl_private' attribute ignored}}
+using private_ptr = int [[clang::sycl_private]] *;
+
+// expected-warning at +1 {{'clang::sycl_generic' attribute ignored}}
+using generic_ptr = int [[clang::sycl_generic]] *;
+
+// expected-warning at +1 {{'clang::sycl_constant' attribute ignored}}
+using constant_ptr = int [[clang::sycl_constant]] *;
diff --git a/clang/test/SemaSYCL/sycl-address-space-attr-on-non-sycl.cpp b/clang/test/SemaSYCL/sycl-address-space-attr-on-non-sycl.cpp
deleted file mode 100644
index 583bea7ac5c36..0000000000000
--- a/clang/test/SemaSYCL/sycl-address-space-attr-on-non-sycl.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -fsycl-is-device -verify %s
-// RUN: %clang_cc1 -fsyntax-only -fsycl-is-host -verify %s
-// RUN: %clang_cc1 -fsyntax-only -verify -x c++ %s
-
-// The SYCL address space attributes are only enabled in SYCL compilations.
-
-#ifndef SYCL_LANGUAGE_VERSION
-// expected-warning@#global {{'clang::sycl_global' attribute ignored}}
-// expected-warning@#local {{'clang::sycl_local' attribute ignored}}
-// expected-warning@#private {{'clang::sycl_private' attribute ignored}}
-// expected-warning@#generic {{'clang::sycl_generic' attribute ignored}}
-// expected-warning@#constant {{'clang::sycl_constant' attribute ignored}}
-#else
-// expected-no-diagnostics
-#endif
-
-using global_ptr = int [[clang::sycl_global]] *; // #global
-using local_ptr = int [[clang::sycl_local]] *; // #local
-using private_ptr = int [[clang::sycl_private]] *; // #private
-using generic_ptr = int [[clang::sycl_generic]] *; // #generic
-using constant_ptr = int [[clang::sycl_constant]] *; // #constant
>From 3f9281f6c0354cf16a3ad894f1feae05f86df2a9 Mon Sep 17 00:00:00 2001
From: Elizabeth Andrews <elizabeth.andrews at intel.com>
Date: Mon, 12 Oct 2026 06:54:10 -0700
Subject: [PATCH 3/3] Add swift_attr test
---
clang/test/SemaObjC/validate-attr-swift_attr.m | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/clang/test/SemaObjC/validate-attr-swift_attr.m b/clang/test/SemaObjC/validate-attr-swift_attr.m
index c7511098804a7..e0cfd02e99af6 100644
--- a/clang/test/SemaObjC/validate-attr-swift_attr.m
+++ b/clang/test/SemaObjC/validate-attr-swift_attr.m
@@ -13,3 +13,11 @@ @interface J
@interface Error<T: __attribute__((swift_attr(1))) id>
// expected-error at -1 {{expected string literal as argument of 'swift_attr' attribute}}
@end
+
+// expected-error at +1 {{'swift_attr' attribute takes one argument}}
+ at interface NoArg<T: __attribute__((swift_attr)) id>
+ at end
+
+// expected-error at +1 {{'swift_attr' attribute takes one argument}}
+I * __attribute__((swift_attr)) obj;
+
More information about the cfe-commits
mailing list