[gccrs COMMIT 2/3] attributes: Check if an attribute is a tool attribute

[email protected]
Newsgroups gmane.comp.gcc.rust,gmane.comp.gcc.patches
Message-ID <[email protected]>
From: Arthur Cohen <[email protected]>

Tool attributes are allowed in Rust code, and should be ignored by the
compiler and handled by the specified tools instead.

gcc/rust/ChangeLog:

	* util/rust-attributes.h: Change Attributes::is_known API to return an enum, add
	AttributeKnowledge result enum.
	* util/rust-attribute-values.h: Add more known tool attributes.
	* util/rust-attributes.cc (Attributes::is_known): Check for tool attributes and
	adapt return type.
	* hir/rust-ast-lower-base.cc (ASTLoweringBase::handle_outer_attributes): Use new
	API and ignore tool attributes.
	* resolve/rust-early-name-resolver-2.0.cc (Early::visit): Likewise.

gcc/testsuite/ChangeLog:

	* rust/compile/tool-attribute1.rs: New test.
---
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/95197bbf4951b8e5a823ffecf5e428b35e516e12

The commit has NOT been mentioned in any issue.

The commit has been mentioned in the following pull-request(s):
 - https://github.com/Rust-GCC/gccrs/pull/4752

 gcc/rust/hir/rust-ast-lower-base.cc           |  8 ++++-
 .../resolve/rust-early-name-resolver-2.0.cc   | 16 ++++++----
 gcc/rust/util/rust-attribute-values.h         |  4 +++
 gcc/rust/util/rust-attributes.cc              | 31 +++++++++++++++++--
 gcc/rust/util/rust-attributes.h               | 19 +++++++++++-
 gcc/testsuite/rust/compile/tool-attribute1.rs | 22 +++++++++++++
 6 files changed, 90 insertions(+), 10 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/tool-attribute1.rs

diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc
index 0de6ace8a..a4ab5d5ed 100644
--- a/gcc/rust/hir/rust-ast-lower-base.cc
+++ b/gcc/rust/hir/rust-ast-lower-base.cc
@@ -797,13 +797,19 @@ ASTLoweringBase::handle_outer_attributes (const ItemWrapper &item)
   for (const auto &attr : item.get_outer_attrs ())
     {
       const auto &str_path = attr.get_path ().as_string ();
-      if (!Analysis::Attributes::is_known (str_path))
+      auto known_check = Analysis::Attributes::is_known (str_path);
+      if (known_check == Analysis::Attributes::AttributeKnowledge::Unknown)
 	{
 	  rust_error_at (attr.get_locus (), "unknown attribute: %qs",
 			 str_path.c_str ());
 	  continue;
 	}
 
+      // If it is a tool attribute, the compiler can ignore it and let the tool
+      // handle it
+      if (known_check == Analysis::Attributes::AttributeKnowledge::Tool)
+	return;
+
       bool is_lang_item = str_path == Values::Attributes::LANG
 			  && attr.has_attr_input ()
 			  && attr.get_attr_input ().get_attr_input_type ()
diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
index 830932cdd..8a07f8f29 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
@@ -454,17 +454,21 @@ Early::visit (AST::Attribute &attr)
   auto &mappings = Analysis::Mappings::get ();
 
   auto name = attr.get_path ().get_segments ().at (0).get_segment_name ();
-  auto is_not_builtin = [&name] (AST::Attribute &attr) {
-    return Analysis::BuiltinAttributeMappings::get ()
-      ->lookup_builtin (name)
-      .is_error ();
-  };
+  auto known_check = Analysis::Attributes::is_known (name);
+
+  // If it is a tool attribute, the compiler can ignore it and let the tool
+  // handle it
+  if (known_check == Analysis::Attributes::AttributeKnowledge::Tool)
+    return;
+
+  auto is_builtin
+    = known_check == Analysis::Attributes::AttributeKnowledge::Known;
 
   if (attr.is_derive ())
     {
       visit_derive_attribute (attr, mappings);
     }
-  else if (is_not_builtin (attr)) // Do not resolve builtins
+  else if (!is_builtin) // Do not resolve builtins
     {
       visit_non_builtin_attribute (attr, mappings, name);
     }
diff --git a/gcc/rust/util/rust-attribute-values.h b/gcc/rust/util/rust-attribute-values.h
index 3ab91d35f..e2718ca4a 100644
--- a/gcc/rust/util/rust-attribute-values.h
+++ b/gcc/rust/util/rust-attribute-values.h
@@ -105,6 +105,10 @@ public:
   static constexpr auto &NON_EXHAUSTIVE = "non_exhaustive";
 
   static constexpr auto &RUSTFMT = "rustfmt";
+  static constexpr auto &CLIPPY = "clippy";
+  static constexpr auto &DIAGNOSTIC = "diagnostic";
+  static constexpr auto &MIRI = "miri";
+  static constexpr auto &RUST_ANALYZER = "rust_analyzer";
 
   static constexpr auto &TEST = "test";
 
diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc
index 2ae917fdb..8ab4bc608 100644
--- a/gcc/rust/util/rust-attributes.cc
+++ b/gcc/rust/util/rust-attributes.cc
@@ -94,6 +94,10 @@ static const BuiltinAttrDefinition __definitions[]
      {Attrs::FUNDAMENTAL, TYPE_CHECK},
      {Attrs::NON_EXHAUSTIVE, TYPE_CHECK},
      {Attrs::RUSTFMT, EXTERNAL},
+     {Attrs::CLIPPY, EXTERNAL},
+     {Attrs::DIAGNOSTIC, EXTERNAL},
+     {Attrs::MIRI, EXTERNAL},
+     {Attrs::RUST_ANALYZER, EXTERNAL},
      {Attrs::TEST, CODE_GENERATION},
      {Attrs::NEEDS_ALLOCATOR, CODE_GENERATION},
      {Attrs::RUSTC_ALLOCATOR, CODE_GENERATION},
@@ -120,13 +124,36 @@ static const std::set<std::string> __outer_attributes
      Attrs::LINK_NAME,
      Attrs::LINK_SECTION};
 
