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: 2026-02-28 14:20: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       705442 : option_classifier::init (int n_opts)
      31              : {
      32       705442 :   m_n_opts = n_opts;
      33       705442 :   m_classify_diagnostic = XNEWVEC (enum kind, n_opts);
      34    730153708 :   for (int i = 0; i < n_opts; i++)
      35    729448266 :     m_classify_diagnostic[i] = kind::unspecified;
      36       705442 :   m_push_list = vNULL;
      37       705442 :   m_classification_history = vNULL;
      38       705442 : }
      39              : 
      40              : void
      41       305101 : option_classifier::fini ()
      42              : {
      43       305101 :   XDELETEVEC (m_classify_diagnostic);
      44       305101 :   m_classify_diagnostic = nullptr;
      45       305101 :   m_classification_history.release ();
      46       305101 :   m_push_list.release ();
      47       305101 : }
      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          428 : option_classifier::pch_save (FILE *f)
      54              : {
      55          428 :   unsigned int lengths[2] = { m_classification_history.length (),
      56          428 :                               m_push_list.length () };
      57          428 :   if (fwrite (lengths, sizeof (lengths), 1, f) != 1
      58          428 :       || (lengths[0]
      59           64 :           && fwrite (m_classification_history.address (),
      60              :                      sizeof (classification_change_t),
      61           32 :                      lengths[0], f) != lengths[0])
      62          856 :       || (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      4352841 : option_classifier::push ()
      97              : {
      98      8667210 :   m_push_list.safe_push (m_classification_history.length ());
      99      4352841 : }
     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      4352198 : option_classifier::pop (location_t where)
     106              : {
     107      4352198 :   int jump_to;
     108              : 
     109      4352198 :   if (!m_push_list.is_empty ())
     110      4352191 :     jump_to = m_push_list.pop ();
     111              :   else
     112              :     jump_to = 0;
     113              : 
     114      4352198 :   classification_change_t v = { where, jump_to, kind::pop };
     115      4352198 :   m_classification_history.safe_push (v);
     116      4352198 : }
     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      5108092 : option_classifier::classify_diagnostic (const context *dc,
     125              :                                         option_id opt_id,
     126              :                                         enum kind new_kind,
     127              :                                         location_t where)
     128              : {
     129      5108092 :   enum kind old_kind;
     130              : 
     131      5108092 :   if (opt_id.m_idx < 0
     132      5108092 :       || opt_id.m_idx >= m_n_opts
     133      5108092 :       || new_kind >= kind::last_diagnostic_kind)
     134              :     return kind::unspecified;
     135              : 
     136      5108092 :   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      5108092 :   if (where != UNKNOWN_LOCATION)
     141              :     {
     142      4037701 :       unsigned i;
     143              : 
     144              :       /* Record the command-line status, so we can reset it back on kind::pop. */
     145      4037701 :       if (old_kind == kind::unspecified)
     146              :         {
     147       523637 :           old_kind = (!dc->option_enabled_p (opt_id)
     148       348876 :                       ? kind::ignored : kind::any);
     149       348876 :           m_classify_diagnostic[opt_id.m_idx] = old_kind;
     150              :         }
     151              : 
     152      4037701 :       classification_change_t *p;
     153    152573252 :       FOR_EACH_VEC_ELT_REVERSE (m_classification_history, i, p)
     154    148218364 :         if (p->option == opt_id.m_idx)
     155              :           {
     156      3682126 :             old_kind = p->kind;
     157      3682126 :             break;
     158              :           }
     159              : 
     160      4037701 :       classification_change_t v
     161      4037701 :         = { where, opt_id.m_idx, new_kind };
     162      4037701 :       m_classification_history.safe_push (v);
     163              :     }
     164              :   else
     165      1070391 :     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      3076070 : option_classifier::
     180              : update_effective_level_from_pragmas (diagnostic_info *diagnostic) const
     181              : {
     182      4449707 :   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     10294430 :   for (location_t loc: diagnostic->m_iinfo.m_ilocs)
     190              :     {
     191              :       /* FIXME: Stupid search.  Optimize later. */
     192      2974055 :       unsigned int i;
     193      2974055 :       classification_change_t *p;
     194    621960027 :       FOR_EACH_VEC_ELT_REVERSE (m_classification_history, i, p)
     195              :         {
     196    616239804 :           location_t pragloc = p->location;
     197    616239804 :           if (!linemap_location_before_p (line_table, pragloc, loc))
     198    614638833 :             continue;
     199              : 
     200    139706893 :           if (p->kind == kind::pop)
     201              :             {
     202              :               /* Move on to the next region.  */
     203    136823318 :               i = p->option;
     204    136823318 :               continue;
     205              :             }
     206              : 
     207      2883575 :           option_id opt_id = p->option;
     208              :           /* The option 0 is for all the diagnostics.  */
     209      2883575 :           if (opt_id == 0 || opt_id == diagnostic->m_option_id)
     210              :             {
     211      1600971 :               enum kind kind = p->kind;
     212      1600971 :               if (kind != diagnostics::kind::unspecified)
     213      1600971 :                 diagnostic->m_kind = kind;
     214      1600971 :               return kind;
     215              :             }
     216              :         }
     217              :     }
     218              : 
     219              :   return kind::unspecified;
     220              : }
     221              : 
     222              : } // 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.