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