Line data Source code
1 : /* Implementation of write_to_const_diagnostic and
2 : write_to_string_literal_diagnostic.
3 : Copyright (C) 2020-2026 Free Software Foundation, Inc.
4 : Contributed by David Malcolm <dmalcolm@redhat.com>.
5 :
6 : This file is part of GCC.
7 :
8 : GCC is free software; you can redistribute it and/or modify it
9 : under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3, or (at your option)
11 : any later version.
12 :
13 : GCC is distributed in the hope that it will be useful, but
14 : WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 : General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with GCC; see the file COPYING3. If not see
20 : <http://www.gnu.org/licenses/>. */
21 :
22 : #include "analyzer/common.h"
23 :
24 : #include "analyzer/region-model.h"
25 :
26 : #if ENABLE_ANALYZER
27 :
28 : namespace ana {
29 :
30 : /* A subclass of pending_diagnostic for complaining about writes to
31 : constant regions of memory. */
32 :
33 : class write_to_const_diagnostic
34 : : public pending_diagnostic_subclass<write_to_const_diagnostic>
35 : {
36 : public:
37 33 : write_to_const_diagnostic (const region *reg, tree decl)
38 33 : : m_reg (reg), m_decl (decl)
39 : {}
40 :
41 421 : const char *get_kind () const final override
42 : {
43 421 : return "write_to_const_diagnostic";
44 : }
45 :
46 33 : bool operator== (const write_to_const_diagnostic &other) const
47 : {
48 33 : return (m_reg == other.m_reg
49 33 : && m_decl == other.m_decl);
50 : }
51 :
52 66 : int get_controlling_option () const final override
53 : {
54 66 : return OPT_Wanalyzer_write_to_const;
55 : }
56 :
57 33 : bool emit (diagnostic_emission_context &ctxt) final override
58 : {
59 33 : auto_diagnostic_group d;
60 33 : bool warned;
61 33 : switch (m_reg->get_kind ())
62 : {
63 20 : default:
64 20 : warned = ctxt.warn ("write to %<const%> object %qE", m_decl);
65 20 : break;
66 9 : case RK_FUNCTION:
67 9 : warned = ctxt.warn ("write to function %qE", m_decl);
68 9 : break;
69 4 : case RK_LABEL:
70 4 : warned = ctxt.warn ("write to label %qE", m_decl);
71 4 : break;
72 : }
73 33 : if (warned)
74 33 : inform (DECL_SOURCE_LOCATION (m_decl), "declared here");
75 66 : return warned;
76 33 : }
77 :
78 : bool
79 66 : describe_final_event (pretty_printer &pp,
80 : const evdesc::final_event &) final override
81 : {
82 66 : switch (m_reg->get_kind ())
83 : {
84 40 : default:
85 40 : {
86 40 : pp_printf (&pp,
87 : "write to %<const%> object %qE here", m_decl);
88 40 : return true;
89 : }
90 18 : case RK_FUNCTION:
91 18 : {
92 18 : pp_printf (&pp,
93 : "write to function %qE here", m_decl);
94 18 : return true;
95 : }
96 8 : case RK_LABEL:
97 8 : {
98 8 : pp_printf (&pp,
99 : "write to label %qE here", m_decl);
100 8 : return true;
101 : }
102 : }
103 : }
104 :
105 : private:
106 : const region *m_reg;
107 : tree m_decl;
108 : };
109 :
110 : std::unique_ptr<pending_diagnostic>
111 33 : make_write_to_const_diagnostic (const region *dest_reg, tree decl)
112 : {
113 33 : return std::make_unique<write_to_const_diagnostic> (dest_reg, decl);
114 : }
115 :
116 : /* A subclass of pending_diagnostic for complaining about writes to
117 : string literals. */
118 :
119 : class write_to_string_literal_diagnostic
120 : : public pending_diagnostic_subclass<write_to_string_literal_diagnostic>
121 : {
122 : public:
123 51 : write_to_string_literal_diagnostic (const region *reg)
124 51 : : m_reg (reg)
125 : {}
126 :
127 337 : const char *get_kind () const final override
128 : {
129 337 : return "write_to_string_literal_diagnostic";
130 : }
131 :
132 47 : bool operator== (const write_to_string_literal_diagnostic &other) const
133 : {
134 47 : return m_reg == other.m_reg;
135 : }
136 :
137 94 : int get_controlling_option () const final override
138 : {
139 94 : return OPT_Wanalyzer_write_to_string_literal;
140 : }
141 :
142 43 : bool emit (diagnostic_emission_context &ctxt) final override
143 : {
144 43 : return ctxt.warn ("write to string literal");
145 : /* Ideally we would show the location of the STRING_CST as well,
146 : but it is not available at this point. */
147 : }
148 :
149 : bool
150 86 : describe_final_event (pretty_printer &pp,
151 : const evdesc::final_event &) final override
152 : {
153 86 : pp_string (&pp, "write to string literal here");
154 86 : return true;
155 : }
156 :
157 : private:
158 : const region *m_reg;
159 : };
160 :
161 : std::unique_ptr<pending_diagnostic>
162 51 : make_write_to_string_literal_diagnostic (const region *reg)
163 : {
164 51 : return std::make_unique<write_to_string_literal_diagnostic> (reg);
165 : }
166 :
167 : } // namespace ana
168 :
169 : #endif /* #if ENABLE_ANALYZER */
|