| /* Functions to enable and disable individual warnings on an expression |
| and statement basis. |
| |
| Copyright (C) 2021 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 |
| <http://www.gnu.org/licenses/>. */ |
| |
| #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 stateemt 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 <class ToType, class FromType> |
| 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_map->put (to_loc, *from_spec); |
| } |
| 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<tree, const_tree>(to, from); |
| } |
| |
| /* Copy the warning disposition mapping from a statement to an expression. */ |
| |
| void |
| copy_warning (tree to, const gimple *from) |
| { |
| copy_warning<tree, const gimple *>(to, from); |
| } |
| |
| /* Copy the warning disposition mapping from an expression to a statement. */ |
| |
| void |
| copy_warning (gimple *to, const_tree from) |
| { |
| copy_warning<gimple *, const_tree>(to, from); |
| } |
| |
| /* Copy the warning disposition mapping from one statement to another. */ |
| |
| void |
| copy_warning (gimple *to, const gimple *from) |
| { |
| copy_warning<gimple *, const gimple *>(to, from); |
| } |