Branch data Line data Source code
1 : : // Copyright (C) 2020-2024 Free Software Foundation, Inc.
2 : :
3 : : // This file is part of GCC.
4 : :
5 : : // GCC is free software; you can redistribute it and/or modify it under
6 : : // the terms of the GNU General Public License as published by the Free
7 : : // Software Foundation; either version 3, or (at your option) any later
8 : : // version.
9 : :
10 : : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 : : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : : // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 : : // for more details.
14 : :
15 : : // You should have received a copy of the GNU General Public License
16 : : // along with GCC; see the file COPYING3. If not see
17 : : // <http://www.gnu.org/licenses/>.
18 : :
19 : : #include "rust-feature-gate.h"
20 : : #include "rust-abi.h"
21 : : #include "rust-ast-visitor.h"
22 : :
23 : : namespace Rust {
24 : :
25 : : void
26 : 3618 : FeatureGate::check (AST::Crate &crate)
27 : : {
28 : 3618 : visit (crate);
29 : 3618 : }
30 : :
31 : : void
32 : 3618 : FeatureGate::visit (AST::Crate &crate)
33 : : {
34 : 3618 : valid_features.clear ();
35 : :
36 : 4095 : for (const auto &attr : crate.inner_attrs)
37 : : {
38 : 477 : if (attr.get_path ().as_string () == "feature")
39 : : {
40 : 358 : const auto &attr_input = attr.get_attr_input ();
41 : 358 : auto type = attr_input.get_attr_input_type ();
42 : 358 : if (type == AST::AttrInput::AttrInputType::TOKEN_TREE)
43 : : {
44 : 358 : const auto &option = static_cast<const AST::DelimTokenTree &> (
45 : 358 : attr.get_attr_input ());
46 : 358 : std::unique_ptr<AST::AttrInputMetaItemContainer> meta_item (
47 : 358 : option.parse_to_meta_item ());
48 : 716 : for (const auto &item : meta_item->get_items ())
49 : : {
50 : 358 : const auto &name_str = item->as_string ();
51 : 358 : auto tname = Feature::as_name (name_str);
52 : 358 : if (tname.has_value ())
53 : : {
54 : 355 : auto name = tname.value ();
55 : 355 : valid_features.insert (name);
56 : : }
57 : :
58 : : else
59 : 3 : rust_error_at (item->get_locus (), ErrorCode::E0635,
60 : : "unknown feature %qs", name_str.c_str ());
61 : 358 : }
62 : 358 : }
63 : : }
64 : : }
65 : :
66 : 3618 : AST::DefaultASTVisitor::visit (crate);
67 : 3618 : }
68 : :
69 : : void
70 : 262 : FeatureGate::gate (Feature::Name name, location_t loc,
71 : : const std::string &error_msg)
72 : : {
73 : 262 : if (!valid_features.count (name))
74 : : {
75 : 5 : auto feature = Feature::create (name);
76 : 5 : auto issue = feature.issue ();
77 : 5 : if (issue > 0)
78 : : {
79 : 1 : const char *fmt_str
80 : : = "%s. see issue %u "
81 : : "<https://github.com/rust-lang/rust/issues/%u> for more "
82 : : "information. add `#![feature(%s)]` to the crate attributes to "
83 : : "enable.";
84 : 1 : rust_error_at (loc, ErrorCode::E0658, fmt_str, error_msg.c_str (),
85 : 1 : issue, issue, feature.as_string ().c_str ());
86 : : }
87 : : else
88 : : {
89 : 4 : const char *fmt_str
90 : : = "%s. add `#![feature(%s)]` to the crate attributes to enable.";
91 : 4 : rust_error_at (loc, ErrorCode::E0658, fmt_str, error_msg.c_str (),
92 : 4 : feature.as_string ().c_str ());
93 : : }
94 : 5 : }
95 : 262 : }
96 : :
97 : : void
98 : 903 : FeatureGate::visit (AST::ExternBlock &block)
99 : : {
100 : 903 : if (block.has_abi ())
101 : : {
102 : 903 : const auto abi = block.get_abi ();
103 : :
104 : 903 : if (get_abi_from_string (abi) == ABI::INTRINSIC)
105 : 152 : gate (Feature::Name::INTRINSICS, block.get_locus (),
106 : : "intrinsics are subject to change");
107 : 903 : }
108 : 903 : AST::DefaultASTVisitor::visit (block);
109 : 903 : }
110 : :
111 : : void
112 : 8986 : FeatureGate::check_rustc_attri (const std::vector<AST::Attribute> &attributes)
113 : : {
114 : 9378 : for (const AST::Attribute &attr : attributes)
115 : : {
116 : 392 : auto name = attr.get_path ().as_string ();
117 : 392 : if (name.rfind ("rustc_", 0) == 0)
118 : : {
119 : 109 : gate (Feature::Name::RUSTC_ATTRS, attr.get_locus (),
120 : : "internal implementation detail");
121 : : }
122 : 392 : }
123 : 8986 : }
124 : :
125 : : void
126 : 596 : FeatureGate::visit (AST::MacroRulesDefinition &rules_def)
127 : : {
128 : 596 : check_rustc_attri (rules_def.get_outer_attrs ());
129 : 596 : }
130 : :
131 : : void
132 : 9711 : FeatureGate::visit (AST::Function &function)
133 : : {
134 : 9711 : if (!function.is_external ())
135 : 8390 : check_rustc_attri (function.get_outer_attrs ());
136 : 9711 : }
137 : :
138 : : void
139 : 1 : FeatureGate::visit (AST::ExternalTypeItem &item)
140 : : {
141 : : // TODO(mxlol233): The gating needs a complete visiting chain to activate
142 : : // `AST::ExternalTypeItem`.
143 : 1 : gate (Feature::Name::EXTERN_TYPES, item.get_locus (),
144 : : "extern types are experimental");
145 : 1 : }
146 : :
147 : : } // namespace Rust
|