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