From 6e4962810fe5de95b807d1ac675df45a725e31a2 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Wed, 16 Nov 2022 17:38:24 -0500 Subject: [PATCH] analyzer: log the stashing of named constants [PR107711] PR analyzer/107711 seems to be a bug in how named constants are looked up by the analyzer in the C frontend. To help debug this, this patch extends -fdump-analyzer and -fdump-analyzer-stderr so that they dump this part of the analyzer's startup. gcc/analyzer/ChangeLog: PR analyzer/107711 * analyzer-language.cc: Include "diagnostic.h". (maybe_stash_named_constant): Add logger param and use it to log the name being looked up, and the result. (stash_named_constants): New, splitting out from... (on_finish_translation_unit): ...this function. Call get_or_create_logfile and use the result to create a logger instance, passing it to stash_named_constants. * analyzer.h (get_or_create_any_logfile): New decl. * engine.cc (dump_fout, owns_dump_fout): New globals, split out from run_checkers. (get_or_create_any_logfile): New function, split out from... (run_checkers): ...here, so that the logfile can be opened by on_finish_translation_unit. Clear the globals when closing the dump file. gcc/testsuite/ChangeLog: PR analyzer/107711 * gcc.dg/analyzer/fdump-analyzer-1.c: New test. Signed-off-by: David Malcolm --- gcc/analyzer/analyzer-language.cc | 42 +++++++++++++--- gcc/analyzer/analyzer.h | 2 + gcc/analyzer/engine.cc | 50 +++++++++++++------ .../gcc.dg/analyzer/fdump-analyzer-1.c | 14 ++++++ 4 files changed, 85 insertions(+), 23 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/analyzer/fdump-analyzer-1.c diff --git a/gcc/analyzer/analyzer-language.cc b/gcc/analyzer/analyzer-language.cc index 0629b681e7c1..0fb43443ffdd 100644 --- a/gcc/analyzer/analyzer-language.cc +++ b/gcc/analyzer/analyzer-language.cc @@ -27,6 +27,7 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/analyzer.h" #include "analyzer/analyzer-language.h" #include "analyzer/analyzer-logging.h" +#include "diagnostic.h" /* Map from identifier to INTEGER_CST. */ static GTY (()) hash_map *analyzer_stashed_constants; @@ -39,8 +40,12 @@ namespace ana { If found, stash its value within analyzer_stashed_constants. */ static void -maybe_stash_named_constant (const translation_unit &tu, const char *name) +maybe_stash_named_constant (logger *logger, + const translation_unit &tu, + const char *name) { + LOG_FUNC_1 (logger, "name: %qs", name); + if (!analyzer_stashed_constants) analyzer_stashed_constants = hash_map::create_ggc (); @@ -49,7 +54,30 @@ maybe_stash_named_constant (const translation_unit &tu, const char *name) { gcc_assert (TREE_CODE (t) == INTEGER_CST); analyzer_stashed_constants->put (id, t); + if (logger) + logger->log ("%qs: %qE", name, t); } + else + { + if (logger) + logger->log ("%qs: not found", name); + } +} + +/* Call into TU to try to find values for the names we care about. + If found, stash their values within analyzer_stashed_constants. */ + +static void +stash_named_constants (logger *logger, const translation_unit &tu) +{ + LOG_SCOPE (logger); + + /* Stash named constants for use by sm-fd.cc */ + maybe_stash_named_constant (logger, tu, "O_ACCMODE"); + maybe_stash_named_constant (logger, tu, "O_RDONLY"); + maybe_stash_named_constant (logger, tu, "O_WRONLY"); + maybe_stash_named_constant (logger, tu, "SOCK_STREAM"); + maybe_stash_named_constant (logger, tu, "SOCK_DGRAM"); } /* Hook for frontend to call into analyzer when TU finishes. @@ -68,12 +96,12 @@ on_finish_translation_unit (const translation_unit &tu) 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"); - maybe_stash_named_constant (tu, "SOCK_STREAM"); - maybe_stash_named_constant (tu, "SOCK_DGRAM"); + FILE *logfile = get_or_create_any_logfile (); + log_user the_logger (NULL); + if (logfile) + the_logger.set_logger (new logger (logfile, 0, 0, + *global_dc->printer)); + stash_named_constants (the_logger.get_logger (), tu); } /* Lookup NAME in the named constants stashed when the frontend TU finished. diff --git a/gcc/analyzer/analyzer.h b/gcc/analyzer/analyzer.h index 99a1d0690d53..1b56745aba23 100644 --- a/gcc/analyzer/analyzer.h +++ b/gcc/analyzer/analyzer.h @@ -324,6 +324,8 @@ public: extern tree get_stashed_constant_by_name (const char *name); extern void log_stashed_constants (logger *logger); +extern FILE *get_or_create_any_logfile (); + } // namespace ana extern bool is_special_named_call_p (const gcall *call, const char *funcname, diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index fe2b9c69221f..b52753da7935 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -6144,6 +6144,34 @@ impl_run_checkers (logger *logger) delete purge_map; } +/* Handle -fdump-analyzer and -fdump-analyzer-stderr. */ +static FILE *dump_fout = NULL; + +/* Track if we're responsible for closing dump_fout. */ +static bool owns_dump_fout = false; + +/* If dumping is enabled, attempt to create dump_fout if it hasn't already + been opened. Return it. */ + +FILE * +get_or_create_any_logfile () +{ + if (!dump_fout) + { + if (flag_dump_analyzer_stderr) + dump_fout = stderr; + else if (flag_dump_analyzer) + { + char *dump_filename = concat (dump_base_name, ".analyzer.txt", NULL); + dump_fout = fopen (dump_filename, "w"); + free (dump_filename); + if (dump_fout) + owns_dump_fout = true; + } + } + return dump_fout; +} + /* External entrypoint to the analysis "engine". Set up any dumps, then call impl_run_checkers. */ @@ -6153,23 +6181,9 @@ run_checkers () /* Save input_location. */ location_t saved_input_location = input_location; - /* Handle -fdump-analyzer and -fdump-analyzer-stderr. */ - FILE *dump_fout = NULL; - /* Track if we're responsible for closing dump_fout. */ - bool owns_dump_fout = false; - if (flag_dump_analyzer_stderr) - dump_fout = stderr; - else if (flag_dump_analyzer) - { - char *dump_filename = concat (dump_base_name, ".analyzer.txt", NULL); - dump_fout = fopen (dump_filename, "w"); - free (dump_filename); - if (dump_fout) - owns_dump_fout = true; - } - { log_user the_logger (NULL); + get_or_create_any_logfile (); if (dump_fout) the_logger.set_logger (new logger (dump_fout, 0, 0, *global_dc->printer)); @@ -6182,7 +6196,11 @@ run_checkers () } if (owns_dump_fout) - fclose (dump_fout); + { + fclose (dump_fout); + owns_dump_fout = false; + dump_fout = NULL; + } /* Restore input_location. Subsequent passes may assume that input_location is some arbitrary value *not* in the block tree, which might be violated diff --git a/gcc/testsuite/gcc.dg/analyzer/fdump-analyzer-1.c b/gcc/testsuite/gcc.dg/analyzer/fdump-analyzer-1.c new file mode 100644 index 000000000000..8962adbf79eb --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/fdump-analyzer-1.c @@ -0,0 +1,14 @@ +/* { dg-additional-options "-fdump-analyzer" } */ + +void test (void) +{ +} + +/* Verify that we log the named constants that we look up in the TU + (before the analysis pass runs). + { dg-final { scan-file fdump-analyzer-1.c.analyzer.txt "maybe_stash_named_constant: name: 'O_ACCMODE'" } } + + Verify that we log the main part of the analysis (part of the + analysis pass): + { dg-final { scan-file fdump-analyzer-1.c.analyzer.txt "ana::run_checkers" } } + */