// Copyright (C) 2020-2023 Free Software Foundation, Inc.
// This file is part of GCC.
// GCC is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 3, or (at your option) any later
// version.
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
// You should have received a copy of the GNU General Public License
// along with GCC; see the file COPYING3. If not see
// .
#include "rust-feature-gate.h"
#include "rust-abi.h"
namespace Rust {
void
FeatureGate::check (AST::Crate &crate)
{
valid_features.clear ();
for (const auto &attr : crate.inner_attrs)
{
if (attr.get_path ().as_string () == "feature")
{
const auto &attr_input = attr.get_attr_input ();
auto type = attr_input.get_attr_input_type ();
if (type == AST::AttrInput::AttrInputType::TOKEN_TREE)
{
const auto &option = static_cast (
attr.get_attr_input ());
std::unique_ptr meta_item (
option.parse_to_meta_item ());
for (const auto &item : meta_item->get_items ())
{
const auto &name_str = item->as_string ();
auto tname = Feature::as_name (name_str);
if (!tname.is_none ())
{
auto name = tname.get ();
valid_features.insert (name);
}
else
rust_error_at (item->get_locus (), "unknown feature '%s'",
name_str.c_str ());
}
}
}
}
auto &items = crate.items;
for (auto it = items.begin (); it != items.end (); it++)
{
auto &item = *it;
item->accept_vis (*this);
}
}
void
FeatureGate::gate (Feature::Name name, Location loc,
const std::string &error_msg)
{
if (!valid_features.count (name))
{
auto feature = Feature::create (name);
auto issue = feature.issue ();
if (issue > 0)
{
const char *fmt_str
= "%s. see issue %ld "
" for more "
"information. add `#![feature(%s)]` to the crate attributes to "
"enable.";
rust_error_at (loc, fmt_str, error_msg.c_str (), issue, issue,
feature.as_string ().c_str ());
}
else
{
const char *fmt_str
= "%s. add `#![feature(%s)]` to the crate attributes to enable.";
rust_error_at (loc, fmt_str, error_msg.c_str (),
feature.as_string ().c_str ());
}
}
}
void
FeatureGate::visit (AST::ExternBlock &block)
{
if (block.has_abi ())
{
const auto abi = block.get_abi ();
if (get_abi_from_string (abi) == ABI::INTRINSIC)
gate (Feature::Name::INTRINSICS, block.get_locus (),
"intrinsics are subject to change");
}
}
} // namespace Rust