@@ -8,7 +8,7 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
8
8
9
9
declare_clippy_lint ! {
10
10
/// **What it does:** Checks for usage of invalid atomic
11
- /// ordering in Atomic*::{load, store} calls .
11
+ /// ordering in atomic loads/stores and memory fences .
12
12
///
13
13
/// **Why is this bad?** Using an invalid atomic ordering
14
14
/// will cause a panic at run-time.
@@ -17,7 +17,7 @@ declare_clippy_lint! {
17
17
///
18
18
/// **Example:**
19
19
/// ```rust,no_run
20
- /// # use std::sync::atomic::{AtomicBool, Ordering};
20
+ /// # use std::sync::atomic::{self, AtomicBool, Ordering};
21
21
///
22
22
/// let x = AtomicBool::new(true);
23
23
///
@@ -26,10 +26,13 @@ declare_clippy_lint! {
26
26
///
27
27
/// x.store(false, Ordering::Acquire);
28
28
/// x.store(false, Ordering::AcqRel);
29
+ ///
30
+ /// atomic::fence(Ordering::Relaxed);
31
+ /// atomic::compiler_fence(Ordering::Relaxed);
29
32
/// ```
30
33
pub INVALID_ATOMIC_ORDERING ,
31
34
correctness,
32
- "usage of invalid atomic ordering in atomic load/store calls "
35
+ "usage of invalid atomic ordering in atomic loads/stores and memory fences "
33
36
}
34
37
35
38
declare_lint_pass ! ( AtomicOrdering => [ INVALID_ATOMIC_ORDERING ] ) ;
@@ -65,37 +68,65 @@ fn match_ordering_def_path(cx: &LateContext<'_, '_>, did: DefId, orderings: &[&s
65
68
. any ( |ordering| match_def_path ( cx, did, & [ "core" , "sync" , "atomic" , "Ordering" , ordering] ) )
66
69
}
67
70
68
- impl < ' a , ' tcx > LateLintPass < ' a , ' tcx > for AtomicOrdering {
69
- fn check_expr ( & mut self , cx : & LateContext < ' a , ' tcx > , expr : & ' tcx Expr < ' _ > ) {
70
- if_chain ! {
71
- if let ExprKind :: MethodCall ( ref method_path, _, args) = & expr. kind;
72
- let method = method_path. ident. name. as_str( ) ;
73
- if type_is_atomic( cx, & args[ 0 ] ) ;
74
- if method == "load" || method == "store" ;
75
- let ordering_arg = if method == "load" { & args[ 1 ] } else { & args[ 2 ] } ;
76
- if let ExprKind :: Path ( ref ordering_qpath) = ordering_arg. kind;
77
- if let Some ( ordering_def_id) = cx. tables. qpath_res( ordering_qpath, ordering_arg. hir_id) . opt_def_id( ) ;
78
- then {
79
- if method == "load" &&
80
- match_ordering_def_path( cx, ordering_def_id, & [ "Release" , "AcqRel" ] ) {
81
- span_help_and_lint(
82
- cx,
83
- INVALID_ATOMIC_ORDERING ,
84
- ordering_arg. span,
85
- "atomic loads cannot have `Release` and `AcqRel` ordering" ,
86
- "consider using ordering modes `Acquire`, `SeqCst` or `Relaxed`"
87
- ) ;
88
- } else if method == "store" &&
89
- match_ordering_def_path( cx, ordering_def_id, & [ "Acquire" , "AcqRel" ] ) {
90
- span_help_and_lint(
91
- cx,
92
- INVALID_ATOMIC_ORDERING ,
93
- ordering_arg. span,
94
- "atomic stores cannot have `Acquire` and `AcqRel` ordering" ,
95
- "consider using ordering modes `Release`, `SeqCst` or `Relaxed`"
96
- ) ;
97
- }
71
+ fn check_atomic_load_store ( cx : & LateContext < ' _ , ' _ > , expr : & Expr < ' _ > ) {
72
+ if_chain ! {
73
+ if let ExprKind :: MethodCall ( ref method_path, _, args) = & expr. kind;
74
+ let method = method_path. ident. name. as_str( ) ;
75
+ if type_is_atomic( cx, & args[ 0 ] ) ;
76
+ if method == "load" || method == "store" ;
77
+ let ordering_arg = if method == "load" { & args[ 1 ] } else { & args[ 2 ] } ;
78
+ if let ExprKind :: Path ( ref ordering_qpath) = ordering_arg. kind;
79
+ if let Some ( ordering_def_id) = cx. tables. qpath_res( ordering_qpath, ordering_arg. hir_id) . opt_def_id( ) ;
80
+ then {
81
+ if method == "load" &&
82
+ match_ordering_def_path( cx, ordering_def_id, & [ "Release" , "AcqRel" ] ) {
83
+ span_help_and_lint(
84
+ cx,
85
+ INVALID_ATOMIC_ORDERING ,
86
+ ordering_arg. span,
87
+ "atomic loads cannot have `Release` and `AcqRel` ordering" ,
88
+ "consider using ordering modes `Acquire`, `SeqCst` or `Relaxed`"
89
+ ) ;
90
+ } else if method == "store" &&
91
+ match_ordering_def_path( cx, ordering_def_id, & [ "Acquire" , "AcqRel" ] ) {
92
+ span_help_and_lint(
93
+ cx,
94
+ INVALID_ATOMIC_ORDERING ,
95
+ ordering_arg. span,
96
+ "atomic stores cannot have `Acquire` and `AcqRel` ordering" ,
97
+ "consider using ordering modes `Release`, `SeqCst` or `Relaxed`"
98
+ ) ;
98
99
}
99
100
}
100
101
}
101
102
}
103
+
104
+ fn check_memory_fence ( cx : & LateContext < ' _ , ' _ > , expr : & Expr < ' _ > ) {
105
+ if_chain ! {
106
+ if let ExprKind :: Call ( ref func, ref args) = expr. kind;
107
+ if let ExprKind :: Path ( ref func_qpath) = func. kind;
108
+ if let Some ( def_id) = cx. tables. qpath_res( func_qpath, func. hir_id) . opt_def_id( ) ;
109
+ if [ "fence" , "compiler_fence" ]
110
+ . iter( )
111
+ . any( |func| match_def_path( cx, def_id, & [ "core" , "sync" , "atomic" , func] ) ) ;
112
+ if let ExprKind :: Path ( ref ordering_qpath) = & args[ 0 ] . kind;
113
+ if let Some ( ordering_def_id) = cx. tables. qpath_res( ordering_qpath, args[ 0 ] . hir_id) . opt_def_id( ) ;
114
+ if match_ordering_def_path( cx, ordering_def_id, & [ "Relaxed" ] ) ;
115
+ then {
116
+ span_help_and_lint(
117
+ cx,
118
+ INVALID_ATOMIC_ORDERING ,
119
+ args[ 0 ] . span,
120
+ "memory fences cannot have `Relaxed` ordering" ,
121
+ "consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst`"
122
+ ) ;
123
+ }
124
+ }
125
+ }
126
+
127
+ impl < ' a , ' tcx > LateLintPass < ' a , ' tcx > for AtomicOrdering {
128
+ fn check_expr ( & mut self , cx : & LateContext < ' a , ' tcx > , expr : & ' tcx Expr < ' _ > ) {
129
+ check_atomic_load_store ( cx, expr) ;
130
+ check_memory_fence ( cx, expr) ;
131
+ }
132
+ }
0 commit comments