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