LCOV - code coverage report
Current view: top level - gcc/diagnostics - option-classifier.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 93.2 % 88 82
Test Date: 2025-09-20 13:40:47 Functions: 100.0 % 8 8
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Stacks of set of classifications of diagnostics.
       2                 :             :    Copyright (C) 1999-2025 Free Software Foundation, Inc.
       3                 :             : 
       4                 :             : This file is part of GCC.
       5                 :             : 
       6                 :             : GCC is free software; you can redistribute it and/or modify it under
       7                 :             : the terms of the GNU General Public License as published by the Free
       8                 :             : Software Foundation; either version 3, or (at your option) any later
       9                 :             : version.
      10                 :             : 
      11                 :             : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12                 :             : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13                 :             : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14                 :             : for more details.
      15                 :             : 
      16                 :             : You should have received a copy of the GNU General Public License
      17                 :             : along with GCC; see the file COPYING3.  If not see
      18                 :             : <http://www.gnu.org/licenses/>.  */
      19                 :             : 
      20                 :             : 
      21                 :             : #include "config.h"
      22                 :             : #include "system.h"
      23                 :             : #include "coretypes.h"
      24                 :             : #include "version.h"
      25                 :             : #include "diagnostic.h"
      26                 :             : 
      27                 :             : namespace diagnostics {
      28                 :             : 
      29                 :             : void
      30                 :      709618 : option_classifier::init (int n_opts)
      31                 :             : {
      32                 :      709618 :   m_n_opts = n_opts;
      33                 :      709618 :   m_classify_diagnostic = XNEWVEC (enum kind, n_opts);
      34                 :   703218869 :   for (int i = 0; i < n_opts; i++)
      35                 :   702509251 :     m_classify_diagnostic[i] = kind::unspecified;
      36                 :      709618 :   m_push_list = vNULL;
      37                 :      709618 :   m_classification_history = vNULL;
      38                 :      709618 : }
      39                 :             : 
      40                 :             : void
      41                 :      304801 : option_classifier::fini ()
      42                 :             : {
      43                 :      304801 :   XDELETEVEC (m_classify_diagnostic);
      44                 :      304801 :   m_classify_diagnostic = nullptr;
      45                 :      304801 :   m_classification_history.release ();
      46                 :      304801 :   m_push_list.release ();
      47                 :      304801 : }
      48                 :             : 
      49                 :             : /* Save the diagnostics::option_classifier state to F for PCH
      50                 :             :    output.  Returns 0 on success, -1 on error.  */
      51                 :             : 
      52                 :             : int
      53                 :         435 : option_classifier::pch_save (FILE *f)
      54                 :             : {
      55                 :         435 :   unsigned int lengths[2] = { m_classification_history.length (),
      56                 :         435 :                               m_push_list.length () };
      57                 :         435 :   if (fwrite (lengths, sizeof (lengths), 1, f) != 1
      58                 :         435 :       || (lengths[0]
      59                 :          64 :           && fwrite (m_classification_history.address (),
      60                 :             :                      sizeof (classification_change_t),
      61                 :          32 :                      lengths[0], f) != lengths[0])
      62                 :         870 :       || (lengths[1]
      63                 :           0 :           && fwrite (m_push_list.address (), sizeof (int),
      64                 :           0 :                      lengths[1], f) != lengths[1]))
      65                 :           0 :     return -1;
      66                 :             :   return 0;
      67                 :             : }
      68                 :             : 
      69                 :             : /* Read the diagnostics::option_classifier state from F for PCH
      70                 :             :    read.  Returns 0 on success, -1 on error.  */
      71                 :             : 
      72                 :             : int
      73                 :         347 : option_classifier::pch_restore (FILE *f)
      74                 :             : {
      75                 :         347 :   unsigned int lengths[2];
      76                 :         347 :   if (fread (lengths, sizeof (lengths), 1, f) != 1)
      77                 :             :     return -1;
      78                 :         347 :   gcc_checking_assert (m_classification_history.is_empty ());
      79                 :         347 :   gcc_checking_assert (m_push_list.is_empty ());
      80                 :         347 :   m_classification_history.safe_grow (lengths[0]);
      81                 :         347 :   m_push_list.safe_grow (lengths[1]);
      82                 :         347 :   if ((lengths[0]
      83                 :          48 :        && fread (m_classification_history.address (),
      84                 :             :                  sizeof (classification_change_t),
      85                 :          24 :                  lengths[0], f) != lengths[0])
      86                 :         371 :       || (lengths[1]
      87                 :           0 :           && fread (m_push_list.address (), sizeof (int),
      88                 :           0 :                     lengths[1], f) != lengths[1]))
      89                 :           0 :     return -1;
      90                 :             :   return 0;
      91                 :             : }
      92                 :             : 
      93                 :             : /* Save all diagnostic classifications in a stack.  */
      94                 :             : 
      95                 :             : void
      96                 :     3976735 : option_classifier::push ()
      97                 :             : {
      98                 :     7914874 :   m_push_list.safe_push (m_classification_history.length ());
      99                 :     3976735 : }
     100                 :             : 
     101                 :             : /* Restore the topmost classification set off the stack.  If the stack
     102                 :             :    is empty, revert to the state based on command line parameters.  */
     103                 :             : 
     104                 :             : void
     105                 :     3976064 : option_classifier::pop (location_t where)
     106                 :             : {
     107                 :     3976064 :   int jump_to;
     108                 :             : 
     109                 :     3976064 :   if (!m_push_list.is_empty ())
     110                 :     3976051 :     jump_to = m_push_list.pop ();
     111                 :             :   else
     112                 :             :     jump_to = 0;
     113                 :             : 
     114                 :     3976064 :   classification_change_t v = { where, jump_to, kind::pop };
     115                 :     3976064 :   m_classification_history.safe_push (v);
     116                 :     3976064 : }
     117                 :             : 
     118                 :             : /* Interface to specify diagnostic kind overrides.  Returns the
     119                 :             :    previous setting, or kind::unspecified if the parameters are out of
     120                 :             :    range.  If OPTION_ID is zero, the new setting is for all the
     121                 :             :    diagnostics.  */
     122                 :             : 
     123                 :             : enum kind
     124                 :     4645984 : option_classifier::classify_diagnostic (const context *dc,
     125                 :             :                                         option_id opt_id,
     126                 :             :                                         enum kind new_kind,
     127                 :             :                                         location_t where)
     128                 :             : {
     129                 :     4645984 :   enum kind old_kind;
     130                 :             : 
     131                 :     4645984 :   if (opt_id.m_idx < 0
     132                 :     4645984 :       || opt_id.m_idx >= m_n_opts
     133                 :     4645984 :       || new_kind >= kind::last_diagnostic_kind)
     134                 :             :     return kind::unspecified;
     135                 :             : 
     136                 :     4645984 :   old_kind = m_classify_diagnostic[opt_id.m_idx];
     137                 :             : 
     138                 :             :   /* Handle pragmas separately, since we need to keep track of *where*
     139                 :             :      the pragmas were.  */
     140                 :     4645984 :   if (where != UNKNOWN_LOCATION)
     141                 :             :     {
     142                 :     3587079 :       unsigned i;
     143                 :             : 
     144                 :             :       /* Record the command-line status, so we can reset it back on kind::pop. */
     145                 :     3587079 :       if (old_kind == kind::unspecified)
     146                 :             :         {
     147                 :      482830 :           old_kind = (!dc->option_enabled_p (opt_id)
     148                 :      320834 :                       ? kind::ignored : kind::any);
     149                 :      320834 :           m_classify_diagnostic[opt_id.m_idx] = old_kind;
     150                 :             :         }
     151                 :             : 
     152                 :     3587079 :       classification_change_t *p;
     153                 :   115252154 :       FOR_EACH_VEC_ELT_REVERSE (m_classification_history, i, p)
     154                 :   111376941 :         if (p->option == opt_id.m_idx)
     155                 :             :           {
     156                 :     3260244 :             old_kind = p->kind;
     157                 :     3260244 :             break;
     158                 :             :           }
     159                 :             : 
     160                 :     3587079 :       classification_change_t v
     161                 :     3587079 :         = { where, opt_id.m_idx, new_kind };
     162                 :     3587079 :       m_classification_history.safe_push (v);
     163                 :             :     }
     164                 :             :   else
     165                 :     1058905 :     m_classify_diagnostic[opt_id.m_idx] = new_kind;
     166                 :             : 
     167                 :             :   return old_kind;
     168                 :             : }
     169                 :             : 
     170                 :             : /* Update the kind of DIAGNOSTIC based on its location(s), including
     171                 :             :    any of those in its inlining stack, relative to any
     172                 :             :      #pragma GCC diagnostic
     173                 :             :    directives recorded within this object.
     174                 :             : 
     175                 :             :    Return the new kind of DIAGNOSTIC if it was updated, or kind::unspecified
     176                 :             :    otherwise.  */
     177                 :             : 
     178                 :             : enum kind
     179                 :     2043427 : option_classifier::
     180                 :             : update_effective_level_from_pragmas (diagnostic_info *diagnostic) const
     181                 :             : {
     182                 :     2429425 :   if (m_classification_history.is_empty ())
     183                 :             :     return kind::unspecified;
     184                 :             : 
     185                 :             :   /* Iterate over the locations, checking the diagnostic disposition
     186                 :             :      for the diagnostic at each.  If it's explicitly set as opposed
     187                 :             :      to unspecified, update the disposition for this instance of
     188                 :             :      the diagnostic and return it.  */
     189                 :     6219408 :   for (location_t loc: diagnostic->m_iinfo.m_ilocs)
     190                 :             :     {
     191                 :             :       /* FIXME: Stupid search.  Optimize later. */
     192                 :     1944596 :       unsigned int i;
     193                 :     1944596 :       classification_change_t *p;
     194                 :    54462002 :       FOR_EACH_VEC_ELT_REVERSE (m_classification_history, i, p)
     195                 :             :         {
     196                 :    51745080 :           location_t pragloc = p->location;
     197                 :    51745080 :           if (!linemap_location_before_p (line_table, pragloc, loc))
     198                 :    50186647 :             continue;
     199                 :             : 
     200                 :    34395854 :           if (p->kind == kind::pop)
     201                 :             :             {
     202                 :             :               /* Move on to the next region.  */
     203                 :    32754890 :               i = p->option;
     204                 :    32754890 :               continue;
     205                 :             :             }
     206                 :             : 
     207                 :     1640964 :           option_id opt_id = p->option;
     208                 :             :           /* The option 0 is for all the diagnostics.  */
     209                 :     1640964 :           if (opt_id == 0 || opt_id == diagnostic->m_option_id)
     210                 :             :             {
     211                 :     1558433 :               enum kind kind = p->kind;
     212                 :     1558433 :               if (kind != diagnostics::kind::unspecified)
     213                 :     1558433 :                 diagnostic->m_kind = kind;
     214                 :     1558433 :               return kind;
     215                 :             :             }
     216                 :             :         }
     217                 :             :     }
     218                 :             : 
     219                 :             :   return kind::unspecified;
     220                 :             : }
     221                 :             : 
     222                 :             : } // namespace diagnostics
        

Generated by: LCOV version 2.1-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.