Line data Source code
1 : /* Diagnostics for complaining about shift operations.
2 : Copyright (C) 2020-2026 Free Software Foundation, Inc.
3 : Contributed by David Malcolm <dmalcolm@redhat.com>.
4 :
5 : This file is part of GCC.
6 :
7 : GCC is free software; you can redistribute it and/or modify it
8 : under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3, or (at your option)
10 : any later version.
11 :
12 : GCC is distributed in the hope that it will be useful, but
13 : WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with GCC; see the file COPYING3. If not see
19 : <http://www.gnu.org/licenses/>. */
20 :
21 : #include "analyzer/common.h"
22 :
23 : #include "analyzer/region-model.h"
24 : #include "analyzer/feasible-graph.h"
25 : #include "diagnostics/sarif-sink.h"
26 :
27 : #if ENABLE_ANALYZER
28 :
29 : namespace ana {
30 :
31 : /* A subclass of pending_diagnostic for complaining about shifts
32 : by negative counts. */
33 :
34 : class shift_count_negative_diagnostic
35 : : public pending_diagnostic_subclass<shift_count_negative_diagnostic>
36 : {
37 : public:
38 24 : shift_count_negative_diagnostic (const gassign *assign, tree count_cst,
39 : const region *src_region)
40 24 : : m_assign (assign), m_count_cst (count_cst), m_src_region (src_region)
41 : {}
42 :
43 156 : const char *get_kind () const final override
44 : {
45 156 : return "shift_count_negative_diagnostic";
46 : }
47 :
48 24 : bool operator== (const shift_count_negative_diagnostic &other) const
49 : {
50 24 : return (m_assign == other.m_assign
51 24 : && same_tree_p (m_count_cst, other.m_count_cst));
52 : }
53 :
54 36 : int get_controlling_option () const final override
55 : {
56 36 : return OPT_Wanalyzer_shift_count_negative;
57 : }
58 :
59 12 : bool emit (diagnostic_emission_context &ctxt) final override
60 : {
61 12 : return ctxt.warn ("shift by negative count (%qE)", m_count_cst);
62 : }
63 :
64 : bool
65 24 : describe_final_event (pretty_printer &pp,
66 : const evdesc::final_event &) final override
67 : {
68 24 : pp_printf (&pp,
69 : "shift by negative amount here (%qE)",
70 : m_count_cst);
71 24 : return true;
72 : }
73 :
74 : void
75 24 : mark_interesting_stuff (interesting_t *interest)
76 : {
77 24 : interest->add_read_region (m_src_region, "shift count value");
78 24 : }
79 :
80 : private:
81 : const gassign *m_assign;
82 : tree m_count_cst;
83 : const region *m_src_region;
84 : };
85 :
86 : std::unique_ptr<pending_diagnostic>
87 24 : make_shift_count_negative_diagnostic (const gassign *assign, tree count_cst,
88 : const region *src_region)
89 : {
90 24 : return std::make_unique<shift_count_negative_diagnostic>
91 24 : (assign, count_cst, src_region);
92 : }
93 :
94 : /* A subclass of pending_diagnostic for complaining about shifts
95 : by counts >= the width of the operand type. */
96 :
97 : class shift_count_overflow_diagnostic
98 : : public pending_diagnostic_subclass<shift_count_overflow_diagnostic>
99 : {
100 : public:
101 24 : shift_count_overflow_diagnostic (const gassign *assign,
102 : int operand_precision,
103 : tree count_cst,
104 : const region *src_region)
105 24 : : m_assign (assign), m_operand_precision (operand_precision),
106 24 : m_count_cst (count_cst),
107 24 : m_src_region (src_region)
108 : {}
109 :
110 108 : const char *get_kind () const final override
111 : {
112 108 : return "shift_count_overflow_diagnostic";
113 : }
114 :
115 24 : bool operator== (const shift_count_overflow_diagnostic &other) const
116 : {
117 24 : return (m_assign == other.m_assign
118 24 : && m_operand_precision == other.m_operand_precision
119 48 : && same_tree_p (m_count_cst, other.m_count_cst));
120 : }
121 :
122 36 : int get_controlling_option () const final override
123 : {
124 36 : return OPT_Wanalyzer_shift_count_overflow;
125 : }
126 :
127 12 : bool emit (diagnostic_emission_context &ctxt) final override
128 : {
129 12 : return ctxt.warn ("shift by count (%qE) >= precision of type (%qi)",
130 12 : m_count_cst, m_operand_precision);
131 : }
132 :
133 : bool
134 24 : describe_final_event (pretty_printer &pp,
135 : const evdesc::final_event &) final override
136 : {
137 24 : pp_printf (&pp,
138 : "shift by count %qE here",
139 : m_count_cst);
140 24 : return true;
141 : }
142 :
143 : void
144 24 : mark_interesting_stuff (interesting_t *interest)
145 : {
146 24 : interest->add_read_region (m_src_region, "shift count value");
147 24 : }
148 :
149 : private:
150 : const gassign *m_assign;
151 : int m_operand_precision;
152 : tree m_count_cst;
153 : const region *m_src_region;
154 : };
155 :
156 : std::unique_ptr<pending_diagnostic>
157 24 : make_shift_count_overflow_diagnostic (const gassign *assign,
158 : int operand_precision,
159 : tree count_cst,
160 : const region *src_region)
161 : {
162 24 : return std::make_unique<shift_count_overflow_diagnostic>
163 24 : (assign, operand_precision, count_cst, src_region);
164 : }
165 :
166 : } // namespace ana
167 :
168 : #endif /* #if ENABLE_ANALYZER */
|