LCOV - code coverage report
Current view: top level - gcc/rust - rust-diagnostics.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 68.4 % 38 26
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 2 2
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // Copyright (C) 2020-2026 Free Software Foundation, Inc.
       2              : 
       3              : // This file is part of GCC.
       4              : 
       5              : // GCC is free software; you can redistribute it and/or modify it under
       6              : // the terms of the GNU General Public License as published by the Free
       7              : // Software Foundation; either version 3, or (at your option) any later
       8              : // version.
       9              : 
      10              : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      11              : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12              : // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      13              : // for more details.
      14              : 
      15              : // You should have received a copy of the GNU General Public License
      16              : // along with GCC; see the file COPYING3.  If not see
      17              : // <http://www.gnu.org/licenses/>.
      18              : 
      19              : // rust-diagnostics.h -- interface to diagnostic reporting   -*- C++ -*-
      20              : 
      21              : #ifndef RUST_DIAGNOSTICS_H
      22              : #define RUST_DIAGNOSTICS_H
      23              : 
      24              : #include "rust-linemap.h"
      25              : #include "util/optional.h"
      26              : 
      27              : // This macro is used to specify the position of format string & it's
      28              : // arguments within the function's parameter list.
      29              : // 'm' specifies the position of the format string parameter.
      30              : // 'n' specifies the position of the first argument for the format string.
      31              : #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)
      32              : #define RUST_ATTRIBUTE_GCC_DIAG(m, n)                                          \
      33              :   __attribute__ ((__format__ (__gcc_tdiag__, m, n)))                           \
      34              :   __attribute__ ((__nonnull__ (m)))
      35              : #else
      36              : #define RUST_ATTRIBUTE_GCC_DIAG(m, n)
      37              : #endif
      38              : 
      39              : // These declarations define the interface through which the frontend
      40              : // reports errors and warnings. These functions accept printf-like
      41              : // format specifiers (e.g. %d, %f, %s, etc), with the following additional
      42              : // extensions:
      43              : //
      44              : //  1.  'q' qualifier may be applied to a specifier to add quoting, e.g.
      45              : //      %qd produces a quoted decimal output, %qs a quoted string output.
      46              : //      [This extension is supported only with single-character format
      47              : //      specifiers].
      48              : //
      49              : //  2.  %m specifier outputs value of "strerror(errno)" at time of call.
      50              : //
      51              : //  3.  %< outputs an opening quote, %> a closing quote.
      52              : //
      53              : // All other format specifiers are as defined by 'sprintf'. The final resulting
      54              : // message is then sent to the back end via rust_be_error_at/rust_be_warning_at.
      55              : 
      56              : // simple location
      57              : 
      58              : // https://gist.github.com/MahadMuhammad/8c9d5fc88ea18d8c520937a8071d4185
      59              : 
      60              : // We want E0005 to be mapped to the value `5` - this way, we can easily format
      61              : // it in `make_description`. We also want to keep the value "5" only once when
      62              : // defining the error code in rust-error-codes.def, so not have ERROR(E0005, 5)
      63              : // as that is error prone. If we just use `0005` as the discriminant for the
      64              : // `E0005` enum variant, then we are actually creating octal values (!) as `0`
      65              : // is the C/C++ octal prefix. So this does not work for `E0009` for example,
      66              : // since 0009 is not a valid octal literal.
      67              : // We can circumvent this by doing a little bit of constant folding in the
      68              : // discriminant expression. So for ERROR(E0009), this macro expands to the
      69              : // following variant:
      70              : //
      71              : // E0009 = (10009 - 10000)
      72              : //
      73              : // which gets folded to the result of the substraction... 9. A valid decimal
      74              : // literal which corresponds to E0009.
      75              : #define ERROR(N) E##N = (1##N - 10000)
      76              : enum class ErrorCode : unsigned int
      77              : {
      78              : #include "rust-error-codes.def"
      79              : };
      80              : #undef ERROR
      81              : 
      82              : // clang-format off
      83              : extern void
      84              : rust_internal_error_at (const location_t, const char *fmt, ...)
      85              :   RUST_ATTRIBUTE_GCC_DIAG (2, 3)
      86              :   RUST_ATTRIBUTE_NORETURN;
      87              : extern void
      88              : rust_error_at (const location_t, const char *fmt, ...)
      89              :   RUST_ATTRIBUTE_GCC_DIAG (2, 3);
      90              : extern void
      91              : rust_error_at (const location_t, const ErrorCode, const char *fmt, ...)
      92              :   RUST_ATTRIBUTE_GCC_DIAG (3, 4);
      93              : extern void
      94              : rust_warning_at (const location_t, int opt, const char *fmt, ...)
      95              :   RUST_ATTRIBUTE_GCC_DIAG (3, 4);
      96              : extern void
      97              : rust_fatal_error (const location_t, const char *fmt, ...)
      98              :   RUST_ATTRIBUTE_GCC_DIAG (2, 3)
      99              :   RUST_ATTRIBUTE_NORETURN;
     100              : extern void
     101              : rust_inform (const location_t, const char *fmt, ...)
     102              :   RUST_ATTRIBUTE_GCC_DIAG (2, 3);
     103              : 
     104              : // rich locations
     105              : extern void
     106              : rust_error_at (const rich_location &, const char *fmt, ...)
     107              :   RUST_ATTRIBUTE_GCC_DIAG (2, 3);
     108              : extern void
     109              : rust_error_at (const rich_location &, const ErrorCode, const char *fmt, ...)
     110              :   RUST_ATTRIBUTE_GCC_DIAG (3, 4);
     111              : extern void /* similiar to other frontends */
     112              : rust_error_at(rich_location *richloc,const char *fmt, ...)
     113              :   RUST_ATTRIBUTE_GCC_DIAG (2, 3);
     114              : extern void /* similiar to other frontends */
     115              : rust_error_at(rich_location *richloc, const ErrorCode, const char *fmt, ...)
     116              :   RUST_ATTRIBUTE_GCC_DIAG (3, 4);
     117              : // clang-format on
     118              : 
     119              : // These interfaces provide a way for the front end to ask for
     120              : // the open/close quote characters it should use when formatting
     121              : // diagnostics (warnings, errors).
     122              : extern const char *rust_open_quote ();
     123              : extern const char *rust_close_quote ();
     124              : 
     125              : // These interfaces are used by utilities above to pass warnings and
     126              : // errors (once format specifiers have been expanded) to the back end,
     127              : // and to determine quoting style. Avoid calling these routines directly;
     128              : // instead use the equivalent routines above. The back end is required to
     129              : // implement these routines.
     130              : 
     131              : // clang-format off
     132              : extern void
     133              : rust_be_internal_error_at (const location_t, const std::string &errmsg)
     134              :   RUST_ATTRIBUTE_NORETURN;
     135              : extern void
     136              : rust_be_error_at (const location_t, const std::string &errmsg);
     137              : extern void
     138              : rust_be_error_at (const location_t, const ErrorCode,
     139              :                   const std::string &errmsg);
     140              : extern void
     141              : rust_be_error_at (const rich_location &, const std::string &errmsg);
     142              : extern void
     143              : rust_be_error_at (const rich_location &, const ErrorCode,
     144              :                   const std::string &errmsg);
     145              : extern void /* similiar to other frontends */
     146              : rust_be_error_at (rich_location *richloc, const std::string &errmsg);
     147              : extern void /* similiar to other frontends */
     148              : rust_be_error_at (rich_location *richloc, const ErrorCode,
     149              :       const std::string &errmsg);
     150              : extern void
     151              : rust_be_warning_at (const location_t, int opt, const std::string &warningmsg);
     152              : extern void
     153              : rust_be_fatal_error (const location_t, const std::string &errmsg)
     154              :   RUST_ATTRIBUTE_NORETURN;
     155              : extern void
     156              : rust_be_inform (const location_t, const std::string &infomsg);
     157              : extern void
     158              : rust_be_get_quotechars (const char **open_quote, const char **close_quote);
     159              : extern bool
     160              : rust_be_debug_p (void);
     161              : // clang-format on
     162              : 
     163              : namespace Rust {
     164              : /* A structure used to represent an error. Useful for enabling
     165              :  * errors to be ignored, e.g. if backtracking. */
     166        13148 : struct Error
     167              : {
     168              :   enum class Kind
     169              :   {
     170              :     Hint,
     171              :     Err,
     172              :     FatalErr,
     173              :   };
     174              : 
     175              :   Kind kind;
     176              :   location_t locus;
     177              :   rich_location *richlocus = nullptr;
     178              :   ErrorCode errorcode;
     179              :   std::string message;
     180              :   bool is_errorcode = false;
     181              : 
     182              :   // simple location
     183         7060 :   Error (Kind kind, location_t locus, std::string message)
     184        11708 :     : kind (kind), locus (locus), message (std::move (message))
     185              :   {
     186         7060 :     this->message.shrink_to_fit ();
     187              :   }
     188              :   // simple location + error code
     189           56 :   Error (Kind kind, location_t locus, ErrorCode code, std::string message)
     190           56 :     : kind (kind), locus (locus), errorcode (std::move (code)),
     191           56 :       message (std::move (message))
     192              :   {
     193           56 :     is_errorcode = true;
     194           56 :     this->message.shrink_to_fit ();
     195              :   }
     196              :   // rich location
     197            0 :   Error (Kind kind, rich_location *richlocus, std::string message)
     198            0 :     : kind (kind), richlocus (richlocus), message (std::move (message))
     199              :   {
     200            0 :     this->message.shrink_to_fit ();
     201              :   }
     202              :   // rich location + error code
     203            0 :   Error (Kind kind, rich_location *richlocus, ErrorCode code,
     204              :          std::string message)
     205            0 :     : kind (kind), richlocus (richlocus), errorcode (std::move (code)),
     206            0 :       message (std::move (message))
     207              :   {
     208            0 :     is_errorcode = true;
     209            0 :     this->message.shrink_to_fit ();
     210              :   }
     211              :   // simple location
     212         4648 :   Error (location_t locus, std::string message)
     213         4648 :   {
     214         9296 :     Error (Kind::Err, locus, std::move (message));
     215         4648 :   }
     216              :   // simple location + error code
     217              :   Error (location_t locus, ErrorCode code, std::string message)
     218              :   {
     219              :     Error (Kind::Err, locus, std::move (code), std::move (message));
     220              :   }
     221              :   // rich location
     222              :   Error (rich_location *richlocus, std::string message)
     223              :   {
     224              :     Error (Kind::Err, richlocus, std::move (message));
     225              :   }
     226              :   // rich location + error code
     227              :   Error (rich_location *richlocus, ErrorCode code, std::string message)
     228              :   {
     229              :     Error (Kind::Err, richlocus, std::move (code), std::move (message));
     230              :   }
     231              : 
     232              :   static Error Hint (location_t locus, std::string message)
     233              :   {
     234              :     return Error (Kind::Hint, locus, std::move (message));
     235              :   }
     236              : 
     237              :   static Error Fatal (location_t locus, std::string message)
     238              :   {
     239              :     return Error (Kind::FatalErr, locus, std::move (message));
     240              :   }
     241              : 
     242              :   // TODO: the attribute part might be incorrect
     243              :   // simple location
     244              :   Error (location_t locus, const char *fmt,
     245              :          ...) /*RUST_ATTRIBUTE_GCC_DIAG (2, 3)*/ RUST_ATTRIBUTE_GCC_DIAG (3, 4);
     246              : 
     247              :   // simple location + error code
     248              :   Error (location_t locus, ErrorCode code, const char *fmt,
     249              :          ...) /*RUST_ATTRIBUTE_GCC_DIAG (3, 4)*/ RUST_ATTRIBUTE_GCC_DIAG (4, 5);
     250              : 
     251              :   // rich location
     252              :   Error (rich_location *richlocus, const char *fmt,
     253              :          ...) /*RUST_ATTRIBUTE_GCC_DIAG (2, 3)*/ RUST_ATTRIBUTE_GCC_DIAG (3, 4);
     254              : 
     255              :   // rich location + error code
     256              :   Error (rich_location *richlocus, ErrorCode code, const char *fmt,
     257              :          ...) /*RUST_ATTRIBUTE_GCC_DIAG (3, 4)*/ RUST_ATTRIBUTE_GCC_DIAG (4, 5);
     258              : 
     259              :   /**
     260              :    * printf-like overload of Error::Hint
     261              :    */
     262              :   static Error Hint (location_t locus, const char *fmt, ...)
     263              :     RUST_ATTRIBUTE_GCC_DIAG (2, 3);
     264              : 
     265              :   /**
     266              :    * printf-like overload of Error::Fatal
     267              :    */
     268              :   static Error Fatal (location_t locus, const char *fmt, ...)
     269              :     RUST_ATTRIBUTE_GCC_DIAG (2, 3);
     270              : 
     271          219 :   void emit () const
     272              :   {
     273          219 :     switch (kind)
     274              :       {
     275            7 :       case Kind::Hint:
     276            7 :         rust_inform (locus, "%s", message.c_str ());
     277            7 :         break;
     278          212 :       case Kind::Err:
     279          212 :         if (is_errorcode)
     280              :           {
     281           36 :             if (richlocus == nullptr)
     282           36 :               rust_error_at (locus, errorcode, "%s", message.c_str ());
     283              :             else
     284            0 :               rust_error_at (*richlocus, errorcode, "%s", message.c_str ());
     285              :           }
     286              :         else
     287              :           {
     288          176 :             if (richlocus == nullptr)
     289          176 :               rust_error_at (locus, "%s", message.c_str ());
     290              :             else
     291            0 :               rust_error_at (*richlocus, "%s", message.c_str ());
     292              :           }
     293              :         break;
     294            0 :       case Kind::FatalErr:
     295            0 :         rust_fatal_error (locus, "%s", message.c_str ());
     296          219 :         break;
     297              :       }
     298          219 :   }
     299              : };
     300              : } // namespace Rust
     301              : 
     302              : // rust_debug uses normal printf formatting, not GCC diagnostic formatting.
     303              : #define rust_debug(...) rust_debug_loc (UNDEF_LOCATION, __VA_ARGS__)
     304              : 
     305              : #define rust_sorry_at(location, ...) sorry_at (location, __VA_ARGS__)
     306              : 
     307              : void rust_debug_loc (const location_t location, const char *fmt,
     308              :                      ...) ATTRIBUTE_PRINTF_2;
     309              : 
     310              : #endif // !defined(RUST_DIAGNOSTICS_H)
        

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.