2
0
mirror of git://gcc.gnu.org/git/gcc.git synced 2025-04-13 12:11:08 +08:00

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 <dmalcolm@redhat.com>
This commit is contained in:
David Malcolm 2022-11-16 17:38:24 -05:00
parent bdd784fc48
commit 6e4962810f
4 changed files with 85 additions and 23 deletions

@ -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 <tree, tree> *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<tree, tree>::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.

@ -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,

@ -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

@ -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" } }
*/