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