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@lock3software.com)
6 This file is part of GCC.
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)
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.
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/>. */
22 #ifndef GCC_CP_CONTRACT_H
23 #define GCC_CP_CONTRACT_H
25 /* Contract levels approximate the complexity of the expression. */
35 /* The concrete semantics determine the behavior of a contract. */
37 enum contract_semantic
46 /* True if the contract is unchecked. */
49 unchecked_contract_p (contract_semantic cs
)
51 return cs
== CCS_IGNORE
|| cs
== CCS_ASSUME
;
54 /* True if the contract is checked. */
57 checked_contract_p (contract_semantic cs
)
59 return cs
>= CCS_NEVER
;
62 /* Must match std::contract_violation_continuation_mode in <contract>. */
63 enum contract_continuation
69 /* Assertion role info. */
73 contract_semantic default_semantic
;
74 contract_semantic audit_semantic
;
75 contract_semantic axiom_semantic
;
78 /* Information for configured contract semantics. */
80 struct contract_configuration
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. */
93 contract_mode () : kind(cm_invalid
) {}
94 contract_mode (contract_level level
, contract_role
*role
= NULL
)
97 contract_configuration cc
;
102 contract_mode (contract_semantic semantic
) : kind(cm_explicit
)
104 u
.semantic
= semantic
;
107 contract_level
get_level () const
109 gcc_assert (kind
== cm_dynamic
);
110 return u
.config
.level
;
113 contract_role
*get_role () const
115 gcc_assert (kind
== cm_dynamic
);
116 return u
.config
.role
;
119 contract_semantic
get_semantic () const
121 gcc_assert (kind
== cm_explicit
);
125 enum { cm_invalid
, cm_dynamic
, cm_explicit
} kind
;
129 contract_configuration config
;
130 contract_semantic semantic
;
134 extern contract_role
*get_contract_role (const char *);
135 extern contract_role
*add_contract_role (const char *,
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 *);
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 *);
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
);
152 /* Returns the default role. */
154 inline contract_role
*
155 get_default_contract_role ()
157 return get_contract_role ("default");
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 *);
167 enum contract_matching_context
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)
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)
184 /* True if NODE is a precondition. */
185 #define PRECONDITION_P(NODE) \
186 (TREE_CODE (NODE) == PRECONDITION_STMT)
188 /* True if NODE is a postcondition. */
189 #define POSTCONDITION_P(NODE) \
190 (TREE_CODE (NODE) == POSTCONDITION_STMT)
192 #define CONTRACT_CHECK(NODE) \
193 (TREE_CHECK3 (NODE, ASSERTION_STMT, PRECONDITION_STMT, POSTCONDITION_STMT))
195 /* True iff the FUNCTION_DECL NODE currently has any contracts. */
196 #define DECL_HAS_CONTRACTS_P(NODE) \
197 (DECL_CONTRACTS (NODE) != NULL_TREE)
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)))
204 /* The next contract (if any) after this one in an attribute list. */
205 #define CONTRACT_CHAIN(NODE) \
206 (find_contract (TREE_CHAIN (NODE)))
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)))
212 /* The original source location of a list of contracts. */
213 #define CONTRACT_SOURCE_LOCATION(NODE) \
214 (EXPR_LOCATION (CONTRACT_SOURCE_LOCATION_WRAPPER (NODE)))
216 /* The actual code _STMT for a contract attribute. */
217 #define CONTRACT_STATEMENT(NODE) \
218 (TREE_VALUE (TREE_VALUE (NODE)))
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
224 #define CONTRACT_LITERAL_MODE_P(NODE) \
225 (CONTRACT_MODE (NODE) != NULL_TREE \
226 && TREE_CODE (CONTRACT_MODE (NODE)) == IDENTIFIER_NODE)
228 /* The identifier denoting the literal semantic of the contract. */
229 #define CONTRACT_LITERAL_SEMANTIC(NODE) \
230 (TREE_OPERAND (NODE, 0))
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))
237 /* The identifier denoting the build level of the contract. */
238 #define CONTRACT_LEVEL(NODE) \
239 (TREE_VALUE (CONTRACT_MODE (NODE)))
241 /* The identifier denoting the role of the contract */
242 #define CONTRACT_ROLE(NODE) \
243 (TREE_PURPOSE (CONTRACT_MODE (NODE)))
245 /* The parsed condition of the contract. */
246 #define CONTRACT_CONDITION(NODE) \
247 (TREE_OPERAND (CONTRACT_CHECK (NODE), 1))
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)
253 /* The raw comment of the contract. */
254 #define CONTRACT_COMMENT(NODE) \
255 (TREE_OPERAND (CONTRACT_CHECK (NODE), 2))
257 /* The VAR_DECL of a postcondition result. For deferred contracts, this
259 #define POSTCONDITION_IDENTIFIER(NODE) \
260 (TREE_OPERAND (POSTCONDITION_STMT_CHECK (NODE), 3))
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)))
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)))
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)
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)
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 tree
apply_postcondition_to_return (tree
);
299 extern void start_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
);
305 #endif /* ! GCC_CP_CONTRACT_H */