]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: proc error on invalid type
authorMason Pike <m@sonpike.net>
Thu, 25 Dec 2025 21:15:57 +0000 (22:15 +0100)
committerArthur Cohen <arthur.cohen@embecosm.com>
Fri, 27 Feb 2026 14:57:07 +0000 (15:57 +0100)
fixes Rust-GCC/gccrs#4235

gcc/rust/ChangeLog:
* util/rust-attributes.cc: add new function to validate that an
attribute is assigned to a valid item type

gcc/testsuite/ChangeLog:
* rust/compile/issue-4232.rs: update expected error to include
the specific illegal attribute

Signed-off-by: Mason Pike <m@sonpike.net>
gcc/rust/util/rust-attributes.cc
gcc/testsuite/rust/compile/issue-4232.rs
gcc/testsuite/rust/compile/issue-4235.rs [new file with mode: 0644]

index 4a0422d3fba1503e197fe8797c67615a5197e9ef..6c0fa0ea07091d8da14c1ff7284229428c6fda4d 100644 (file)
@@ -369,6 +369,45 @@ check_deprecated_attribute (const AST::Attribute &attribute)
     }
 }
 
+/**
+ * Emit an error when an attribute is attached
+ * to an incompatable item type. e.g.:
+ *
+ * #[cold]
+ * struct A(u8, u8);
+ *
+ * Note that "#[derive]" is handled
+ * explicitly in rust-derive.cc
+ */
+static void
+check_valid_attribute_for_item (const AST::AttrVec &attributes,
+                               const AST::Item &item)
+{
+  for (auto &attr : attributes)
+    {
+      if (item.get_item_kind () != AST::Item::Kind::Function
+         && (attr.get_path () == Values::Attributes::TARGET_FEATURE
+             || attr.get_path () == Values::Attributes::COLD
+             || attr.get_path () == Values::Attributes::INLINE))
+       {
+         rust_error_at (
+           attr.get_locus (),
+           "the %<#[%s]%> attribute may only be applied to functions",
+           attr.get_path ().as_string ().c_str ());
+       }
+      else if (attr.get_path () == Values::Attributes::REPR
+              && item.get_item_kind () == AST::Item::Kind::Enum
+              && item.get_item_kind () == AST::Item::Kind::Union
+              && item.get_item_kind () == AST::Item::Kind::Struct)
+       {
+         rust_error_at (attr.get_locus (),
+                        "the %<#[%s]%> attribute may only be applied "
+                        "to structs, enums and unions",
+                        attr.get_path ().as_string ().c_str ());
+       }
+    }
+}
+
 static bool
 is_proc_macro_type (const AST::Attribute &attribute)
 {
@@ -809,6 +848,7 @@ AttributeChecker::visit (AST::TypeBoundWhereClauseItem &)
 void
 AttributeChecker::visit (AST::Module &module)
 {
+  check_valid_attribute_for_item (module.get_outer_attrs (), module);
   check_attributes (module.get_outer_attrs ());
   check_proc_macro_non_function (module.get_outer_attrs ());
   for (auto &item : module.get_items ())
@@ -821,6 +861,7 @@ AttributeChecker::visit (AST::Module &module)
 void
 AttributeChecker::visit (AST::ExternCrate &crate)
 {
+  check_valid_attribute_for_item (crate.get_outer_attrs (), crate);
   check_proc_macro_non_function (crate.get_outer_attrs ());
 }
 
@@ -839,6 +880,7 @@ AttributeChecker::visit (AST::UseTreeRebind &)
 void
 AttributeChecker::visit (AST::UseDeclaration &declaration)
 {
+  check_valid_attribute_for_item (declaration.get_outer_attrs (), declaration);
   check_proc_macro_non_function (declaration.get_outer_attrs ());
 }
 
@@ -861,6 +903,7 @@ check_no_mangle_function (const AST::Attribute &attribute,
 void
 AttributeChecker::visit (AST::Function &fun)
 {
+  check_valid_attribute_for_item (fun.get_outer_attrs (), fun);
   auto check_crate_type = [] (const char *name, AST::Attribute &attribute) {
     if (!Session::get_instance ().options.is_proc_macro ())
       rust_error_at (attribute.get_locus (),
@@ -943,12 +986,6 @@ AttributeChecker::visit (AST::Function &fun)
        {
          check_link_section_attribute (attribute);
        }
-      else if (result.name == Attrs::REPR)
-       {
-         rust_error_at (
-           attribute.get_locus (),
-           "attribute should be applied to a struct, enum, or union");
-       }
     }
 
   if (fun.has_body ())
@@ -958,12 +995,14 @@ AttributeChecker::visit (AST::Function &fun)
 void
 AttributeChecker::visit (AST::TypeAlias &alias)
 {
+  check_valid_attribute_for_item (alias.get_outer_attrs (), alias);
   check_proc_macro_non_function (alias.get_outer_attrs ());
 }
 
 void
 AttributeChecker::visit (AST::StructStruct &struct_item)
 {
+  check_valid_attribute_for_item (struct_item.get_outer_attrs (), struct_item);
   check_attributes (struct_item.get_outer_attrs ());
   check_proc_macro_non_function (struct_item.get_outer_attrs ());
 }
@@ -971,6 +1010,7 @@ AttributeChecker::visit (AST::StructStruct &struct_item)
 void
 AttributeChecker::visit (AST::TupleStruct &tuplestruct)
 {
+  check_valid_attribute_for_item (tuplestruct.get_outer_attrs (), tuplestruct);
   check_proc_macro_non_function (tuplestruct.get_outer_attrs ());
 }
 
@@ -993,24 +1033,28 @@ AttributeChecker::visit (AST::EnumItemDiscriminant &)
 void
 AttributeChecker::visit (AST::Enum &enumeration)
 {
+  check_valid_attribute_for_item (enumeration.get_outer_attrs (), enumeration);
   check_proc_macro_non_function (enumeration.get_outer_attrs ());
 }
 
 void
 AttributeChecker::visit (AST::Union &u)
 {
+  check_valid_attribute_for_item (u.get_outer_attrs (), u);
   check_proc_macro_non_function (u.get_outer_attrs ());
 }
 
 void
 AttributeChecker::visit (AST::ConstantItem &item)
 {
+  check_valid_attribute_for_item (item.get_outer_attrs (), item);
   check_proc_macro_non_function (item.get_outer_attrs ());
 }
 
 void
 AttributeChecker::visit (AST::StaticItem &item)
 {
+  check_valid_attribute_for_item (item.get_outer_attrs (), item);
   check_proc_macro_non_function (item.get_outer_attrs ());
 
   BuiltinAttrDefinition result;
@@ -1037,6 +1081,7 @@ AttributeChecker::visit (AST::TraitItemType &)
 void
 AttributeChecker::visit (AST::Trait &trait)
 {
+  check_valid_attribute_for_item (trait.get_outer_attrs (), trait);
   check_proc_macro_non_function (trait.get_outer_attrs ());
   check_attributes (trait.get_outer_attrs ());
 }
@@ -1044,6 +1089,7 @@ AttributeChecker::visit (AST::Trait &trait)
 void
 AttributeChecker::visit (AST::InherentImpl &impl)
 {
+  check_valid_attribute_for_item (impl.get_outer_attrs (), impl);
   check_proc_macro_non_function (impl.get_outer_attrs ());
   AST::DefaultASTVisitor::visit (impl);
 }
@@ -1051,6 +1097,7 @@ AttributeChecker::visit (AST::InherentImpl &impl)
 void
 AttributeChecker::visit (AST::TraitImpl &impl)
 {
+  check_valid_attribute_for_item (impl.get_outer_attrs (), impl);
   check_proc_macro_non_function (impl.get_outer_attrs ());
   AST::DefaultASTVisitor::visit (impl);
 }
@@ -1066,6 +1113,7 @@ AttributeChecker::visit (AST::ExternalStaticItem &)
 void
 AttributeChecker::visit (AST::ExternBlock &block)
 {
+  check_valid_attribute_for_item (block.get_outer_attrs (), block);
   check_proc_macro_non_function (block.get_outer_attrs ());
 }
 
index fa12538808d84c8837d212f9eec131fcfd3d5280..96a896665b281d6b60c7879ffcb84724ec9a0513 100644 (file)
@@ -1,3 +1,3 @@
 // { dg-options "-w" }
-#[repr(C)] // { dg-error "attribute should be applied to a struct, enum, or union" }
-fn a() {}
\ No newline at end of file
+#[repr(C)] // { dg-error "the ...repr.. attribute may only be applied to structs, enums and unions" }
+fn a() {}
diff --git a/gcc/testsuite/rust/compile/issue-4235.rs b/gcc/testsuite/rust/compile/issue-4235.rs
new file mode 100644 (file)
index 0000000..5febf1f
--- /dev/null
@@ -0,0 +1,2 @@
+#[target_feature(enable = "sse")] // { dg-error "the ...target_feature.. attribute may only be applied to functions" }
+struct _Test {}