Line data Source code
1 : /* Interface between analyzer and frontends.
2 : Copyright (C) 2022-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 "diagnostic.h"
24 : #include "stringpool.h"
25 : #include "context.h"
26 : #include "channels.h"
27 :
28 : #include "analyzer/analyzer-language.h"
29 : #include "analyzer/analyzer-logging.h"
30 :
31 : /* Map from identifier to INTEGER_CST. */
32 : static GTY (()) hash_map <tree, tree> *analyzer_stashed_constants;
33 :
34 : #if ENABLE_ANALYZER
35 :
36 : namespace ana {
37 :
38 : /* Call into TU to try to find a value for NAME.
39 : If found, stash its value within analyzer_stashed_constants. */
40 :
41 : static void
42 27728 : maybe_stash_named_constant (logger *logger,
43 : const translation_unit &tu,
44 : const char *name)
45 : {
46 27728 : LOG_FUNC_1 (logger, "name: %qs", name);
47 :
48 27728 : if (!analyzer_stashed_constants)
49 3466 : analyzer_stashed_constants = hash_map<tree, tree>::create_ggc ();
50 :
51 27728 : tree id = get_identifier (name);
52 27728 : if (tree t = tu.lookup_constant_by_id (id))
53 : {
54 110 : gcc_assert (TREE_CODE (t) == INTEGER_CST);
55 110 : analyzer_stashed_constants->put (id, t);
56 110 : if (logger)
57 0 : logger->log ("%qs: %qE", name, t);
58 : }
59 : else
60 : {
61 27618 : if (logger)
62 40 : logger->log ("%qs: not found", name);
63 : }
64 27728 : }
65 :
66 : /* Call into TU to try to find values for the names we care about.
67 : If found, stash their values within analyzer_stashed_constants. */
68 :
69 : static void
70 3466 : stash_named_constants (logger *logger, const translation_unit &tu)
71 : {
72 3466 : LOG_SCOPE (logger);
73 :
74 : /* Stash named constants for use by sm-fd.cc */
75 3466 : maybe_stash_named_constant (logger, tu, "O_ACCMODE");
76 3466 : maybe_stash_named_constant (logger, tu, "O_RDONLY");
77 3466 : maybe_stash_named_constant (logger, tu, "O_WRONLY");
78 3466 : maybe_stash_named_constant (logger, tu, "SOCK_STREAM");
79 3466 : maybe_stash_named_constant (logger, tu, "SOCK_DGRAM");
80 :
81 : /* Stash named constants for use by kf.cc */
82 3466 : maybe_stash_named_constant (logger, tu, "O_CREAT");
83 3466 : maybe_stash_named_constant (logger, tu, "O_EXCL");
84 3466 : maybe_stash_named_constant (logger, tu, "O_RDWR");
85 3466 : }
86 :
87 : /* Hook for frontend to call into analyzer when TU finishes.
88 : This exists so that the analyzer can stash named constant values from
89 : header files (e.g. macros and enums) for later use when modeling the
90 : behaviors of APIs.
91 :
92 : By doing it this way, the analyzer can use the precise values for those
93 : constants from the user's headers, rather than attempting to model them
94 : as properties of the target. */
95 :
96 : void
97 3466 : on_finish_translation_unit (const translation_unit &tu)
98 : {
99 : /* Bail if the analyzer isn't enabled. */
100 3466 : if (!flag_analyzer)
101 0 : return;
102 :
103 3466 : FILE *logfile = get_or_create_any_logfile ();
104 3466 : log_user the_logger (nullptr);
105 3466 : if (logfile)
106 5 : the_logger.set_logger (new logger (logfile, 0, 0,
107 5 : *global_dc->get_reference_printer ()));
108 3466 : stash_named_constants (the_logger.get_logger (), tu);
109 :
110 3466 : if (auto chan = g->get_channels ().analyzer_events_channel.get_if_active ())
111 : {
112 38 : gcc::topics::analyzer_events::on_tu_finished msg {the_logger.get_logger (),
113 38 : tu};
114 38 : chan->publish (msg);
115 : }
116 3466 : }
117 :
118 : /* Lookup NAME in the named constants stashed when the frontend TU finished.
119 : Return either an INTEGER_CST, or NULL_TREE. */
120 :
121 : tree
122 17326 : get_stashed_constant_by_name (const char *name)
123 : {
124 17326 : if (!analyzer_stashed_constants)
125 : return NULL_TREE;
126 17201 : tree id = get_identifier (name);
127 17201 : if (tree *slot = analyzer_stashed_constants->get (id))
128 : {
129 223 : gcc_assert (TREE_CODE (*slot) == INTEGER_CST);
130 : return *slot;
131 : }
132 : return NULL_TREE;
133 : }
134 :
135 : /* Log all stashed named constants to LOGGER. */
136 :
137 : void
138 5 : log_stashed_constants (logger *logger)
139 : {
140 5 : gcc_assert (logger);
141 5 : LOG_SCOPE (logger);
142 5 : if (analyzer_stashed_constants)
143 10 : for (auto iter : *analyzer_stashed_constants)
144 0 : logger->log ("%qE: %qE", iter.first, iter.second);
145 5 : }
146 :
147 : } // namespace ana
148 :
149 : #endif /* #if ENABLE_ANALYZER */
150 :
151 : #include "gt-analyzer-language.h"
|