@@ -2651,26 +2651,6 @@ emit_contract_attr (tree attr)
2651
2651
emit_contract_statement (CONTRACT_STATEMENT (attr));
2652
2652
}
2653
2653
2654
- /* Add the statements of contract attributes ATTRS of the type specified
2655
- with CODE to the current block. */
2656
-
2657
- static void
2658
- emit_contract_conditions (tree attrs, tree_code code)
2659
- {
2660
- if (!attrs) return ;
2661
- gcc_checking_assert (TREE_CODE (attrs) == TREE_LIST);
2662
- gcc_checking_assert (code == PRECONDITION_STMT
2663
- || code == POSTCONDITION_STMT);
2664
- for (attrs = find_contract (attrs); attrs;
2665
- attrs = CONTRACT_CHAIN (attrs))
2666
- {
2667
- tree contract = CONTRACT_STATEMENT (attrs);
2668
- if (TREE_CODE (contract) != code)
2669
- continue ;
2670
- emit_contract_attr (attrs);
2671
- }
2672
- }
2673
-
2674
2654
/* Emit the statement for an assertion attribute. */
2675
2655
2676
2656
void
@@ -2691,22 +2671,6 @@ emit_assertion (tree attr)
2691
2671
}
2692
2672
}
2693
2673
2694
- /* Emit statements for precondition attributes. */
2695
-
2696
- static void
2697
- emit_preconditions (tree attr)
2698
- {
2699
- return emit_contract_conditions (attr, PRECONDITION_STMT);
2700
- }
2701
-
2702
- /* Emit statements for postcondition attributes. */
2703
-
2704
- static void
2705
- emit_postconditions (tree attr)
2706
- {
2707
- return emit_contract_conditions (attr, POSTCONDITION_STMT);
2708
- }
2709
-
2710
2674
/* We're compiling the pre/postcondition function CONDFN; remap any FN
2711
2675
attributes that match CODE and emit them. */
2712
2676
@@ -3010,6 +2974,72 @@ add_post_condition_fn_call (tree fndecl)
3010
2974
finish_expr_stmt (call);
3011
2975
}
3012
2976
2977
+ /* Returns a copy of FNDECL contracts. This is used when emiting a contract.
2978
+ If we were to emit the original contract tree, any folding of the contract
2979
+ condition would affect the original contract too. The original contract
2980
+ tree needs to be preserved in case it is used to apply to a different
2981
+ function (for inheritance or wrapping reasons). */
2982
+
2983
+ tree
2984
+ copy_contracts (tree fndecl, contract_match_kind remap_kind = cmk_all )
2985
+ {
2986
+ tree last = NULL_TREE, contract_attrs = NULL_TREE;
2987
+ for (tree a = DECL_CONTRACTS (fndecl);
2988
+ a != NULL_TREE;
2989
+ a = CONTRACT_CHAIN (a))
2990
+ {
2991
+ if ((remap_kind == cmk_pre
2992
+ && (TREE_CODE (CONTRACT_STATEMENT (a)) == POSTCONDITION_STMT))
2993
+ || (remap_kind == cmk_post
2994
+ && (TREE_CODE (CONTRACT_STATEMENT (a)) == PRECONDITION_STMT)))
2995
+ continue ;
2996
+
2997
+ tree c = copy_node (a);
2998
+ TREE_VALUE (c) = build_tree_list (TREE_PURPOSE (TREE_VALUE (c)),
2999
+ copy_node (CONTRACT_STATEMENT (c)));
3000
+
3001
+ copy_body_data id;
3002
+ hash_map<tree, tree> decl_map;
3003
+
3004
+ memset (&id, 0 , sizeof (id));
3005
+
3006
+ id.src_fn = fndecl;
3007
+ id.dst_fn = fndecl;
3008
+ id.src_cfun = DECL_STRUCT_FUNCTION (fndecl);
3009
+ id.decl_map = &decl_map;
3010
+
3011
+ id.copy_decl = retain_decl;
3012
+
3013
+ id.transform_call_graph_edges = CB_CGE_DUPLICATE;
3014
+ id.transform_new_cfg = false ;
3015
+ id.transform_return_to_modify = false ;
3016
+ id.transform_parameter = true ;
3017
+
3018
+ /* Make sure not to unshare trees behind the front-end's back
3019
+ since front-end specific mechanisms may rely on sharing. */
3020
+ id.regimplify = false ;
3021
+ id.do_not_unshare = true ;
3022
+ id.do_not_fold = true ;
3023
+
3024
+ /* We're not inside any EH region. */
3025
+ id.eh_lp_nr = 0 ;
3026
+ walk_tree (&CONTRACT_CONDITION (CONTRACT_STATEMENT (c)),
3027
+ copy_tree_body_r, &id, NULL );
3028
+
3029
+
3030
+ CONTRACT_COMMENT (CONTRACT_STATEMENT (c))
3031
+ = copy_node (CONTRACT_COMMENT (CONTRACT_STATEMENT (c)));
3032
+
3033
+ chainon (last, c);
3034
+ last = c;
3035
+ if (!contract_attrs)
3036
+ contract_attrs = c;
3037
+ }
3038
+
3039
+ return contract_attrs;
3040
+ }
3041
+
3042
+
3013
3043
/* Add a call or a direct evaluation of the pre checks. */
3014
3044
3015
3045
static void
@@ -3018,7 +3048,11 @@ apply_preconditions (tree fndecl)
3018
3048
if (outline_contracts_p (fndecl))
3019
3049
add_pre_condition_fn_call (fndecl);
3020
3050
else
3021
- emit_preconditions (DECL_CONTRACTS (fndecl));
3051
+ {
3052
+ tree contract_copy = copy_contracts (fndecl, cmk_pre);
3053
+ for (; contract_copy; contract_copy = CONTRACT_CHAIN (contract_copy))
3054
+ emit_contract_attr (contract_copy);
3055
+ }
3022
3056
}
3023
3057
3024
3058
/* Add a call or a direct evaluation of the post checks. */
@@ -3029,7 +3063,11 @@ apply_postconditions (tree fndecl)
3029
3063
if (outline_contracts_p (fndecl))
3030
3064
add_post_condition_fn_call (fndecl);
3031
3065
else
3032
- emit_postconditions (DECL_CONTRACTS (fndecl));
3066
+ {
3067
+ tree contract_copy = copy_contracts (fndecl, cmk_post);
3068
+ for (; contract_copy; contract_copy = CONTRACT_CHAIN (contract_copy))
3069
+ emit_contract_attr (contract_copy);
3070
+ }
3033
3071
}
3034
3072
3035
3073
/* Add contract handling to the function in FNDECL.
0 commit comments