1 // Copyright (C) 2020-2023 Free Software Foundation, Inc.
3 // This file is part of GCC.
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
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
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/>.
19 #include "rust-ast-validation.h"
20 #include "rust-common.h"
21 #include "rust-diagnostics.h"
22 #include "rust-item.h"
23 #include "rust-keyword-values.h"
28 ASTValidation::visit (AST::Lifetime
&lifetime
)
30 auto name
= lifetime
.get_lifetime_name ();
31 auto valid
= std::set
<std::string
>{"static", "_"};
32 auto &keywords
= Values::Keywords::keywords
;
34 if (valid
.find (name
) == valid
.end ()
35 && keywords
.find (name
) != keywords
.end ())
36 rust_error_at (lifetime
.get_locus (), "lifetimes cannot use keyword names");
38 AST::ContextualASTVisitor::visit (lifetime
);
42 ASTValidation::visit (AST::LoopLabel
&label
)
44 auto name
= label
.get_lifetime ().get_lifetime_name ();
45 auto lifetime_name
= '\'' + name
;
46 auto &keywords
= Values::Keywords::keywords
;
47 if (keywords
.find (name
) != keywords
.end ())
48 rust_error_at (label
.get_lifetime ().get_locus (), "invalid label name %qs",
49 lifetime_name
.c_str ());
51 // WARNING: Do not call ContextualASTVisitor, we don't want to visit the
53 // Maybe we should refactor LoopLabel instead ?
57 ASTValidation::visit (AST::ConstantItem
&const_item
)
59 if (!const_item
.has_expr () && context
.back () != Context::TRAIT_IMPL
)
61 rust_error_at (const_item
.get_locus (),
62 "associated constant in %<impl%> without body");
64 AST::ContextualASTVisitor::visit (const_item
);
68 ASTValidation::visit (AST::ExternalFunctionItem
&item
)
70 auto ¶ms
= item
.get_function_params ();
72 if (params
.size () == 1 && params
[0].is_variadic ())
74 params
[0].get_locus (),
75 "C-variadic function must be declared with at least one named argument");
77 for (auto it
= params
.begin (); it
!= params
.end (); it
++)
78 if (it
->is_variadic () && it
+ 1 != params
.end ())
81 "%<...%> must be the last argument of a C-variadic function");
83 AST::ContextualASTVisitor::visit (item
);
87 ASTValidation::visit (AST::Union
&item
)
89 if (item
.get_variants ().empty ())
90 rust_error_at (item
.get_locus (), "unions cannot have zero fields");
92 AST::ContextualASTVisitor::visit (item
);
96 ASTValidation::visit (AST::Function
&function
)
98 const auto &qualifiers
= function
.get_qualifiers ();
99 if (qualifiers
.is_async () && qualifiers
.is_const ())
100 rust_error_at (function
.get_locus (),
101 "functions cannot be both %<const%> and %<async%>");
103 if (qualifiers
.is_const ()
104 && (context
.back () == Context::TRAIT_IMPL
105 || context
.back () == Context::TRAIT
))
106 rust_error_at (function
.get_locus (), ErrorCode::E0379
,
107 "functions in traits cannot be declared %<const%>");
110 if (qualifiers
.is_async ()
111 && (context
.back () == Context::TRAIT_IMPL
112 || context
.back () == Context::TRAIT
))
113 rust_error_at (function
.get_locus (), ErrorCode::E0706
,
114 "functions in traits cannot be declared %<async%>");
116 // if not an associated function but has a self parameter
117 if (context
.back () != Context::TRAIT
118 && context
.back () != Context::TRAIT_IMPL
119 && context
.back () != Context::INHERENT_IMPL
120 && function
.has_self_param ())
122 function
.get_self_param ()->get_locus (),
123 "%<self%> parameter is only allowed in associated functions");
125 if (!function
.has_body ())
127 if (context
.back () == Context::INHERENT_IMPL
128 || context
.back () == Context::TRAIT_IMPL
)
129 rust_error_at (function
.get_locus (),
130 "associated function in %<impl%> without body");
131 else if (context
.back () != Context::TRAIT
)
132 rust_error_at (function
.get_locus (), "free function without a body");
135 if (function
.is_variadic ())
137 function
.get_function_params ().back ()->get_locus (),
138 "only foreign or %<unsafe extern \"C\"%> functions may be C-variadic");
140 AST::ContextualASTVisitor::visit (function
);
144 ASTValidation::visit (AST::Trait
&trait
)
146 if (trait
.is_auto ())
148 if (trait
.has_generics ())
149 rust_error_at (trait
.get_generic_params ()[0]->get_locus (),
151 "auto traits cannot have generic parameters");
152 if (trait
.has_type_param_bounds ())
153 rust_error_at (trait
.get_type_param_bounds ()[0]->get_locus (),
155 "auto traits cannot have super traits");
156 if (trait
.has_trait_items ())
158 rust_error_at (trait
.get_identifier ().get_locus (), ErrorCode::E0380
,
159 "auto traits cannot have methods or associated items");
160 for (const auto &item
: trait
.get_trait_items ())
161 Error::Hint (item
->get_locus (), "remove this item").emit ();
165 AST::ContextualASTVisitor::visit (trait
);
169 ASTValidation::visit (AST::Module
&module
)
171 if (module
.get_unsafety () == Unsafety::Unsafe
)
172 rust_error_at (module
.get_locus (), "module cannot be declared unsafe");
174 AST::ContextualASTVisitor::visit (module
);