/* Functions to enable and disable individual warnings on an expression and statement basis. Copyright (C) 2021-2022 Free Software Foundation, Inc. This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see . */ #include "config.h" #include "system.h" #include "coretypes.h" #include "backend.h" #include "bitmap.h" #include "tree.h" #include "gimple.h" #include "cgraph.h" #include "hash-map.h" #include "diagnostic-spec.h" /* Return the no-warning bit for EXPR. */ static inline bool get_no_warning_bit (const_tree expr) { return expr->base.nowarning_flag; } /* Return the no-warning bit for statement STMT. */ static inline bool get_no_warning_bit (const gimple *stmt) { return stmt->no_warning; } /* Set the no-warning bit for EXPR to VALUE. */ static inline void set_no_warning_bit (tree expr, bool value) { expr->base.nowarning_flag = value; } /* Set the no-warning bit for statement STMT to VALUE. */ static inline void set_no_warning_bit (gimple *stmt, bool value) { stmt->no_warning = value; } /* Return EXPR location or 'UNKNOWN_LOCATION'. */ static inline location_t get_location (const_tree expr) { if (DECL_P (expr)) return DECL_SOURCE_LOCATION (expr); if (EXPR_P (expr)) return EXPR_LOCATION (expr); return UNKNOWN_LOCATION; } /* Return STMT location (may be 'UNKNOWN_LOCATION'). */ static inline location_t get_location (const gimple *stmt) { return gimple_location (stmt); } /* Return the no-warning bitmap for decl/expression EXPR. */ static nowarn_spec_t * get_nowarn_spec (const_tree expr) { const location_t loc = get_location (expr); if (RESERVED_LOCATION_P (loc)) return NULL; if (!get_no_warning_bit (expr)) return NULL; return nowarn_map ? nowarn_map->get (loc) : NULL; } /* Return the no-warning bitmap for statement STMT. */ static nowarn_spec_t * get_nowarn_spec (const gimple *stmt) { const location_t loc = get_location (stmt); if (RESERVED_LOCATION_P (loc)) return NULL; if (!get_no_warning_bit (stmt)) return NULL; return nowarn_map ? nowarn_map->get (loc) : NULL; } /* Return true if warning OPT is suppressed for decl/expression EXPR. By default tests the disposition for any warning. */ bool warning_suppressed_p (const_tree expr, opt_code opt /* = all_warnings */) { const nowarn_spec_t *spec = get_nowarn_spec (expr); if (!spec) return get_no_warning_bit (expr); const nowarn_spec_t optspec (opt); bool dis = *spec & optspec; gcc_assert (get_no_warning_bit (expr) || !dis); return dis; } /* Return true if warning OPT is suppressed for statement STMT. By default tests the disposition for any warning. */ bool warning_suppressed_p (const gimple *stmt, opt_code opt /* = all_warnings */) { const nowarn_spec_t *spec = get_nowarn_spec (stmt); if (!spec) /* Fall back on the single no-warning bit. */ return get_no_warning_bit (stmt); const nowarn_spec_t optspec (opt); bool dis = *spec & optspec; gcc_assert (get_no_warning_bit (stmt) || !dis); return dis; } /* Enable, or by default disable, a warning for the expression. The wildcard OPT of -1 controls all warnings. */ void suppress_warning (tree expr, opt_code opt /* = all_warnings */, bool supp /* = true */) { if (opt == no_warning) return; const location_t loc = get_location (expr); if (!RESERVED_LOCATION_P (loc)) supp = suppress_warning_at (loc, opt, supp) || supp; set_no_warning_bit (expr, supp); } /* Enable, or by default disable, a warning for the statement STMT. The wildcard OPT of -1 controls all warnings. */ void suppress_warning (gimple *stmt, opt_code opt /* = all_warnings */, bool supp /* = true */) { if (opt == no_warning) return; const location_t loc = get_location (stmt); if (!RESERVED_LOCATION_P (loc)) supp = suppress_warning_at (loc, opt, supp) || supp; set_no_warning_bit (stmt, supp); } /* Copy the warning disposition mapping between an expression and/or a statement. */ template void copy_warning (ToType to, FromType from) { const location_t to_loc = get_location (to); bool supp = get_no_warning_bit (from); nowarn_spec_t *from_spec = get_nowarn_spec (from); if (RESERVED_LOCATION_P (to_loc)) /* We cannot set no-warning dispositions for 'to', so we have no chance but lose those potentially set for 'from'. */ ; else { if (from_spec) { /* If there's an entry in the map the no-warning bit must be set. */ gcc_assert (supp); gcc_checking_assert (nowarn_map); nowarn_spec_t tem = *from_spec; nowarn_map->put (to_loc, tem); } else { if (nowarn_map) nowarn_map->remove (to_loc); } } /* The no-warning bit might be set even if the map has not been consulted, or otherwise if there's no entry in the map. */ set_no_warning_bit (to, supp); } /* Copy the warning disposition mapping from one expression to another. */ void copy_warning (tree to, const_tree from) { copy_warning(to, from); } /* Copy the warning disposition mapping from a statement to an expression. */ void copy_warning (tree to, const gimple *from) { copy_warning(to, from); } /* Copy the warning disposition mapping from an expression to a statement. */ void copy_warning (gimple *to, const_tree from) { copy_warning(to, from); } /* Copy the warning disposition mapping from one statement to another. */ void copy_warning (gimple *to, const gimple *from) { copy_warning(to, from); }