]>
Commit | Line | Data |
---|---|---|
83ffe9cd | 1 | // Copyright (C) 2020-2023 Free Software Foundation, Inc. |
b1b35204 AC |
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-unsafe-checker.h" | |
20 | #include "rust-hir.h" | |
21 | #include "rust-hir-expr.h" | |
22 | #include "rust-hir-stmt.h" | |
23 | #include "rust-hir-item.h" | |
24 | ||
25 | namespace Rust { | |
26 | namespace HIR { | |
27 | ||
28 | UnsafeChecker::UnsafeChecker () | |
29 | : context (*Resolver::TypeCheckContext::get ()), | |
30 | resolver (*Resolver::Resolver::get ()), | |
31 | mappings (*Analysis::Mappings::get ()) | |
32 | {} | |
33 | ||
34 | void | |
35 | UnsafeChecker::go (HIR::Crate &crate) | |
36 | { | |
37 | for (auto &item : crate.items) | |
38 | item->accept_vis (*this); | |
39 | } | |
40 | ||
41 | static void | |
42 | check_static_mut (HIR::Item *maybe_static, Location locus) | |
43 | { | |
44 | if (maybe_static->get_hir_kind () == Node::BaseKind::VIS_ITEM) | |
45 | { | |
46 | auto item = static_cast<Item *> (maybe_static); | |
47 | if (item->get_item_kind () == Item::ItemKind::Static) | |
48 | { | |
49 | auto static_item = static_cast<StaticItem *> (item); | |
50 | if (static_item->is_mut ()) | |
51 | rust_error_at ( | |
52 | locus, "use of mutable static requires unsafe function or block"); | |
53 | } | |
54 | } | |
55 | } | |
56 | ||
57 | static void | |
58 | check_extern_static (HIR::ExternalItem *maybe_static, Location locus) | |
59 | { | |
60 | if (maybe_static->get_extern_kind () == ExternalItem::ExternKind::Static) | |
61 | rust_error_at (locus, | |
62 | "use of extern static requires unsafe function or block"); | |
63 | } | |
64 | ||
65 | void | |
66 | UnsafeChecker::check_use_of_static (HirId node_id, Location locus) | |
67 | { | |
68 | if (unsafe_context.is_in_context ()) | |
69 | return; | |
70 | ||
71 | auto maybe_static_mut = mappings.lookup_hir_item (node_id); | |
72 | ||
73 | HirId extern_block; | |
74 | auto maybe_extern_static | |
75 | = mappings.lookup_hir_extern_item (node_id, &extern_block); | |
76 | ||
77 | if (maybe_static_mut) | |
78 | check_static_mut (maybe_static_mut, locus); | |
79 | ||
80 | if (maybe_extern_static) | |
81 | check_extern_static (static_cast<ExternalItem *> (maybe_extern_static), | |
82 | locus); | |
83 | } | |
84 | ||
85 | static void | |
86 | check_unsafe_call (HIR::Function *fn, Location locus, const std::string &kind) | |
87 | { | |
88 | if (fn->get_qualifiers ().is_unsafe ()) | |
89 | rust_error_at (locus, "call to unsafe %s requires unsafe function or block", | |
90 | kind.c_str ()); | |
91 | } | |
92 | ||
93 | static bool | |
94 | is_safe_intrinsic (const std::string &fn_name) | |
95 | { | |
96 | static const std::unordered_set<std::string> safe_intrinsics = { | |
97 | "abort", | |
98 | "size_of", | |
99 | "min_align_of", | |
100 | "needs_drop", | |
101 | "caller_location", | |
102 | "add_with_overflow", | |
103 | "sub_with_overflow", | |
104 | "mul_with_overflow", | |
105 | "wrapping_add", | |
106 | "wrapping_sub", | |
107 | "wrapping_mul", | |
108 | "saturating_add", | |
109 | "saturating_sub", | |
110 | "rotate_left", | |
111 | "rotate_right", | |
112 | "ctpop", | |
113 | "ctlz", | |
114 | "cttz", | |
115 | "bswap", | |
116 | "bitreverse", | |
117 | "discriminant_value", | |
118 | "type_id", | |
119 | "likely", | |
120 | "unlikely", | |
121 | "ptr_guaranteed_eq", | |
122 | "ptr_guaranteed_ne", | |
123 | "minnumf32", | |
124 | "minnumf64", | |
125 | "maxnumf32", | |
126 | "rustc_peek", | |
127 | "maxnumf64", | |
128 | "type_name", | |
129 | "forget", | |
130 | "black_box", | |
131 | "variant_count", | |
132 | }; | |
133 | ||
134 | return safe_intrinsics.find (fn_name) != safe_intrinsics.end (); | |
135 | } | |
136 | ||
137 | static void | |
138 | check_extern_call (HIR::ExternalItem *maybe_fn, HIR::ExternBlock *parent_block, | |
139 | Location locus) | |
140 | { | |
141 | // We have multiple operations to perform here | |
142 | // 1. Is the item an actual function we're calling | |
143 | // 2. Is the block it's defined in an FFI block or an `extern crate` block | |
144 | // | |
145 | // It is not unsafe to call into other crates, so items defined in an `extern | |
146 | // crate` must be callable without being in an unsafe context. On the other | |
147 | // hand, any function defined in a block with a specific ABI (even `extern | |
148 | // "Rust"` blocks) is unsafe to call | |
149 | ||
150 | if (maybe_fn->get_extern_kind () != ExternalItem::ExternKind::Function) | |
151 | return; | |
152 | ||
153 | // Some intrinsics are safe to call | |
154 | if (parent_block->get_abi () == Rust::ABI::INTRINSIC | |
155 | && is_safe_intrinsic (maybe_fn->get_item_name ())) | |
156 | return; | |
157 | ||
158 | rust_error_at (locus, | |
159 | "call to extern function requires unsafe function or block"); | |
160 | } | |
161 | ||
162 | void | |
163 | UnsafeChecker::check_function_call (HirId node_id, Location locus) | |
164 | { | |
165 | if (unsafe_context.is_in_context ()) | |
166 | return; | |
167 | ||
168 | HirId parent_extern_block; | |
169 | auto maybe_fn = mappings.lookup_hir_item (node_id); | |
170 | auto maybe_extern | |
171 | = mappings.lookup_hir_extern_item (node_id, &parent_extern_block); | |
172 | ||
173 | if (maybe_fn && maybe_fn->get_item_kind () == Item::ItemKind::Function) | |
174 | check_unsafe_call (static_cast<Function *> (maybe_fn), locus, "function"); | |
175 | ||
176 | if (maybe_extern) | |
177 | check_extern_call (static_cast<ExternalItem *> (maybe_extern), | |
178 | mappings.lookup_hir_extern_block (parent_extern_block), | |
179 | locus); | |
180 | } | |
181 | ||
182 | void | |
183 | UnsafeChecker::visit (Lifetime &lifetime) | |
184 | {} | |
185 | ||
186 | void | |
187 | UnsafeChecker::visit (LifetimeParam &lifetime_param) | |
188 | {} | |
189 | ||
190 | void | |
191 | UnsafeChecker::visit (PathInExpression &path) | |
192 | { | |
193 | NodeId ast_node_id = path.get_mappings ().get_nodeid (); | |
194 | NodeId ref_node_id; | |
195 | HirId definition_id; | |
196 | ||
197 | if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id)) | |
198 | return; | |
199 | ||
200 | rust_assert (mappings.lookup_node_to_hir (ref_node_id, &definition_id)); | |
201 | ||
202 | check_use_of_static (definition_id, path.get_locus ()); | |
203 | } | |
204 | ||
205 | void | |
206 | UnsafeChecker::visit (TypePathSegment &segment) | |
207 | {} | |
208 | ||
209 | void | |
210 | UnsafeChecker::visit (TypePathSegmentGeneric &segment) | |
211 | {} | |
212 | ||
213 | void | |
214 | UnsafeChecker::visit (TypePathSegmentFunction &segment) | |
215 | {} | |
216 | ||
217 | void | |
218 | UnsafeChecker::visit (TypePath &path) | |
219 | {} | |
220 | ||
221 | void | |
222 | UnsafeChecker::visit (QualifiedPathInExpression &path) | |
223 | {} | |
224 | ||
225 | void | |
226 | UnsafeChecker::visit (QualifiedPathInType &path) | |
227 | {} | |
228 | ||
229 | void | |
230 | UnsafeChecker::visit (LiteralExpr &expr) | |
231 | {} | |
232 | ||
233 | void | |
234 | UnsafeChecker::visit (BorrowExpr &expr) | |
235 | { | |
236 | expr.get_expr ()->accept_vis (*this); | |
237 | } | |
238 | ||
239 | void | |
240 | UnsafeChecker::visit (DereferenceExpr &expr) | |
241 | { | |
242 | TyTy::BaseType *to_deref_type; | |
243 | auto to_deref = expr.get_expr ()->get_mappings ().get_hirid (); | |
244 | ||
245 | rust_assert (context.lookup_type (to_deref, &to_deref_type)); | |
246 | ||
247 | if (to_deref_type->get_kind () == TyTy::TypeKind::POINTER | |
248 | && !unsafe_context.is_in_context ()) | |
249 | rust_error_at (expr.get_locus (), "dereference of raw pointer requires " | |
250 | "unsafe function or block"); | |
251 | } | |
252 | ||
253 | void | |
254 | UnsafeChecker::visit (ErrorPropagationExpr &expr) | |
255 | { | |
256 | expr.get_expr ()->accept_vis (*this); | |
257 | } | |
258 | ||
259 | void | |
260 | UnsafeChecker::visit (NegationExpr &expr) | |
261 | { | |
262 | expr.get_expr ()->accept_vis (*this); | |
263 | } | |
264 | ||
265 | void | |
266 | UnsafeChecker::visit (ArithmeticOrLogicalExpr &expr) | |
267 | { | |
268 | expr.get_lhs ()->accept_vis (*this); | |
269 | expr.get_rhs ()->accept_vis (*this); | |
270 | } | |
271 | ||
272 | void | |
273 | UnsafeChecker::visit (ComparisonExpr &expr) | |
274 | { | |
275 | expr.get_lhs ()->accept_vis (*this); | |
276 | expr.get_rhs ()->accept_vis (*this); | |
277 | } | |
278 | ||
279 | void | |
280 | UnsafeChecker::visit (LazyBooleanExpr &expr) | |
281 | { | |
282 | expr.get_lhs ()->accept_vis (*this); | |
283 | expr.get_rhs ()->accept_vis (*this); | |
284 | } | |
285 | ||
286 | void | |
287 | UnsafeChecker::visit (TypeCastExpr &expr) | |
288 | { | |
289 | expr.get_expr ()->accept_vis (*this); | |
290 | } | |
291 | ||
292 | void | |
293 | UnsafeChecker::visit (AssignmentExpr &expr) | |
294 | { | |
295 | expr.get_lhs ()->accept_vis (*this); | |
296 | expr.get_rhs ()->accept_vis (*this); | |
297 | } | |
298 | ||
299 | void | |
300 | UnsafeChecker::visit (CompoundAssignmentExpr &expr) | |
301 | { | |
302 | expr.get_left_expr ()->accept_vis (*this); | |
303 | expr.get_right_expr ()->accept_vis (*this); | |
304 | } | |
305 | ||
306 | void | |
307 | UnsafeChecker::visit (GroupedExpr &expr) | |
308 | { | |
309 | expr.get_expr_in_parens ()->accept_vis (*this); | |
310 | } | |
311 | ||
312 | void | |
313 | UnsafeChecker::visit (ArrayElemsValues &elems) | |
314 | { | |
315 | for (auto &elem : elems.get_values ()) | |
316 | elem->accept_vis (*this); | |
317 | } | |
318 | ||
319 | void | |
320 | UnsafeChecker::visit (ArrayElemsCopied &elems) | |
321 | { | |
322 | elems.get_elem_to_copy ()->accept_vis (*this); | |
323 | } | |
324 | ||
325 | void | |
326 | UnsafeChecker::visit (ArrayExpr &expr) | |
327 | { | |
328 | expr.get_internal_elements ()->accept_vis (*this); | |
329 | } | |
330 | ||
331 | void | |
332 | UnsafeChecker::visit (ArrayIndexExpr &expr) | |
333 | { | |
334 | expr.get_array_expr ()->accept_vis (*this); | |
335 | expr.get_index_expr ()->accept_vis (*this); | |
336 | } | |
337 | ||
338 | void | |
339 | UnsafeChecker::visit (TupleExpr &expr) | |
340 | { | |
341 | for (auto &elem : expr.get_tuple_elems ()) | |
342 | elem->accept_vis (*this); | |
343 | } | |
344 | ||
345 | void | |
346 | UnsafeChecker::visit (TupleIndexExpr &expr) | |
347 | { | |
348 | expr.get_tuple_expr ()->accept_vis (*this); | |
349 | } | |
350 | ||
351 | void | |
352 | UnsafeChecker::visit (StructExprStruct &expr) | |
353 | {} | |
354 | ||
355 | void | |
356 | UnsafeChecker::visit (StructExprFieldIdentifier &field) | |
357 | {} | |
358 | ||
359 | void | |
360 | UnsafeChecker::visit (StructExprFieldIdentifierValue &field) | |
361 | { | |
362 | field.get_value ()->accept_vis (*this); | |
363 | } | |
364 | ||
365 | void | |
366 | UnsafeChecker::visit (StructExprFieldIndexValue &field) | |
367 | { | |
368 | field.get_value ()->accept_vis (*this); | |
369 | } | |
370 | ||
371 | void | |
372 | UnsafeChecker::visit (StructExprStructFields &expr) | |
373 | { | |
374 | for (auto &field : expr.get_fields ()) | |
375 | field->accept_vis (*this); | |
376 | } | |
377 | ||
378 | void | |
379 | UnsafeChecker::visit (StructExprStructBase &expr) | |
380 | {} | |
381 | ||
382 | void | |
383 | UnsafeChecker::visit (CallExpr &expr) | |
384 | { | |
385 | auto fn = expr.get_fnexpr (); | |
386 | if (!fn) | |
387 | return; | |
388 | ||
389 | NodeId ast_node_id = fn->get_mappings ().get_nodeid (); | |
390 | NodeId ref_node_id; | |
391 | HirId definition_id; | |
392 | ||
393 | // There are no unsafe types, and functions are defined in the name resolver. | |
394 | // If we can't find the name, then we're dealing with a type and should return | |
395 | // early. | |
396 | if (!resolver.lookup_resolved_name (ast_node_id, &ref_node_id)) | |
397 | return; | |
398 | ||
399 | rust_assert (mappings.lookup_node_to_hir (ref_node_id, &definition_id)); | |
400 | ||
401 | // At this point we have the function's HIR Id. There are two checks we | |
402 | // must perform: | |
403 | // 1. The function is an unsafe one | |
404 | // 2. The function is an extern one | |
405 | check_function_call (definition_id, expr.get_locus ()); | |
406 | ||
407 | if (expr.has_params ()) | |
408 | for (auto &arg : expr.get_arguments ()) | |
409 | arg->accept_vis (*this); | |
410 | } | |
411 | ||
412 | void | |
413 | UnsafeChecker::visit (MethodCallExpr &expr) | |
414 | { | |
415 | TyTy::BaseType *method_type; | |
416 | context.lookup_type (expr.get_method_name ().get_mappings ().get_hirid (), | |
417 | &method_type); | |
418 | ||
419 | auto fn = *static_cast<TyTy::FnType *> (method_type); | |
420 | auto method = mappings.lookup_hir_implitem (fn.get_ref (), nullptr); | |
421 | ||
422 | if (!unsafe_context.is_in_context () && method) | |
423 | check_unsafe_call (static_cast<Function *> (method), expr.get_locus (), | |
424 | "method"); | |
425 | ||
426 | expr.get_receiver ()->accept_vis (*this); | |
427 | ||
428 | for (auto &arg : expr.get_arguments ()) | |
429 | arg->accept_vis (*this); | |
430 | } | |
431 | ||
432 | void | |
433 | UnsafeChecker::visit (FieldAccessExpr &expr) | |
434 | { | |
435 | expr.get_receiver_expr ()->accept_vis (*this); | |
436 | ||
437 | if (unsafe_context.is_in_context ()) | |
438 | return; | |
439 | ||
440 | TyTy::BaseType *receiver_ty; | |
441 | auto ok = context.lookup_type ( | |
442 | expr.get_receiver_expr ()->get_mappings ().get_hirid (), &receiver_ty); | |
443 | rust_assert (ok); | |
444 | ||
445 | if (receiver_ty->get_kind () == TyTy::TypeKind::ADT) | |
446 | { | |
447 | auto maybe_union = static_cast<TyTy::ADTType *> (receiver_ty); | |
448 | if (maybe_union->is_union ()) | |
449 | rust_error_at ( | |
450 | expr.get_locus (), | |
451 | "access to union field requires unsafe function or block"); | |
452 | } | |
453 | } | |
454 | ||
455 | void | |
456 | UnsafeChecker::visit (ClosureExprInner &expr) | |
457 | {} | |
458 | ||
459 | void | |
460 | UnsafeChecker::visit (BlockExpr &expr) | |
461 | { | |
462 | for (auto &stmt : expr.get_statements ()) | |
463 | stmt->accept_vis (*this); | |
464 | ||
465 | if (expr.has_expr ()) | |
466 | expr.get_final_expr ()->accept_vis (*this); | |
467 | } | |
468 | ||
469 | void | |
470 | UnsafeChecker::visit (ClosureExprInnerTyped &expr) | |
471 | {} | |
472 | ||
473 | void | |
474 | UnsafeChecker::visit (ContinueExpr &expr) | |
475 | {} | |
476 | ||
477 | void | |
478 | UnsafeChecker::visit (BreakExpr &expr) | |
479 | { | |
480 | if (expr.has_break_expr ()) | |
481 | expr.get_expr ()->accept_vis (*this); | |
482 | } | |
483 | ||
484 | void | |
485 | UnsafeChecker::visit (RangeFromToExpr &expr) | |
486 | { | |
487 | expr.get_from_expr ()->accept_vis (*this); | |
488 | expr.get_to_expr ()->accept_vis (*this); | |
489 | } | |
490 | ||
491 | void | |
492 | UnsafeChecker::visit (RangeFromExpr &expr) | |
493 | { | |
494 | expr.get_from_expr ()->accept_vis (*this); | |
495 | } | |
496 | ||
497 | void | |
498 | UnsafeChecker::visit (RangeToExpr &expr) | |
499 | { | |
500 | expr.get_to_expr ()->accept_vis (*this); | |
501 | } | |
502 | ||
503 | void | |
504 | UnsafeChecker::visit (RangeFullExpr &expr) | |
505 | {} | |
506 | ||
507 | void | |
508 | UnsafeChecker::visit (RangeFromToInclExpr &expr) | |
509 | { | |
510 | expr.get_from_expr ()->accept_vis (*this); | |
511 | expr.get_to_expr ()->accept_vis (*this); | |
512 | } | |
513 | ||
514 | void | |
515 | UnsafeChecker::visit (RangeToInclExpr &expr) | |
516 | { | |
517 | expr.get_to_expr ()->accept_vis (*this); | |
518 | } | |
519 | ||
520 | void | |
521 | UnsafeChecker::visit (ReturnExpr &expr) | |
522 | { | |
523 | if (expr.has_return_expr ()) | |
524 | expr.get_expr ()->accept_vis (*this); | |
525 | } | |
526 | ||
527 | void | |
528 | UnsafeChecker::visit (UnsafeBlockExpr &expr) | |
529 | { | |
530 | unsafe_context.enter (expr.get_mappings ().get_hirid ()); | |
531 | ||
532 | expr.get_block_expr ()->accept_vis (*this); | |
533 | ||
534 | unsafe_context.exit (); | |
535 | } | |
536 | ||
537 | void | |
538 | UnsafeChecker::visit (LoopExpr &expr) | |
539 | { | |
540 | expr.get_loop_block ()->accept_vis (*this); | |
541 | } | |
542 | ||
543 | void | |
544 | UnsafeChecker::visit (WhileLoopExpr &expr) | |
545 | { | |
546 | expr.get_predicate_expr ()->accept_vis (*this); | |
547 | expr.get_loop_block ()->accept_vis (*this); | |
548 | } | |
549 | ||
550 | void | |
551 | UnsafeChecker::visit (WhileLetLoopExpr &expr) | |
552 | { | |
553 | expr.get_cond ()->accept_vis (*this); | |
554 | expr.get_loop_block ()->accept_vis (*this); | |
555 | } | |
556 | ||
557 | void | |
558 | UnsafeChecker::visit (ForLoopExpr &expr) | |
559 | { | |
560 | expr.get_iterator_expr ()->accept_vis (*this); | |
561 | expr.get_loop_block ()->accept_vis (*this); | |
562 | } | |
563 | ||
564 | void | |
565 | UnsafeChecker::visit (IfExpr &expr) | |
566 | { | |
567 | expr.get_if_condition ()->accept_vis (*this); | |
568 | expr.get_if_block ()->accept_vis (*this); | |
569 | } | |
570 | ||
571 | void | |
572 | UnsafeChecker::visit (IfExprConseqElse &expr) | |
573 | { | |
574 | expr.get_if_condition ()->accept_vis (*this); | |
575 | expr.get_if_block ()->accept_vis (*this); | |
576 | expr.get_else_block ()->accept_vis (*this); | |
577 | } | |
578 | ||
579 | void | |
580 | UnsafeChecker::visit (IfExprConseqIf &expr) | |
581 | { | |
582 | expr.get_if_condition ()->accept_vis (*this); | |
583 | expr.get_if_block ()->accept_vis (*this); | |
584 | expr.get_conseq_if_expr ()->accept_vis (*this); | |
585 | } | |
586 | ||
587 | void | |
588 | UnsafeChecker::visit (IfExprConseqIfLet &expr) | |
589 | { | |
590 | expr.get_if_condition ()->accept_vis (*this); | |
591 | expr.get_if_block ()->accept_vis (*this); | |
592 | ||
593 | // TODO: Visit conseq if let expression | |
594 | } | |
595 | ||
596 | void | |
597 | UnsafeChecker::visit (IfLetExpr &expr) | |
598 | { | |
599 | expr.get_scrutinee_expr ()->accept_vis (*this); | |
600 | expr.get_if_block ()->accept_vis (*this); | |
601 | } | |
602 | ||
603 | void | |
604 | UnsafeChecker::visit (IfLetExprConseqElse &expr) | |
605 | { | |
606 | expr.get_scrutinee_expr ()->accept_vis (*this); | |
607 | expr.get_if_block ()->accept_vis (*this); | |
608 | ||
609 | // TODO: Visit else expression | |
610 | } | |
611 | ||
612 | void | |
613 | UnsafeChecker::visit (IfLetExprConseqIf &expr) | |
614 | { | |
615 | expr.get_scrutinee_expr ()->accept_vis (*this); | |
616 | expr.get_if_block ()->accept_vis (*this); | |
617 | } | |
618 | ||
619 | void | |
620 | UnsafeChecker::visit (IfLetExprConseqIfLet &expr) | |
621 | { | |
622 | expr.get_scrutinee_expr ()->accept_vis (*this); | |
623 | expr.get_if_block ()->accept_vis (*this); | |
624 | ||
625 | // TODO: Visit conseq if let expression | |
626 | } | |
627 | ||
628 | void | |
629 | UnsafeChecker::visit (MatchExpr &expr) | |
630 | { | |
631 | expr.get_scrutinee_expr ()->accept_vis (*this); | |
632 | ||
633 | for (auto &match_arm : expr.get_match_cases ()) | |
634 | match_arm.get_expr ()->accept_vis (*this); | |
635 | } | |
636 | ||
637 | void | |
638 | UnsafeChecker::visit (AwaitExpr &expr) | |
639 | { | |
640 | // TODO: Visit expression | |
641 | } | |
642 | ||
643 | void | |
644 | UnsafeChecker::visit (AsyncBlockExpr &expr) | |
645 | { | |
646 | // TODO: Visit block expression | |
647 | } | |
648 | ||
649 | void | |
650 | UnsafeChecker::visit (TypeParam ¶m) | |
651 | {} | |
652 | ||
653 | void | |
654 | UnsafeChecker::visit (ConstGenericParam ¶m) | |
655 | {} | |
656 | ||
657 | void | |
658 | UnsafeChecker::visit (LifetimeWhereClauseItem &item) | |
659 | {} | |
660 | ||
661 | void | |
662 | UnsafeChecker::visit (TypeBoundWhereClauseItem &item) | |
663 | {} | |
664 | ||
665 | void | |
666 | UnsafeChecker::visit (Module &module) | |
667 | { | |
668 | for (auto &item : module.get_items ()) | |
669 | item->accept_vis (*this); | |
670 | } | |
671 | ||
672 | void | |
673 | UnsafeChecker::visit (ExternCrate &crate) | |
674 | {} | |
675 | ||
676 | void | |
677 | UnsafeChecker::visit (UseTreeGlob &use_tree) | |
678 | {} | |
679 | ||
680 | void | |
681 | UnsafeChecker::visit (UseTreeList &use_tree) | |
682 | {} | |
683 | ||
684 | void | |
685 | UnsafeChecker::visit (UseTreeRebind &use_tree) | |
686 | {} | |
687 | ||
688 | void | |
689 | UnsafeChecker::visit (UseDeclaration &use_decl) | |
690 | {} | |
691 | ||
692 | void | |
693 | UnsafeChecker::visit (Function &function) | |
694 | { | |
695 | auto is_unsafe_fn = function.get_qualifiers ().is_unsafe (); | |
696 | ||
697 | if (is_unsafe_fn) | |
698 | unsafe_context.enter (function.get_mappings ().get_hirid ()); | |
699 | ||
700 | function.get_definition ()->accept_vis (*this); | |
701 | ||
702 | if (is_unsafe_fn) | |
703 | unsafe_context.exit (); | |
704 | } | |
705 | ||
706 | void | |
707 | UnsafeChecker::visit (TypeAlias &type_alias) | |
708 | { | |
709 | // FIXME: What do we need to do to handle type aliasing? Is it possible to | |
710 | // have unsafe types? Type aliases on unsafe functions? | |
711 | } | |
712 | ||
713 | void | |
714 | UnsafeChecker::visit (StructStruct &struct_item) | |
715 | {} | |
716 | ||
717 | void | |
718 | UnsafeChecker::visit (TupleStruct &tuple_struct) | |
719 | {} | |
720 | ||
721 | void | |
722 | UnsafeChecker::visit (EnumItem &item) | |
723 | {} | |
724 | ||
725 | void | |
726 | UnsafeChecker::visit (EnumItemTuple &item) | |
727 | {} | |
728 | ||
729 | void | |
730 | UnsafeChecker::visit (EnumItemStruct &item) | |
731 | {} | |
732 | ||
733 | void | |
734 | UnsafeChecker::visit (EnumItemDiscriminant &item) | |
735 | {} | |
736 | ||
737 | void | |
738 | UnsafeChecker::visit (Enum &enum_item) | |
739 | {} | |
740 | ||
741 | void | |
742 | UnsafeChecker::visit (Union &union_item) | |
743 | {} | |
744 | ||
745 | void | |
746 | UnsafeChecker::visit (ConstantItem &const_item) | |
747 | { | |
748 | const_item.get_expr ()->accept_vis (*this); | |
749 | } | |
750 | ||
751 | void | |
752 | UnsafeChecker::visit (StaticItem &static_item) | |
753 | { | |
754 | static_item.get_expr ()->accept_vis (*this); | |
755 | } | |
756 | ||
757 | void | |
758 | UnsafeChecker::visit (TraitItemFunc &item) | |
759 | { | |
760 | if (item.has_block_defined ()) | |
761 | item.get_block_expr ()->accept_vis (*this); | |
762 | } | |
763 | ||
764 | void | |
765 | UnsafeChecker::visit (TraitItemConst &item) | |
766 | { | |
767 | if (item.has_expr ()) | |
768 | item.get_expr ()->accept_vis (*this); | |
769 | } | |
770 | ||
771 | void | |
772 | UnsafeChecker::visit (TraitItemType &item) | |
773 | {} | |
774 | ||
775 | void | |
776 | UnsafeChecker::visit (Trait &trait) | |
777 | { | |
778 | // FIXME: Handle unsafe traits | |
779 | for (auto &item : trait.get_trait_items ()) | |
780 | item->accept_vis (*this); | |
781 | } | |
782 | ||
783 | void | |
784 | UnsafeChecker::visit (ImplBlock &impl) | |
785 | { | |
786 | // FIXME: Handle unsafe impls | |
787 | for (auto &item : impl.get_impl_items ()) | |
788 | item->accept_vis (*this); | |
789 | } | |
790 | ||
791 | void | |
792 | UnsafeChecker::visit (ExternalStaticItem &item) | |
793 | {} | |
794 | ||
795 | void | |
796 | UnsafeChecker::visit (ExternalFunctionItem &item) | |
797 | {} | |
798 | ||
799 | void | |
800 | UnsafeChecker::visit (ExternBlock &block) | |
801 | { | |
802 | // FIXME: Do we need to do this? | |
803 | for (auto &item : block.get_extern_items ()) | |
804 | item->accept_vis (*this); | |
805 | } | |
806 | ||
807 | void | |
808 | UnsafeChecker::visit (LiteralPattern &pattern) | |
809 | {} | |
810 | ||
811 | void | |
812 | UnsafeChecker::visit (IdentifierPattern &pattern) | |
813 | {} | |
814 | ||
815 | void | |
816 | UnsafeChecker::visit (WildcardPattern &pattern) | |
817 | {} | |
818 | ||
819 | void | |
820 | UnsafeChecker::visit (RangePatternBoundLiteral &bound) | |
821 | {} | |
822 | ||
823 | void | |
824 | UnsafeChecker::visit (RangePatternBoundPath &bound) | |
825 | {} | |
826 | ||
827 | void | |
828 | UnsafeChecker::visit (RangePatternBoundQualPath &bound) | |
829 | {} | |
830 | ||
831 | void | |
832 | UnsafeChecker::visit (RangePattern &pattern) | |
833 | {} | |
834 | ||
835 | void | |
836 | UnsafeChecker::visit (ReferencePattern &pattern) | |
837 | {} | |
838 | ||
839 | void | |
840 | UnsafeChecker::visit (StructPatternFieldTuplePat &field) | |
841 | {} | |
842 | ||
843 | void | |
844 | UnsafeChecker::visit (StructPatternFieldIdentPat &field) | |
845 | {} | |
846 | ||
847 | void | |
848 | UnsafeChecker::visit (StructPatternFieldIdent &field) | |
849 | {} | |
850 | ||
851 | void | |
852 | UnsafeChecker::visit (StructPattern &pattern) | |
853 | {} | |
854 | ||
855 | void | |
856 | UnsafeChecker::visit (TupleStructItemsNoRange &tuple_items) | |
857 | {} | |
858 | ||
859 | void | |
860 | UnsafeChecker::visit (TupleStructItemsRange &tuple_items) | |
861 | {} | |
862 | ||
863 | void | |
864 | UnsafeChecker::visit (TupleStructPattern &pattern) | |
865 | {} | |
866 | ||
867 | void | |
868 | UnsafeChecker::visit (TuplePatternItemsMultiple &tuple_items) | |
869 | {} | |
870 | ||
871 | void | |
872 | UnsafeChecker::visit (TuplePatternItemsRanged &tuple_items) | |
873 | {} | |
874 | ||
875 | void | |
876 | UnsafeChecker::visit (TuplePattern &pattern) | |
877 | {} | |
878 | ||
879 | void | |
880 | UnsafeChecker::visit (GroupedPattern &pattern) | |
881 | {} | |
882 | ||
883 | void | |
884 | UnsafeChecker::visit (SlicePattern &pattern) | |
885 | {} | |
886 | ||
887 | void | |
888 | UnsafeChecker::visit (EmptyStmt &stmt) | |
889 | {} | |
890 | ||
891 | void | |
892 | UnsafeChecker::visit (LetStmt &stmt) | |
893 | { | |
894 | if (stmt.has_init_expr ()) | |
895 | stmt.get_init_expr ()->accept_vis (*this); | |
896 | } | |
897 | ||
898 | void | |
899 | UnsafeChecker::visit (ExprStmtWithoutBlock &stmt) | |
900 | { | |
901 | stmt.get_expr ()->accept_vis (*this); | |
902 | } | |
903 | ||
904 | void | |
905 | UnsafeChecker::visit (ExprStmtWithBlock &stmt) | |
906 | { | |
907 | stmt.get_expr ()->accept_vis (*this); | |
908 | } | |
909 | ||
910 | void | |
911 | UnsafeChecker::visit (TraitBound &bound) | |
912 | {} | |
913 | ||
914 | void | |
915 | UnsafeChecker::visit (ImplTraitType &type) | |
916 | {} | |
917 | ||
918 | void | |
919 | UnsafeChecker::visit (TraitObjectType &type) | |
920 | {} | |
921 | ||
922 | void | |
923 | UnsafeChecker::visit (ParenthesisedType &type) | |
924 | {} | |
925 | ||
926 | void | |
927 | UnsafeChecker::visit (ImplTraitTypeOneBound &type) | |
928 | {} | |
929 | ||
930 | void | |
931 | UnsafeChecker::visit (TupleType &type) | |
932 | {} | |
933 | ||
934 | void | |
935 | UnsafeChecker::visit (NeverType &type) | |
936 | {} | |
937 | ||
938 | void | |
939 | UnsafeChecker::visit (RawPointerType &type) | |
940 | {} | |
941 | ||
942 | void | |
943 | UnsafeChecker::visit (ReferenceType &type) | |
944 | {} | |
945 | ||
946 | void | |
947 | UnsafeChecker::visit (ArrayType &type) | |
948 | {} | |
949 | ||
950 | void | |
951 | UnsafeChecker::visit (SliceType &type) | |
952 | {} | |
953 | ||
954 | void | |
955 | UnsafeChecker::visit (InferredType &type) | |
956 | {} | |
957 | ||
958 | void | |
959 | UnsafeChecker::visit (BareFunctionType &type) | |
960 | {} | |
961 | ||
962 | } // namespace HIR | |
963 | } // namespace Rust |