return fn;
}
+/* Return true if CONTRACT is checked or assumed under the current build
+ configuration. */
+
+bool
+contract_active_p (tree contract)
+{
+ return get_contract_semantic (contract) != CCS_IGNORE;
+}
+
static bool
has_active_contract_condition (tree d, tree_code c)
{
return has_active_contract_condition (d, POSTCONDITION_STMT);
}
+/* Return true if any contract in the CONTRACT list is checked or assumed
+ under the current build configuration. */
+
+bool
+contract_any_active_p (tree contract)
+{
+ for (; contract != NULL_TREE; contract = CONTRACT_CHAIN (contract))
+ if (contract_active_p (TREE_VALUE (TREE_VALUE (contract))))
+ return true;
+ return false;
+}
+
+/* Do we need to mess with contracts for DECL1? */
+
+static bool
+handle_contracts_p (tree decl1)
+{
+ return (flag_contracts
+ && !processing_template_decl
+ && DECL_ORIGINAL_FN (decl1) == NULL_TREE
+ && contract_any_active_p (DECL_CONTRACTS (decl1)));
+}
+
+/* Should we break out DECL1's pre/post contracts into separate functions?
+ FIXME I'd like this to default to 0, but that will need an overhaul to the
+ return identifier handling to just refor to the RESULT_DECL. */
+
+static bool
+outline_contracts_p (tree decl1)
+{
+ return (!DECL_CONSTRUCTOR_P (decl1)
+ && !DECL_DESTRUCTOR_P (decl1));
+}
+
/* Build the precondition checking function for D. */
static tree
build_contract_function_decls (tree d)
{
/* Constructors and destructors have their contracts inserted inline. */
- if (DECL_CONSTRUCTOR_P (d) || DECL_DESTRUCTOR_P (d))
+ if (!outline_contracts_p (d))
return;
/* Build the pre/post functions (or not). */
build_contract_violation (tree contract, contract_continuation cmode)
{
expanded_location loc = expand_location (EXPR_LOCATION (contract));
- const char *function =
- TREE_CODE (contract) == ASSERTION_STMT
- || DECL_CONSTRUCTOR_P (current_function_decl)
- || DECL_DESTRUCTOR_P (current_function_decl)
- ? current_function_name ()
- : fndecl_name (DECL_ORIGINAL_FN (current_function_decl));
+ const char *function = fndecl_name (DECL_ORIGIN (current_function_decl));
const char *level = get_contract_level_name (contract);
const char *role = get_contract_role_name (contract);
finish_expr_stmt (call);
}
-/* Return true if CONTRACT is checked or assumed under the current build
- configuration. */
-
-bool
-contract_active_p (tree contract)
-{
- return get_contract_semantic (contract) != CCS_IGNORE;
-}
-
-/* Return true if any contract in the CONTRACT list is checked or assumed
- under the current build configuration. */
-
-bool
-contract_any_active_p (tree contract)
-{
- for (; contract != NULL_TREE; contract = CONTRACT_CHAIN (contract))
- if (contract_active_p (TREE_VALUE (TREE_VALUE (contract))))
- return true;
- return false;
-}
-
/* Generate the code that checks or assumes a contract, but do not attach
it to the current context. This is called during genericization. */
void
start_function_contracts (tree decl1)
{
- bool starting_guarded_p = !processing_template_decl
- && DECL_ORIGINAL_FN (decl1) == NULL_TREE
- && contract_any_active_p (DECL_CONTRACTS (decl1))
- && !DECL_CONSTRUCTOR_P (decl1)
- && !DECL_DESTRUCTOR_P (decl1);
-
- if (!starting_guarded_p)
+ if (!handle_contracts_p (decl1))
return;
+ if (!outline_contracts_p (decl1))
+ {
+ emit_preconditions (DECL_CONTRACTS (current_function_decl));
+ emit_postconditions_cleanup (DECL_CONTRACTS (current_function_decl));
+ return;
+ }
+
/* Contracts may have just been added without a chance to parse them, though
we still need the PRE_FN available to generate a call to it. */
if (!DECL_PRE_FN (decl1))
void
finish_function_contracts (tree fndecl)
{
- bool finishing_guarded_p = !processing_template_decl
- && DECL_ORIGINAL_FN (fndecl) == NULL_TREE
- && contract_any_active_p (DECL_CONTRACTS (fndecl))
- && !DECL_CONSTRUCTOR_P (fndecl)
- && !DECL_DESTRUCTOR_P (fndecl);
-
- if (!finishing_guarded_p)
+ if (!handle_contracts_p (fndecl)
+ || !outline_contracts_p (fndecl))
return;
for (tree ca = DECL_CONTRACTS (fndecl); ca; ca = CONTRACT_CHAIN (ca))