| /* Interface between analyzer and frontends. |
| Copyright (C) 2022 Free Software Foundation, Inc. |
| Contributed by David Malcolm <dmalcolm@redhat.com>. |
| |
| This file is part of GCC. |
| |
| GCC is free software; you can redistribute it and/or modify it |
| under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 3, or (at your option) |
| any later version. |
| |
| GCC is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GCC; see the file COPYING3. If not see |
| <http://www.gnu.org/licenses/>. */ |
| |
| #include "config.h" |
| #define INCLUDE_MEMORY |
| #include "system.h" |
| #include "coretypes.h" |
| #include "tree.h" |
| #include "stringpool.h" |
| #include "analyzer/analyzer.h" |
| #include "analyzer/analyzer-language.h" |
| #include "analyzer/analyzer-logging.h" |
| |
| /* Map from identifier to INTEGER_CST. */ |
| static GTY (()) hash_map <tree, tree> *analyzer_stashed_constants; |
| |
| #if ENABLE_ANALYZER |
| |
| namespace ana { |
| |
| /* Call into TU to try to find a value for NAME. |
| If found, stash its value within analyzer_stashed_constants. */ |
| |
| static void |
| maybe_stash_named_constant (const translation_unit &tu, const char *name) |
| { |
| if (!analyzer_stashed_constants) |
| analyzer_stashed_constants = hash_map<tree, tree>::create_ggc (); |
| |
| tree id = get_identifier (name); |
| if (tree t = tu.lookup_constant_by_id (id)) |
| { |
| gcc_assert (TREE_CODE (t) == INTEGER_CST); |
| analyzer_stashed_constants->put (id, t); |
| } |
| } |
| |
| /* Hook for frontend to call into analyzer when TU finishes. |
| This exists so that the analyzer can stash named constant values from |
| header files (e.g. macros and enums) for later use when modeling the |
| behaviors of APIs. |
| |
| By doing it this way, the analyzer can use the precise values for those |
| constants from the user's headers, rather than attempting to model them |
| as properties of the target. */ |
| |
| void |
| on_finish_translation_unit (const translation_unit &tu) |
| { |
| /* Bail if the analyzer isn't enabled. */ |
| if (!flag_analyzer) |
| return; |
| |
| /* Stash named constants for use by sm-fd.cc */ |
| maybe_stash_named_constant (tu, "O_ACCMODE"); |
| maybe_stash_named_constant (tu, "O_RDONLY"); |
| maybe_stash_named_constant (tu, "O_WRONLY"); |
| } |
| |
| /* Lookup NAME in the named constants stashed when the frontend TU finished. |
| Return either an INTEGER_CST, or NULL_TREE. */ |
| |
| tree |
| get_stashed_constant_by_name (const char *name) |
| { |
| if (!analyzer_stashed_constants) |
| return NULL_TREE; |
| tree id = get_identifier (name); |
| if (tree *slot = analyzer_stashed_constants->get (id)) |
| { |
| gcc_assert (TREE_CODE (*slot) == INTEGER_CST); |
| return *slot; |
| } |
| return NULL_TREE; |
| } |
| |
| /* Log all stashed named constants to LOGGER. */ |
| |
| void |
| log_stashed_constants (logger *logger) |
| { |
| gcc_assert (logger); |
| LOG_SCOPE (logger); |
| if (analyzer_stashed_constants) |
| for (auto iter : *analyzer_stashed_constants) |
| logger->log ("%qE: %qE", iter.first, iter.second); |
| } |
| |
| } // namespace ana |
| |
| #endif /* #if ENABLE_ANALYZER */ |
| |
| #include "gt-analyzer-language.h" |