From: Mason Pike <[email protected]>
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 <[email protected]>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.
Commit on github:
https://github.com/Rust-GCC/gccrs/commit/74afbcea690c3bb8588a1662fee838e3546dd00e
The commit has been mentioned in the following pull-request(s):
- https://github.com/Rust-GCC/gccrs/pull/4339
gcc/rust/util/rust-attributes.cc | 60 +++++++++++++++++++++---
gcc/testsuite/rust/compile/issue-4232.rs | 4 +-
gcc/testsuite/rust/compile/issue-4235.rs | 2 +
3 files changed, 58 insertions(+), 8 deletions(-)
create mode 100644 gcc/testsuite/rust/compile/issue-4235.rs
diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc
index 4a0422d3f..6c0fa0ea0 100644
--- a/gcc/rust/util/rust-attributes.cc
+++ b/gcc/rust/util/rust-attributes.cc
@@ -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 ());
}
diff --git a/gcc/testsuite/rust/compile/issue-4232.rs
b/gcc/testsuite/rust/compile/issue-4232.rs
index fa1253880..96a896665 100644
--- a/gcc/testsuite/rust/compile/issue-4232.rs
+++ b/gcc/testsuite/rust/compile/issue-4232.rs
@@ -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
index 000000000..5febf1f4d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-4235.rs
@@ -0,0 +1,2 @@
+#[target_feature(enable = "sse")] // { dg-error "the ...target_feature..
attribute may only be applied to functions" }
+struct _Test {}
base-commit: c57cf8312f7b9a1eb475f2693791110c66356e7c
--
2.52.0