LCOV - code coverage report
Current view: top level - gcc/diagnostics - option-classifier.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 92.5 % 80 74
Test Date: 2026-08-01 15:33:25 Functions: 100.0 % 8 8
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Stacks of set of classifications of diagnostics.
       2              :    Copyright (C) 1999-2026 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       735313 : option_classifier::init (int n_opts)
      31              : {
      32       735313 :   m_n_opts = n_opts;
      33       735313 :   m_classify_diagnostic = XNEWVEC (enum kind, n_opts);
      34    759399209 :   for (int i = 0; i < n_opts; i++)
      35    758663896 :     m_classify_diagnostic[i] = kind::unspecified;
      36       735313 :   m_push_list = vNULL;
      37       735313 :   m_classification_history = vNULL;
      38       735313 : }
      39              : 
      40              : void
      41       313212 : option_classifier::fini ()
      42              : {
      43       313212 :   XDELETEVEC (m_classify_diagnostic);
      44       313212 :   m_classify_diagnostic = nullptr;
      45       313212 :   m_classification_history.release ();
      46       313212 :   m_push_list.release ();
      47       313212 : }
      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          470 : option_classifier::pch_save (FILE *f)
      54              : {
      55          470 :   unsigned int lengths[2] = { m_classification_history.length (),
      56          470 :                               m_push_list.length () };
      57          470 :   if (fwrite (lengths, sizeof (lengths), 1, f) != 1
      58          470 :       || (lengths[0]
      59           64 :           && fwrite (m_classification_history.address (),
      60              :                      sizeof (classification_change_t),
      61           32 :                      lengths[0], f) != lengths[0])
      62          940 :       || (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          350 : option_classifier::pch_restore (FILE *f)
      74              : {
      75          350 :   unsigned int lengths[2];
      76          350 :   if (fread (lengths, sizeof (lengths), 1, f) != 1)
      77              :     return -1;
      78          350 :   gcc_checking_assert (m_classification_history.is_empty ());
      79          350 :   gcc_checking_assert (m_push_list.is_empty ());
      80          350 :   m_classification_history.safe_grow (lengths[0]);
      81          350 :   m_push_list.safe_grow (lengths[1]);
      82          350 :   if ((lengths[0]
      83           48 :        && fread (m_classification_history.address (),
      84              :                  sizeof (classification_change_t),
      85           24 :                  lengths[0], f) != lengths[0])
      86          374 :       || (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      4877556 : option_classifier::push ()
      97              : {
      98      9715289 :   m_push_list.safe_push (m_classification_history.length ());
      99      4877556 : }
     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      4876951 : option_classifier::pop (location_t where)
     106              : {
     107      4876951 :   int jump_to;
     108              : 
     109      4876951 :   if (!m_push_list.is_empty ())
     110      4876944 :     jump_to = m_push_list.pop ();
     111              :   else
     112              :     jump_to = 0;
     113              : 
     114      4876951 :   classification_change_t v = { where, jump_to, kind::pop };
     115      4876951 :   m_classification_history.safe_push (v);
     116      4876951 : }
     117              : 
     118              : /* Interface to specify diagnostic kind overrides.  If OPTION_ID is zero, the
     119              :    new setting is for all the diagnostics.  */
     120              : 
     121              : void
     122      5630908 : option_classifier::classify_diagnostic (const context *dc,
     123              :                                         option_id opt_id,
     124              :                                         enum kind new_kind,
     125              :                                         location_t where)
     126              : {
     127      5630908 :   if (opt_id.m_idx < 0
     128      5630908 :       || opt_id.m_idx >= m_n_opts
     129      5630908 :       || new_kind >= kind::last_diagnostic_kind)
     130              :     return;
     131              : 
     132      5630908 :   auto &base_kind = m_classify_diagnostic[opt_id.m_idx];
     133              : 
     134              :   /* Handle pragmas separately, since we need to keep track of *where*
     135              :      the pragmas were.  */
     136      5630908 :   if (where != UNKNOWN_LOCATION)
     137              :     {
     138              :       /* Record the command-line status, so we can reset it back on kind::pop. */
     139      4527306 :       if (base_kind == kind::unspecified)
     140       776374 :         base_kind = (!dc->option_enabled_p (opt_id)
     141       388187 :                      ? kind::ignored : kind::any);
     142              : 
     143      4527306 :       classification_change_t v
     144      4527306 :         = { where, opt_id.m_idx, new_kind };
     145      4527306 :       m_classification_history.safe_push (v);
     146              :     }
     147              :   else
     148      1103602 :     base_kind = new_kind;
     149              : }
     150              : 
     151              : /* Update the kind of DIAGNOSTIC based on its location(s), including
     152              :    any of those in its inlining stack, relative to any
     153              :      #pragma GCC diagnostic
     154              :    directives recorded within this object.
     155              : 
     156              :    Return the new kind of DIAGNOSTIC if it was updated, or kind::unspecified
     157              :    otherwise.  */
     158              : 
     159              : enum kind
     160      3786284 : option_classifier::
     161              : update_effective_level_from_pragmas (diagnostic_info *diagnostic) const
     162              : {
     163      5590476 :   if (m_classification_history.is_empty ())
     164              :     return kind::unspecified;
     165              : 
     166              :   /* Iterate over the locations, checking the diagnostic disposition
     167              :      for the diagnostic at each.  If it's explicitly set as opposed
     168              :      to unspecified, update the disposition for this instance of
     169              :      the diagnostic and return it.  */
     170     12850692 :   for (location_t loc: diagnostic->m_iinfo.m_ilocs)
     171              :     {
     172              :       /* FIXME: Stupid search.  Optimize later. */
     173      3682679 :       unsigned int i;
     174      3682679 :       classification_change_t *p;
     175    870490331 :       FOR_EACH_VEC_ELT_REVERSE (m_classification_history, i, p)
     176              :         {
     177    863200254 :           location_t pragloc = p->location;
     178    863200254 :           if (!linemap_location_before_p (line_table, pragloc, loc))
     179    861321274 :             continue;
     180              : 
     181    208744547 :           if (p->kind == kind::pop)
     182              :             {
     183              :               /* Move on to the next region.  */
     184    205101907 :               i = p->option;
     185    205101907 :               continue;
     186              :             }
     187              : 
     188      3642640 :           option_id opt_id = p->option;
     189              :           /* The option 0 is for all the diagnostics.  */
     190      3642640 :           if (opt_id == 0 || opt_id == diagnostic->m_option_id)
     191              :             {
     192      1878980 :               enum kind kind = p->kind;
     193      1878980 :               if (kind != diagnostics::kind::unspecified)
     194      1878980 :                 diagnostic->m_kind = kind;
     195      1878980 :               return kind;
     196              :             }
     197              :         }
     198              :     }
     199              : 
     200              :   return kind::unspecified;
     201              : }
     202              : 
     203              : } // namespace diagnostics
        

Generated by: LCOV version 2.4-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.