(root)/
gcc-13.2.0/
gcc/
analyzer/
analyzer-logging.h
       1  /* Hierarchical log messages for the analyzer.
       2     Copyright (C) 2014-2023 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  /* Adapted from jit-logging.h.  */
      22  
      23  #ifndef ANALYZER_LOGGING_H
      24  #define ANALYZER_LOGGING_H
      25  
      26  #include "diagnostic-core.h"
      27  
      28  namespace ana {
      29  
      30  /* A logger encapsulates a logging stream: a way to send
      31     lines of pertinent information to a FILE *.  */
      32  
      33  class logger
      34  {
      35   public:
      36    logger (FILE *f_out, int flags, int verbosity, const pretty_printer &reference_pp);
      37    ~logger ();
      38  
      39    void incref (const char *reason);
      40    void decref (const char *reason);
      41  
      42    void log (const char *fmt, ...)
      43      ATTRIBUTE_GCC_DIAG(2, 3);
      44    void log_va (const char *fmt, va_list *ap)
      45      ATTRIBUTE_GCC_DIAG(2, 0);
      46    void start_log_line ();
      47    void log_partial (const char *fmt, ...)
      48      ATTRIBUTE_GCC_DIAG(2, 3);
      49    void log_va_partial (const char *fmt, va_list *ap)
      50      ATTRIBUTE_GCC_DIAG(2, 0);
      51    void end_log_line ();
      52  
      53    void enter_scope (const char *scope_name);
      54    void enter_scope (const char *scope_name, const char *fmt, va_list *ap)
      55      ATTRIBUTE_GCC_DIAG(3, 0);
      56    void exit_scope (const char *scope_name);
      57    void inc_indent () { m_indent_level++; }
      58    void dec_indent () { m_indent_level--; }
      59  
      60    pretty_printer *get_printer () const { return m_pp; }
      61    FILE *get_file () const { return m_f_out; }
      62  
      63  private:
      64    DISABLE_COPY_AND_ASSIGN (logger);
      65  
      66    int m_refcount;
      67    FILE *m_f_out;
      68    int m_indent_level;
      69    bool m_log_refcount_changes;
      70    pretty_printer *m_pp;
      71  };
      72  
      73  /* The class log_scope is an RAII-style class intended to make
      74     it easy to notify a logger about entering and exiting the body of a
      75     given function.  */
      76  
      77  class log_scope
      78  {
      79  public:
      80    log_scope (logger *logger, const char *name);
      81    log_scope (logger *logger, const char *name, const char *fmt, ...)
      82      ATTRIBUTE_GCC_DIAG(4, 5);
      83    ~log_scope ();
      84  
      85   private:
      86    DISABLE_COPY_AND_ASSIGN (log_scope);
      87  
      88    logger *m_logger;
      89    const char *m_name;
      90  };
      91  
      92  /* The constructor for log_scope.
      93  
      94     The normal case is that the logger is NULL, in which case this should
      95     be largely a no-op.
      96  
      97     If we do have a logger, notify it that we're entering the given scope.
      98     We also need to hold a reference on it, to avoid a use-after-free
      99     when logging the cleanup of the owner of the logger.  */
     100  
     101  inline
     102  log_scope::log_scope (logger *logger, const char *name) :
     103   m_logger (logger),
     104   m_name (name)
     105  {
     106    if (m_logger)
     107      {
     108        m_logger->incref ("log_scope ctor");
     109        m_logger->enter_scope (m_name);
     110      }
     111  }
     112  
     113  inline
     114  log_scope::log_scope (logger *logger, const char *name, const char *fmt, ...):
     115   m_logger (logger),
     116   m_name (name)
     117  {
     118    if (m_logger)
     119      {
     120        m_logger->incref ("log_scope ctor");
     121        va_list ap;
     122        va_start (ap, fmt);
     123        m_logger->enter_scope (m_name, fmt, &ap);
     124        va_end (ap);
     125      }
     126  }
     127  
     128  
     129  /* The destructor for log_scope; essentially the opposite of
     130     the constructor.  */
     131  
     132  inline
     133  log_scope::~log_scope ()
     134  {
     135    if (m_logger)
     136      {
     137        m_logger->exit_scope (m_name);
     138        m_logger->decref ("log_scope dtor");
     139      }
     140  }
     141  
     142  /* A log_user is something that potentially uses a logger (which could be NULL).
     143  
     144     The log_user class keeps the reference-count of a logger up-to-date.  */
     145  
     146  class log_user
     147  {
     148   public:
     149    log_user (logger *logger);
     150    ~log_user ();
     151  
     152    logger * get_logger () const { return m_logger; }
     153    void set_logger (logger * logger);
     154  
     155    void log (const char *fmt, ...) const
     156      ATTRIBUTE_GCC_DIAG(2, 3);
     157  
     158    void start_log_line () const;
     159    void end_log_line () const;
     160  
     161    void enter_scope (const char *scope_name);
     162    void exit_scope (const char *scope_name);
     163  
     164    pretty_printer *get_logger_pp () const
     165    {
     166      gcc_assert (m_logger);
     167      return m_logger->get_printer ();
     168    }
     169  
     170    FILE *get_logger_file () const
     171    {
     172      if (m_logger == NULL)
     173        return NULL;
     174      return m_logger->get_file ();
     175    }
     176  
     177   private:
     178    DISABLE_COPY_AND_ASSIGN (log_user);
     179  
     180    logger *m_logger;
     181  };
     182  
     183  /* A shortcut for calling log from a log_user, handling the common
     184     case where the underlying logger is NULL via a no-op.  */
     185  
     186  inline void
     187  log_user::log (const char *fmt, ...) const
     188  {
     189    if (m_logger)
     190      {
     191        va_list ap;
     192        va_start (ap, fmt);
     193        m_logger->log_va (fmt, &ap);
     194        va_end (ap);
     195      }
     196  }
     197  
     198  /* A shortcut for starting a log line from a log_user,
     199     handling the common case where the underlying logger is NULL via
     200     a no-op.  */
     201  
     202  inline void
     203  log_user::start_log_line () const
     204  {
     205    if (m_logger)
     206      m_logger->start_log_line ();
     207  }
     208  
     209  /* A shortcut for ending a log line from a log_user,
     210     handling the common case where the underlying logger is NULL via
     211     a no-op.  */
     212  
     213  inline void
     214  log_user::end_log_line () const
     215  {
     216    if (m_logger)
     217      m_logger->end_log_line ();
     218  }
     219  
     220  /* A shortcut for recording entry into a scope from a log_user,
     221     handling the common case where the underlying logger is NULL via
     222     a no-op.  */
     223  
     224  inline void
     225  log_user::enter_scope (const char *scope_name)
     226  {
     227    if (m_logger)
     228      m_logger->enter_scope (scope_name);
     229  }
     230  
     231  /* A shortcut for recording exit from a scope from a log_user,
     232     handling the common case where the underlying logger is NULL via
     233     a no-op.  */
     234  
     235  inline void
     236  log_user::exit_scope (const char *scope_name)
     237  {
     238    if (m_logger)
     239      m_logger->exit_scope (scope_name);
     240  }
     241  
     242  /* If the given logger is non-NULL, log entry/exit of this scope to
     243     it, identifying it using __PRETTY_FUNCTION__.  */
     244  
     245  #define LOG_SCOPE(LOGGER)		\
     246    log_scope s (LOGGER, __PRETTY_FUNCTION__)
     247  
     248  /* If the given logger is non-NULL, log entry/exit of this scope to
     249     it, identifying it using __func__.  */
     250  
     251  #define LOG_FUNC(LOGGER) \
     252    log_scope s (LOGGER, __func__)
     253  
     254  #define LOG_FUNC_1(LOGGER, FMT, A0)	\
     255    log_scope s (LOGGER, __func__, FMT, A0)
     256  
     257  #define LOG_FUNC_2(LOGGER, FMT, A0, A1)		\
     258    log_scope s (LOGGER, __func__, FMT, A0, A1)
     259  
     260  #define LOG_FUNC_3(LOGGER, FMT, A0, A1, A2)	\
     261    log_scope s (LOGGER, __func__, FMT, A0, A1, A2)
     262  
     263  #define LOG_FUNC_4(LOGGER, FMT, A0, A1, A2, A3) \
     264    log_scope s (LOGGER, __func__, FMT, A0, A1, A2, A3)
     265  
     266  } // namespace ana
     267  
     268  #endif /* ANALYZER_LOGGING_H */