aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/ast/rust-ast-full-test.cc9
-rw-r--r--gcc/rust/ast/rust-ast.h2
-rw-r--r--gcc/rust/ast/rust-macro.h8
-rw-r--r--gcc/rust/backend/rust-compile-base.cc73
-rw-r--r--gcc/rust/backend/rust-compile-base.h3
-rw-r--r--gcc/rust/backend/rust-mangle.cc6
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-type.cc47
-rw-r--r--gcc/rust/rust-gcc.cc10
-rw-r--r--gcc/rust/util/rust-attributes.cc1
-rw-r--r--gcc/testsuite/rust/compile/attr_deprecated.rs14
-rw-r--r--gcc/testsuite/rust/compile/attr_deprecated_2.rs11
11 files changed, 181 insertions, 3 deletions
diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast-full-test.cc
index 0d4d36b..8179113 100644
--- a/gcc/rust/ast/rust-ast-full-test.cc
+++ b/gcc/rust/ast/rust-ast-full-test.cc
@@ -20,10 +20,12 @@ along with GCC; see the file COPYING3. If not see
// FIXME: This does not work on Windows
#include <string>
#include <unistd.h>
+#include <memory>
#include "rust-ast-full.h"
#include "rust-diagnostics.h"
#include "rust-ast-visitor.h"
+#include "rust-macro.h"
#include "rust-session-manager.h"
#include "rust-lex.h"
#include "rust-parse.h"
@@ -3862,7 +3864,12 @@ MetaItemInner::~MetaItemInner () = default;
std::unique_ptr<MetaNameValueStr>
MetaItemInner::to_meta_name_value_str () const
{
- // TODO parse foo = bar
+ if (is_key_value_pair ())
+ {
+ auto converted_item = static_cast<const MetaNameValueStr *> (this);
+ return converted_item->to_meta_name_value_str ();
+ }
+ // TODO actually parse foo = bar
return nullptr;
}
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 76324dc..51fe3c4 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -645,6 +645,8 @@ public:
virtual Attribute to_attribute () const { return Attribute::create_empty (); }
virtual bool check_cfg_predicate (const Session &session) const = 0;
+
+ virtual bool is_key_value_pair () const { return false; }
};
// Container used to store MetaItems as AttrInput (bridge-ish kinda thing)
diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h
index 1bf8912..ce515db 100644
--- a/gcc/rust/ast/rust-macro.h
+++ b/gcc/rust/ast/rust-macro.h
@@ -21,6 +21,7 @@
#include "rust-ast.h"
#include "rust-location.h"
+#include <string>
namespace Rust {
namespace AST {
@@ -816,6 +817,13 @@ public:
Attribute to_attribute () const override;
+ inline std::pair<Identifier, std::string> get_name_value_pair () const
+ {
+ return std::pair<Identifier, std::string> (ident, str);
+ }
+
+ bool is_key_value_pair () const override { return true; }
+
protected:
// Use covariance to implement clone function as returning this type
MetaNameValueStr *clone_meta_item_inner_impl () const override
diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc
index 8fa3fa1..066ef43 100644
--- a/gcc/rust/backend/rust-compile-base.cc
+++ b/gcc/rust/backend/rust-compile-base.cc
@@ -22,7 +22,8 @@
#include "rust-compile-fnparam.h"
#include "rust-compile-var-decl.h"
-#include "rust-expr.h" // for AST::AttrInputLiteral
+#include "rust-expr.h" // for AST::AttrInputLiteral
+#include "rust-macro.h" // for AST::MetaNameValueStr
#include "fold-const.h"
#include "stringpool.h"
@@ -66,6 +67,9 @@ HIRCompileBase::setup_fndecl (tree fndecl, bool is_main_entry_point,
bool is_link_section
= attr.get_path ().as_string ().compare ("link_section") == 0;
bool no_mangle = attr.get_path ().as_string ().compare ("no_mangle") == 0;
+ bool is_deprecated
+ = attr.get_path ().as_string ().compare ("deprecated") == 0;
+
if (is_inline)
{
handle_inline_attribute_on_fndecl (fndecl, attr);
@@ -82,6 +86,10 @@ HIRCompileBase::setup_fndecl (tree fndecl, bool is_main_entry_point,
{
handle_link_section_attribute_on_fndecl (fndecl, attr);
}
+ else if (is_deprecated)
+ {
+ handle_deprecated_attribute_on_fndecl (fndecl, attr);
+ }
else if (no_mangle)
{
handle_no_mangle_attribute_on_fndecl (fndecl, attr);
@@ -148,6 +156,69 @@ HIRCompileBase::handle_no_mangle_attribute_on_fndecl (
}
void
+HIRCompileBase::handle_deprecated_attribute_on_fndecl (
+ tree fndecl, const AST::Attribute &attr)
+{
+ tree value = NULL_TREE;
+ TREE_DEPRECATED (fndecl) = 1;
+
+ // simple #[deprecated]
+ if (!attr.has_attr_input ())
+ return;
+
+ const AST::AttrInput &input = attr.get_attr_input ();
+ auto input_type = input.get_attr_input_type ();
+
+ if (input_type == AST::AttrInput::AttrInputType::LITERAL)
+ {
+ // handle #[deprecated = "message"]
+ auto &literal
+ = static_cast<AST::AttrInputLiteral &> (attr.get_attr_input ());
+ const auto &msg_str = literal.get_literal ().as_string ();
+ value = build_string (msg_str.size (), msg_str.c_str ());
+ }
+ else if (input_type == AST::AttrInput::AttrInputType::TOKEN_TREE)
+ {
+ // handle #[deprecated(since = "...", note = "...")]
+ const auto &option = static_cast<const AST::DelimTokenTree &> (input);
+ AST::AttrInputMetaItemContainer *meta_item = option.parse_to_meta_item ();
+ for (const auto &item : meta_item->get_items ())
+ {
+ auto converted_item = item->to_meta_name_value_str ();
+ if (!converted_item)
+ continue;
+ auto key_value = converted_item->get_name_value_pair ();
+ if (key_value.first.compare ("since") == 0)
+ {
+ // valid, but this is handled by Cargo and some third-party audit
+ // tools
+ continue;
+ }
+ else if (key_value.first.compare ("note") == 0)
+ {
+ const auto &msg_str = key_value.second;
+ if (value)
+ rust_error_at (attr.get_locus (), "multiple %<note%> items");
+ value = build_string (msg_str.size (), msg_str.c_str ());
+ }
+ else
+ {
+ rust_error_at (attr.get_locus (), "unknown meta item %qs",
+ key_value.first.c_str ());
+ }
+ }
+ }
+
+ if (value)
+ {
+ tree attr_list = build_tree_list (NULL_TREE, value);
+ DECL_ATTRIBUTES (fndecl)
+ = tree_cons (get_identifier ("deprecated"), attr_list,
+ DECL_ATTRIBUTES (fndecl));
+ }
+}
+
+void
HIRCompileBase::handle_inline_attribute_on_fndecl (tree fndecl,
const AST::Attribute &attr)
{
diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h
index 52e0568..f993d06 100644
--- a/gcc/rust/backend/rust-compile-base.h
+++ b/gcc/rust/backend/rust-compile-base.h
@@ -92,6 +92,9 @@ protected:
static void
handle_link_section_attribute_on_fndecl (tree fndecl,
const AST::Attribute &attr);
+ static void
+ handle_deprecated_attribute_on_fndecl (tree fndecl,
+ const AST::Attribute &attr);
static void handle_no_mangle_attribute_on_fndecl (tree fndecl,
const AST::Attribute &attr);
diff --git a/gcc/rust/backend/rust-mangle.cc b/gcc/rust/backend/rust-mangle.cc
index c0aea02..4d20207 100644
--- a/gcc/rust/backend/rust-mangle.cc
+++ b/gcc/rust/backend/rust-mangle.cc
@@ -14,6 +14,7 @@ static const std::string kMangledPtr = "$BP$";
static const std::string kMangledLeftSqParen = "$u5b$"; // [
static const std::string kMangledRightSqParen = "$u5d$"; // ]
static const std::string kQualPathBegin = "_" + kMangledSubstBegin;
+static const std::string kMangledComma = "$C$";
namespace Rust {
namespace Compile {
@@ -39,6 +40,9 @@ legacy_mangle_name (const std::string &name)
//
// example::Foo<T>::new:
// _ZN7example12Foo$LT$T$GT$3new17h9a2aacb7fd783515E:
+ //
+ // <example::Identity as example::FnLike<&T,&T>>::call
+ // _ZN74_$LT$example..Identity$u20$as$u20$example..FnLike$LT$$RF$T$C$$RF$T$GT$$GT$4call17ha9ee58935895acb3E
std::string buffer;
for (size_t i = 0; i < name.size (); i++)
@@ -62,6 +66,8 @@ legacy_mangle_name (const std::string &name)
m = kMangledLeftSqParen;
else if (c == ']')
m = kMangledRightSqParen;
+ else if (c == ',')
+ m = kMangledComma;
else if (c == ':')
{
rust_assert (i + 1 < name.size ());
diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc b/gcc/rust/resolve/rust-ast-resolve-type.cc
index 5d0ceb5..a823543 100644
--- a/gcc/rust/resolve/rust-ast-resolve-type.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-type.cc
@@ -356,7 +356,52 @@ ResolveTypeToCanonicalPath::visit (AST::TypePath &path)
if (mappings->lookup_canonical_path (mappings->get_current_crate (),
resolved_node, &type_path))
{
- result = *type_path;
+ auto &final_seg = path.get_segments ().back ();
+ switch (final_seg->get_type ())
+ {
+ case AST::TypePathSegment::SegmentType::GENERIC: {
+ AST::TypePathSegmentGeneric *s
+ = static_cast<AST::TypePathSegmentGeneric *> (final_seg.get ());
+
+ std::vector<CanonicalPath> args;
+ if (s->has_generic_args ())
+ {
+ for (auto &gt : s->get_generic_args ().get_type_args ())
+ {
+ CanonicalPath arg = CanonicalPath::create_empty ();
+ bool ok = ResolveTypeToCanonicalPath::go (gt.get (), arg);
+ if (ok)
+ args.push_back (std::move (arg));
+ }
+ }
+
+ result = *type_path;
+ if (!args.empty ())
+ {
+ // append this onto the path
+ std::string buf;
+ for (size_t i = 0; i < args.size (); i++)
+ {
+ bool has_next = (i + 1) < args.size ();
+ const auto &arg = args.at (i);
+
+ buf += arg.get ();
+ if (has_next)
+ buf += ", ";
+ }
+
+ std::string arg_seg = "<" + buf + ">";
+ CanonicalPath argument_seg
+ = CanonicalPath::new_seg (s->get_node_id (), arg_seg);
+ result = result.append (argument_seg);
+ }
+ }
+ break;
+
+ default:
+ result = *type_path;
+ break;
+ }
}
}
diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc
index 445cb0d..4fea6fb 100644
--- a/gcc/rust/rust-gcc.cc
+++ b/gcc/rust/rust-gcc.cc
@@ -51,6 +51,8 @@
#include "rust-backend.h"
#include "rust-object-export.h"
+#include "backend/rust-tree.h"
+
// TODO: this will have to be significantly modified to work with Rust
// Bvariable is a bit more complicated, because of zero-sized types.
@@ -1852,6 +1854,14 @@ Gcc_backend::call_expression (tree fn, const std::vector<tree> &fn_args,
excess_type != NULL_TREE ? excess_type : rettype,
fn, nargs, args);
+ // check for deprecated function usage
+ if (fndecl && TREE_DEPRECATED (fndecl))
+ {
+ // set up the call-site information for `warn_deprecated_use`
+ input_location = location.gcc_location ();
+ warn_deprecated_use (fndecl, NULL_TREE);
+ }
+
if (chain_expr)
CALL_EXPR_STATIC_CHAIN (ret) = chain_expr;
diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc
index c36d462..870ca21 100644
--- a/gcc/rust/util/rust-attributes.cc
+++ b/gcc/rust/util/rust-attributes.cc
@@ -27,6 +27,7 @@ static const BuiltinAttrDefinition __definitions[] = {
{"cold", CODE_GENERATION},
{"cfg", EXPANSION},
{"cfg_attr", EXPANSION},
+ {"deprecated", STATIC_ANALYSIS},
{"allow", STATIC_ANALYSIS},
{"doc", HIR_LOWERING},
{"must_use", STATIC_ANALYSIS},
diff --git a/gcc/testsuite/rust/compile/attr_deprecated.rs b/gcc/testsuite/rust/compile/attr_deprecated.rs
new file mode 100644
index 0000000..01bc9c4
--- /dev/null
+++ b/gcc/testsuite/rust/compile/attr_deprecated.rs
@@ -0,0 +1,14 @@
+#[deprecated(since="1.0", note="do not use this function")]
+fn test1() {}
+
+#[deprecated]
+fn test() {}
+
+#[deprecated = "a different message"]
+fn test2() {}
+
+fn main() {
+ test(); // { dg-warning ".attr_deprecated::test. is deprecated" }
+ test1(); // { dg-warning ".attr_deprecated::test1. is deprecated: do not use this function" }
+ test2(); // { dg-warning ".attr_deprecated::test2. is deprecated: a different message" }
+}
diff --git a/gcc/testsuite/rust/compile/attr_deprecated_2.rs b/gcc/testsuite/rust/compile/attr_deprecated_2.rs
new file mode 100644
index 0000000..66f4ce3
--- /dev/null
+++ b/gcc/testsuite/rust/compile/attr_deprecated_2.rs
@@ -0,0 +1,11 @@
+#[deprecated(since="1.0")]
+fn test1() {}
+
+// { dg-excess-errors "unknown meta item ...." }
+#[deprecated(invalid="invalid")]
+fn test2() {}
+
+fn main() {
+ test1(); // { dg-warning ".attr_deprecated_2::test1. is deprecated" }
+ test2();
+}