-bool
+Attributes::AttributeKnowledge
 Attributes::is_known (const std::string &attribute_path)
 {
   const auto &lookup
     = BuiltinAttributeMappings::get ()->lookup_builtin (attribute_path);
 
-  return !lookup.is_error ();
+  if (!lookup.is_error ())
+    return AttributeKnowledge::Known;
+
+  // We have to check for tool attributes as well
+  // https://doc.rust-lang.org/reference/attributes.html#tool-attributes
+  //
+  // > rustc currently recognizes the tools “clippy”, “rustfmt”, “diagnostic”,
+  // “miri”, and “rust_analyzer”.
+  static std::unordered_set<std::string> known_tools = {
+    "clippy", "rustfmt", "diagnostic", "miri", "rust_analyzer",
+  };
+
+  auto colon = attribute_path.find ("::");
+  if (colon != std::string::npos)
+    {
+      auto tool = attribute_path.substr (0, colon);
+
+      // If this is a known tool, the attribute is "known". The rest of the path
+      // is up to the tool to interpret.
+      if (known_tools.find (tool) != known_tools.end ())
+	return AttributeKnowledge::Tool;
+    }
+
+  return AttributeKnowledge::Unknown;
 }
 
 bool
diff --git a/gcc/rust/util/rust-attributes.h b/gcc/rust/util/rust-attributes.h
index 778cc9e33..c173a3f76 100644
--- a/gcc/rust/util/rust-attributes.h
+++ b/gcc/rust/util/rust-attributes.h
@@ -27,7 +27,24 @@ namespace Analysis {
 class Attributes
 {
 public:
-  static bool is_known (const std::string &attribute_path);
+  enum class AttributeKnowledge
+  {
+    /**
+     * Built-in attribute
+     */
+    Known,
+    /**
+     * Tool attribute, to be handled by the specified tool rather than the
+     * compiler
+     */
+    Tool,
+    /**
+     * Unknown attribute
+     */
+    Unknown,
+  };
+
+  static AttributeKnowledge is_known (const std::string &attribute_path);
   static bool valid_outer_attribute (const std::string &attribute_path);
   static tl::optional<std::string>
   extract_string_literal (const AST::Attribute &attr);
diff --git a/gcc/testsuite/rust/compile/tool-attribute1.rs b/gcc/testsuite/rust/compile/tool-attribute1.rs
new file mode 100644
index 000000000..f8f198f50
--- /dev/null
+++ b/gcc/testsuite/rust/compile/tool-attribute1.rs
@@ -0,0 +1,22 @@
+#![feature(no_core)]
+#![feature(lang_items)]
+#![feature(rustc_attrs)]
+#![no_core]
+
+#[rustfmt::skip]
+pub fn foo() {}
+
+#[clippy::something::useful]
+#[diagnostic::diagnose_this]
+struct Boo;
+
+#[miri::save_us_all]
+unsafe fn scary() {}
+
+#[rust_analyzer::vade_retro]
+unsafe fn stannanas() {}
+
+#[not_a_tool::but_still_tool_like]
+// { dg-error "macro not found" "" { target *-*-* } .-1 }
+// { dg-error "could not resolve attribute macro invocation" "" { target *-*-* } .-2 }
+pub fn ha_exclam() {}
-- 
2.54.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.