Home | History | Annotate | Line # | Download | only in cp
      1 /* Definitions for C++ contract levels.  Implements functionality described in
      2    the N4820 working draft version of contracts, P1290, P1332, and P1429.
      3    Copyright (C) 2020-2024 Free Software Foundation, Inc.
      4    Contributed by Jeff Chapman II (jchapman (at) lock3software.com)
      5 
      6 This file is part of GCC.
      7 
      8 GCC is free software; you can redistribute it and/or modify
      9 it under the terms of the GNU General Public License as published by
     10 the Free Software Foundation; either version 3, or (at your option)
     11 any later version.
     12 
     13 GCC is distributed in the hope that it will be useful,
     14 but WITHOUT ANY WARRANTY; without even the implied warranty of
     15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16 GNU General Public License for more details.
     17 
     18 You should have received a copy of the GNU General Public License
     19 along with GCC; see the file COPYING3.  If not see
     20 <http://www.gnu.org/licenses/>.  */
     21 
     22 #ifndef GCC_CP_CONTRACT_H
     23 #define GCC_CP_CONTRACT_H
     24 
     25 /* Contract levels approximate the complexity of the expression.  */
     26 
     27 enum contract_level
     28 {
     29   CONTRACT_INVALID,
     30   CONTRACT_DEFAULT,
     31   CONTRACT_AUDIT,
     32   CONTRACT_AXIOM
     33 };
     34 
     35 /* The concrete semantics determine the behavior of a contract.  */
     36 
     37 enum contract_semantic
     38 {
     39   CCS_INVALID,
     40   CCS_IGNORE,
     41   CCS_ASSUME,
     42   CCS_NEVER,
     43   CCS_MAYBE
     44 };
     45 
     46 /* True if the contract is unchecked.  */
     47 
     48 inline bool
     49 unchecked_contract_p (contract_semantic cs)
     50 {
     51   return cs == CCS_IGNORE || cs == CCS_ASSUME;
     52 }
     53 
     54 /* True if the contract is checked.  */
     55 
     56 inline bool
     57 checked_contract_p (contract_semantic cs)
     58 {
     59   return cs >= CCS_NEVER;
     60 }
     61 
     62 /* Must match std::contract_violation_continuation_mode in <contract>.  */
     63 enum contract_continuation
     64 {
     65   NEVER_CONTINUE,
     66   MAYBE_CONTINUE
     67 };
     68 
     69 /* Assertion role info.  */
     70 struct contract_role
     71 {
     72   const char *name;
     73   contract_semantic default_semantic;
     74   contract_semantic audit_semantic;
     75   contract_semantic axiom_semantic;
     76 };
     77 
     78 /* Information for configured contract semantics.  */
     79 
     80 struct contract_configuration
     81 {
     82   contract_level level;
     83   contract_role* role;
     84 };
     85 
     86 /* A contract mode contains information used to derive the checking
     87    and assumption semantics of a contract. This is either a dynamic
     88    configuration, meaning it derives from the build mode, or it is
     89    explicitly specified.  */
     90 
     91 struct contract_mode
     92 {
     93   contract_mode () : kind(cm_invalid) {}
     94   contract_mode (contract_level level, contract_role *role = NULL)
     95     : kind(cm_dynamic)
     96   {
     97     contract_configuration cc;
     98     cc.level = level;
     99     cc.role = role;
    100     u.config = cc;
    101   }
    102   contract_mode (contract_semantic semantic) : kind(cm_explicit)
    103   {
    104     u.semantic = semantic;
    105   }
    106 
    107   contract_level get_level () const
    108   {
    109     gcc_assert (kind == cm_dynamic);
    110     return u.config.level;
    111   }
    112 
    113   contract_role *get_role () const
    114   {
    115     gcc_assert (kind == cm_dynamic);
    116     return u.config.role;
    117   }
    118 
    119   contract_semantic get_semantic () const
    120   {
    121     gcc_assert (kind == cm_explicit);
    122     return u.semantic;
    123   }
    124 
    125   enum { cm_invalid, cm_dynamic, cm_explicit } kind;
    126 
    127   union
    128   {
    129     contract_configuration config;
    130     contract_semantic semantic;
    131   } u;
    132 };
    133 
    134 extern contract_role *get_contract_role	(const char *);
    135 extern contract_role *add_contract_role	(const char *,
    136 					 contract_semantic,
    137 					 contract_semantic,
    138 					 contract_semantic,
    139 					 bool = true);
    140 extern void validate_contract_role	(contract_role *);
    141 extern void setup_default_contract_role	(bool = true);
    142 extern contract_semantic lookup_concrete_semantic (const char *);
    143 
    144 /* Map a source level semantic or level name to its value, or invalid.  */
    145 extern contract_semantic map_contract_semantic	(const char *);
    146 extern contract_level map_contract_level	(const char *);
    147 
    148 /* Check if an attribute is a cxx contract attribute.  */
    149 extern bool cxx_contract_attribute_p (const_tree);
    150 extern bool cp_contract_assertion_p (const_tree);
    151 
    152 /* Returns the default role.  */
    153 
    154 inline contract_role *
    155 get_default_contract_role ()
    156 {
    157   return get_contract_role ("default");
    158 }
    159 
    160 /* Handle various command line arguments related to semantic mapping.  */
    161 extern void handle_OPT_fcontract_build_level_ (const char *);
    162 extern void handle_OPT_fcontract_assumption_mode_ (const char *);
    163 extern void handle_OPT_fcontract_continuation_mode_ (const char *);
    164 extern void handle_OPT_fcontract_role_ (const char *);
    165 extern void handle_OPT_fcontract_semantic_ (const char *);
    166 
    167 enum contract_matching_context
    168 {
    169   cmc_declaration,
    170   cmc_override
    171 };
    172 
    173 /* True if NODE is any kind of contract.  */
    174 #define CONTRACT_P(NODE)			\
    175   (TREE_CODE (NODE) == ASSERTION_STMT		\
    176    || TREE_CODE (NODE) == PRECONDITION_STMT	\
    177    || TREE_CODE (NODE) == POSTCONDITION_STMT)
    178 
    179 /* True if NODE is a contract condition.  */
    180 #define CONTRACT_CONDITION_P(NODE)		\
    181   (TREE_CODE (NODE) == PRECONDITION_STMT	\
    182    || TREE_CODE (NODE) == POSTCONDITION_STMT)
    183 
    184 /* True if NODE is a precondition.  */
    185 #define PRECONDITION_P(NODE)           \
    186   (TREE_CODE (NODE) == PRECONDITION_STMT)
    187 
    188 /* True if NODE is a postcondition.  */
    189 #define POSTCONDITION_P(NODE)          \
    190   (TREE_CODE (NODE) == POSTCONDITION_STMT)
    191 
    192 #define CONTRACT_CHECK(NODE) \
    193   (TREE_CHECK3 (NODE, ASSERTION_STMT, PRECONDITION_STMT, POSTCONDITION_STMT))
    194 
    195 /* True iff the FUNCTION_DECL NODE currently has any contracts.  */
    196 #define DECL_HAS_CONTRACTS_P(NODE) \
    197   (DECL_CONTRACTS (NODE) != NULL_TREE)
    198 
    199 /* For a FUNCTION_DECL of a guarded function, this points to a list of the pre
    200    and post contracts of the first decl of NODE in original order. */
    201 #define DECL_CONTRACTS(NODE) \
    202   (find_contract (DECL_ATTRIBUTES (NODE)))
    203 
    204 /* The next contract (if any) after this one in an attribute list.  */
    205 #define CONTRACT_CHAIN(NODE) \
    206   (find_contract (TREE_CHAIN (NODE)))
    207 
    208 /* The wrapper of the original source location of a list of contracts.  */
    209 #define CONTRACT_SOURCE_LOCATION_WRAPPER(NODE) \
    210   (TREE_PURPOSE (TREE_VALUE (NODE)))
    211 
    212 /* The original source location of a list of contracts.  */
    213 #define CONTRACT_SOURCE_LOCATION(NODE) \
    214   (EXPR_LOCATION (CONTRACT_SOURCE_LOCATION_WRAPPER (NODE)))
    215 
    216 /* The actual code _STMT for a contract attribute.  */
    217 #define CONTRACT_STATEMENT(NODE) \
    218   (TREE_VALUE (TREE_VALUE (NODE)))
    219 
    220 /* True if the contract semantic was specified literally. If true, the
    221    contract mode is an identifier containing the semantic. Otherwise,
    222    it is a TREE_LIST whose TREE_VALUE is the level and whose TREE_PURPOSE
    223    is the role.  */
    224 #define CONTRACT_LITERAL_MODE_P(NODE) \
    225   (CONTRACT_MODE (NODE) != NULL_TREE \
    226    && TREE_CODE (CONTRACT_MODE (NODE)) == IDENTIFIER_NODE)
    227 
    228 /* The identifier denoting the literal semantic of the contract.  */
    229 #define CONTRACT_LITERAL_SEMANTIC(NODE) \
    230   (TREE_OPERAND (NODE, 0))
    231 
    232 /* The written "mode" of the contract. Either an IDENTIFIER with the
    233    literal semantic or a TREE_LIST containing the level and role.  */
    234 #define CONTRACT_MODE(NODE) \
    235   (TREE_OPERAND (CONTRACT_CHECK (NODE), 0))
    236 
    237 /* The identifier denoting the build level of the contract. */
    238 #define CONTRACT_LEVEL(NODE)		\
    239   (TREE_VALUE (CONTRACT_MODE (NODE)))
    240 
    241 /* The identifier denoting the role of the contract */
    242 #define CONTRACT_ROLE(NODE)		\
    243   (TREE_PURPOSE (CONTRACT_MODE (NODE)))
    244 
    245 /* The parsed condition of the contract.  */
    246 #define CONTRACT_CONDITION(NODE) \
    247   (TREE_OPERAND (CONTRACT_CHECK (NODE), 1))
    248 
    249 /* True iff the condition of the contract NODE is not yet parsed.  */
    250 #define CONTRACT_CONDITION_DEFERRED_P(NODE) \
    251   (TREE_CODE (CONTRACT_CONDITION (NODE)) == DEFERRED_PARSE)
    252 
    253 /* The raw comment of the contract.  */
    254 #define CONTRACT_COMMENT(NODE) \
    255   (TREE_OPERAND (CONTRACT_CHECK (NODE), 2))
    256 
    257 /* The VAR_DECL of a postcondition result. For deferred contracts, this
    258    is an IDENTIFIER.  */
    259 #define POSTCONDITION_IDENTIFIER(NODE) \
    260   (TREE_OPERAND (POSTCONDITION_STMT_CHECK (NODE), 3))
    261 
    262 /* For a FUNCTION_DECL of a guarded function, this holds the function decl
    263    where pre contract checks are emitted.  */
    264 #define DECL_PRE_FN(NODE) \
    265   (get_precondition_function ((NODE)))
    266 
    267 /* For a FUNCTION_DECL of a guarded function, this holds the function decl
    268    where post contract checks are emitted.  */
    269 #define DECL_POST_FN(NODE) \
    270   (get_postcondition_function ((NODE)))
    271 
    272 /* True iff the FUNCTION_DECL is the pre function for a guarded function.  */
    273 #define DECL_IS_PRE_FN_P(NODE) \
    274   (DECL_ABSTRACT_ORIGIN (NODE) && DECL_PRE_FN (DECL_ABSTRACT_ORIGIN (NODE)) == NODE)
    275 
    276 /* True iff the FUNCTION_DECL is the post function for a guarded function.  */
    277 #define DECL_IS_POST_FN_P(NODE) \
    278   (DECL_ABSTRACT_ORIGIN (NODE) && DECL_POST_FN (DECL_ABSTRACT_ORIGIN (NODE)) == NODE)
    279 
    280 extern void remove_contract_attributes		(tree);
    281 extern void copy_contract_attributes		(tree, tree);
    282 extern void remap_contracts			(tree, tree, tree, bool);
    283 extern void maybe_update_postconditions		(tree);
    284 extern void rebuild_postconditions		(tree);
    285 extern bool check_postcondition_result		(tree, tree, location_t);
    286 extern tree get_precondition_function		(tree);
    287 extern tree get_postcondition_function		(tree);
    288 extern void duplicate_contracts			(tree, tree);
    289 extern void match_deferred_contracts		(tree);
    290 extern void defer_guarded_contract_match	(tree, tree, tree);
    291 extern bool diagnose_misapplied_contracts	(tree);
    292 extern tree finish_contract_attribute		(tree, tree);
    293 extern tree invalidate_contract			(tree);
    294 extern void update_late_contract		(tree, tree, tree);
    295 extern tree splice_out_contracts		(tree);
    296 extern bool all_attributes_are_contracts_p	(tree);
    297 extern void inherit_base_contracts		(tree, tree);
    298 extern void start_function_contracts		(tree);
    299 extern void maybe_apply_function_contracts	(tree);
    300 extern void finish_function_contracts		(tree);
    301 extern void set_contract_functions		(tree, tree, tree);
    302 extern tree build_contract_check		(tree);
    303 extern void emit_assertion			(tree);
    304 
    305 #endif /* ! GCC_CP_CONTRACT_H */
    306