case POSTCONDITION_STMT:
if (!checked_contract_p (get_contract_semantic (t)))
return true;
- if (!RECUR (CONTRACT_CONDITION (t), rval))
- return false;
- return true;
+ return RECUR (CONTRACT_CONDITION (t), rval);
case LABEL_EXPR:
t = LABEL_EXPR_LABEL (t);
For cdtors a post contract is implemented using a CLEANUP_STMT.
- FIXME the compiler already handles sharing cleanup code on multiple exit
- paths properly, so this outlining seems unnecessary if we represent the
- postcondition as a cleanup for all functions.
+ FIXME the compiler already shores cleanup code on multiple exit paths, so
+ this outlining seems unnecessary if we represent the postcondition as a
+ cleanup for all functions.
More helpful for optimization might be to make the contracts a wrapper
function (for non-variadic functions), that could be inlined into a
caller while preserving the call to the actual function? Either that or
- turn a never-continue post contract into an assume in the caller. */
+ mirror a never-continue post contract with an assume in the caller. */
#include "config.h"
#include "system.h"
/* Returns the parameter corresponding to the return value of a guarded
function D. Returns NULL_TREE if D has no postconditions or is void. */
-tree
+static tree
get_postcondition_result_parameter (tree d)
{
if (!d || d == error_mark_node)
This is also used to reuse a parent type's contracts on virtual methods. */
-void
+static void
remap_contract (tree src, tree dst, tree contract, bool duplicate_p)
{
copy_body_data id;
/* Replace all references to dummy this parameters in EXPR with references to
the first argument of the FUNCTION_DECL FN. */
-void
+static void
remap_dummy_this (tree fn, tree *expr)
{
walk_tree (expr, remap_dummy_this_1, fn, NULL);
{
return (flag_contracts
&& !processing_template_decl
- && DECL_ORIGINAL_FN (decl1) == NULL_TREE
+ && DECL_ABSTRACT_ORIGIN (decl1) == NULL_TREE
&& contract_any_active_p (DECL_CONTRACTS (decl1)));
}
return build_contract_condition_function (d, /*pre=*/false);
}
-void
+static void
build_contract_function_decls (tree d)
{
/* Constructors and destructors have their contracts inserted inline. */
set_contract_functions (d, pre, post);
}
-/* Begin a new scope for the postcondition. */
-
-tree
-start_postcondition_statement ()
-{
- tree list = push_stmt_list ();
- tree stmt = begin_compound_stmt (BCS_NORMAL);
- return build_tree_list (list, stmt);
-}
-
-/* Finish the block containing the postcondition check. */
-
-void
-finish_postcondition_statement (tree stmt)
-{
- finish_compound_stmt (TREE_VALUE (stmt));
- pop_stmt_list (TREE_PURPOSE (stmt));
-}
-
static const char *
get_contract_level_name (tree contract)
{
/* Emit statements for precondition attributes. */
-void
+static void
emit_preconditions (tree attr)
{
return emit_contract_conditions (attr, PRECONDITION_STMT);
/* Emit statements for postcondition attributes. */
-void
+static void
emit_postconditions_cleanup (tree contracts)
{
tree stmts = push_stmt_list ();
cmc_override
};
+/* True if NODE is any kind of contract. */
+#define CONTRACT_P(NODE) \
+ (TREE_CODE (NODE) == ASSERTION_STMT \
+ || TREE_CODE (NODE) == PRECONDITION_STMT \
+ || TREE_CODE (NODE) == POSTCONDITION_STMT)
+
+/* True if NODE is a contract condition. */
+#define CONTRACT_CONDITION_P(NODE) \
+ (TREE_CODE (NODE) == PRECONDITION_STMT \
+ || TREE_CODE (NODE) == POSTCONDITION_STMT)
+
+/* True if NODE is a precondition. */
+#define PRECONDITION_P(NODE) \
+ (TREE_CODE (NODE) == PRECONDITION_STMT)
+
+/* True if NODE is a postcondition. */
+#define POSTCONDITION_P(NODE) \
+ (TREE_CODE (NODE) == POSTCONDITION_STMT)
+
+#define CONTRACT_CHECK(NODE) \
+ (TREE_CHECK3 (NODE, ASSERTION_STMT, PRECONDITION_STMT, POSTCONDITION_STMT))
+
/* True iff the FUNCTION_DECL NODE currently has any contracts. */
#define DECL_HAS_CONTRACTS_P(NODE) \
(DECL_CONTRACTS (NODE) != NULL_TREE)
#define CONTRACT_STATEMENT(NODE) \
(TREE_VALUE (TREE_VALUE (NODE)))
+/* True if the contract semantic was specified literally. If true, the
+ contract mode is an identifier containing the semantic. Otherwise,
+ it is a TREE_LIST whose TREE_VALUE is the level and whose TREE_PURPOSE
+ is the role. */
+#define CONTRACT_LITERAL_MODE_P(NODE) \
+ (CONTRACT_MODE (NODE) != NULL_TREE \
+ && TREE_CODE (CONTRACT_MODE (NODE)) == IDENTIFIER_NODE)
+
+/* The identifier denoting the literal semantic of the contract. */
+#define CONTRACT_LITERAL_SEMANTIC(NODE) \
+ (TREE_OPERAND (NODE, 0))
+
+/* The written "mode" of the contract. Either an IDENTIFIER with the
+ literal semantic or a TREE_LIST containing the level and role. */
+#define CONTRACT_MODE(NODE) \
+ (TREE_OPERAND (CONTRACT_CHECK (NODE), 0))
+
+/* The identifier denoting the build level of the contract. */
+#define CONTRACT_LEVEL(NODE) \
+ (TREE_VALUE (CONTRACT_MODE (NODE)))
+
+/* The identifier denoting the role of the contract */
+#define CONTRACT_ROLE(NODE) \
+ (TREE_PURPOSE (CONTRACT_MODE (NODE)))
+
+/* The parsed condition of the contract. */
+#define CONTRACT_CONDITION(NODE) \
+ (TREE_OPERAND (CONTRACT_CHECK (NODE), 1))
+
+/* True iff the condition of the contract NODE is not yet parsed. */
+#define CONTRACT_CONDITION_DEFERRED_P(NODE) \
+ (TREE_CODE (CONTRACT_CONDITION (NODE)) == DEFERRED_PARSE)
+
+/* The raw comment of the contract. */
+#define CONTRACT_COMMENT(NODE) \
+ (TREE_OPERAND (CONTRACT_CHECK (NODE), 2))
+
+/* The VAR_DECL of a postcondition result. For deferred contracts, this
+ is an IDENTIFIER. */
+#define POSTCONDITION_IDENTIFIER(NODE) \
+ (TREE_OPERAND (POSTCONDITION_STMT_CHECK (NODE), 3))
+
/* For a FUNCTION_DECL of a guarded function, this holds the function decl
where pre contract checks are emitted. */
#define DECL_PRE_FN(NODE) \
#define DECL_POST_FN(NODE) \
(get_postcondition_function ((NODE)))
-/* For a FUNCTION_DECL of a pre/post function, this points back to the
- original guarded function. */
-#define DECL_ORIGINAL_FN(NODE) \
- (DECL_ABSTRACT_ORIGIN (NODE))
-
/* True iff the FUNCTION_DECL is the pre function for a guarded function. */
#define DECL_IS_PRE_FN_P(NODE) \
- (DECL_ORIGINAL_FN (NODE) && DECL_PRE_FN (DECL_ORIGINAL_FN (NODE)) == NODE)
+ (DECL_ABSTRACT_ORIGIN (NODE) && DECL_PRE_FN (DECL_ABSTRACT_ORIGIN (NODE)) == NODE)
/* True iff the FUNCTION_DECL is the post function for a guarded function. */
#define DECL_IS_POST_FN_P(NODE) \
- (DECL_ORIGINAL_FN (NODE) && DECL_POST_FN (DECL_ORIGINAL_FN (NODE)) == NODE)
+ (DECL_ABSTRACT_ORIGIN (NODE) && DECL_POST_FN (DECL_ABSTRACT_ORIGIN (NODE)) == NODE)
-extern tree invalidate_contract (tree);
-extern tree finish_contract_attribute (tree, tree);
-extern void update_late_contract (tree, tree, tree);
extern void remove_contract_attributes (tree);
extern void copy_contract_attributes (tree, tree);
-extern tree splice_out_contracts (tree);
-extern bool check_postcondition_result (tree, tree, location_t);
+extern void remap_contracts (tree, tree, tree, bool);
+extern void maybe_update_postconditions (tree);
extern void rebuild_postconditions (tree);
+extern bool check_postcondition_result (tree, tree, location_t);
+extern tree get_precondition_function (tree);
+extern tree get_postcondition_function (tree);
+extern void duplicate_contracts (tree, tree);
extern bool match_contract_conditions (location_t, tree, location_t, tree, contract_matching_context);
-extern void defer_guarded_contract_match (tree, tree, tree);
extern void match_deferred_contracts (tree);
-extern void remap_contract (tree, tree, tree, bool);
-extern void remap_contracts (tree, tree, tree, bool);
-extern void remap_dummy_this (tree, tree *);
-extern bool contract_active_p (tree);
-extern bool contract_any_active_p (tree);
-extern bool contract_any_deferred_p (tree);
+extern void defer_guarded_contract_match (tree, tree, tree);
+extern bool diagnose_misapplied_contracts (tree);
+extern tree finish_contract_attribute (tree, tree);
+extern tree invalidate_contract (tree);
+extern void update_late_contract (tree, tree, tree);
+extern tree splice_out_contracts (tree);
extern bool all_attributes_are_contracts_p (tree);
-extern void build_contract_function_decls (tree);
+extern void inherit_base_contracts (tree, tree);
+extern tree apply_postcondition_to_return (tree);
+extern void start_function_contracts (tree);
+extern void finish_function_contracts (tree);
extern void set_contract_functions (tree, tree, tree);
-extern tree start_postcondition_statement ();
-extern void finish_postcondition_statement (tree);
extern tree build_contract_check (tree);
-extern tree get_postcondition_result_parameter (tree);
-extern tree get_precondition_function (tree);
-extern tree get_postcondition_function (tree);
-extern tree get_contracts_original_fn (tree);
extern void emit_assertion (tree);
-extern void emit_preconditions (tree);
-extern void emit_postconditions_cleanup (tree);
-extern void maybe_update_postconditions (tree);
-extern void start_function_contracts (tree);
-extern void finish_function_contracts (tree);
-extern tree apply_postcondition_to_return (tree);
-extern void duplicate_contracts (tree, tree);
-extern void inherit_base_contracts (tree, tree);
#endif /* ! GCC_CP_CONTRACT_H */
location_t location;
};
-/* True if NODE is any kind of contract. */
-#define CONTRACT_P(NODE) \
- (TREE_CODE (NODE) == ASSERTION_STMT \
- || TREE_CODE (NODE) == PRECONDITION_STMT \
- || TREE_CODE (NODE) == POSTCONDITION_STMT)
-
-/* True if NODE is a contract condition. */
-#define CONTRACT_CONDITION_P(NODE) \
- (TREE_CODE (NODE) == PRECONDITION_STMT \
- || TREE_CODE (NODE) == POSTCONDITION_STMT)
-
-/* True if NODE is a precondition. */
-#define PRECONDITION_P(NODE) \
- (TREE_CODE (NODE) == PRECONDITION_STMT)
-
-/* True if NODE is a postcondition. */
-#define POSTCONDITION_P(NODE) \
- (TREE_CODE (NODE) == POSTCONDITION_STMT)
-
-#define CONTRACT_CHECK(NODE) \
- (TREE_CHECK3 (NODE, ASSERTION_STMT, PRECONDITION_STMT, POSTCONDITION_STMT))
-
-/* Returns the computed semantic of the node. */
-
-inline contract_semantic
-get_contract_semantic (const_tree t)
-{
- return (contract_semantic) (TREE_LANG_FLAG_3 (CONTRACT_CHECK (t))
- | (TREE_LANG_FLAG_2 (t) << 1)
- | (TREE_LANG_FLAG_0 ((t)) << 2));
-}
-
-/* Sets the computed semantic of the node. */
-
-inline void
-set_contract_semantic (tree t, contract_semantic semantic)
-{
- TREE_LANG_FLAG_3 (CONTRACT_CHECK (t)) = semantic & 0x01;
- TREE_LANG_FLAG_2 (t) = (semantic & 0x02) >> 1;
- TREE_LANG_FLAG_0 (t) = (semantic & 0x04) >> 2;
-}
-
-/* True if the contract semantic was specified literally. If true, the
- contract mode is an identifier containing the semantic. Otherwise,
- it is a TREE_LIST whose TREE_VALUE is the level and whose TREE_PURPOSE
- is the role. */
-#define CONTRACT_LITERAL_MODE_P(NODE) \
- (CONTRACT_MODE (NODE) != NULL_TREE \
- && TREE_CODE (CONTRACT_MODE (NODE)) == IDENTIFIER_NODE)
-
-/* The identifier denoting the literal semantic of the contract. */
-#define CONTRACT_LITERAL_SEMANTIC(NODE) \
- (TREE_OPERAND (NODE, 0))
-
-/* The written "mode" of the contract. Either an IDENTIFIER with the
- literal semantic or a TREE_LIST containing the level and role. */
-#define CONTRACT_MODE(NODE) \
- (TREE_OPERAND (CONTRACT_CHECK (NODE), 0))
-
-/* The identifier denoting the build level of the contract. */
-#define CONTRACT_LEVEL(NODE) \
- (TREE_VALUE (CONTRACT_MODE (NODE)))
-
-/* The identifier denoting the role of the contract */
-#define CONTRACT_ROLE(NODE) \
- (TREE_PURPOSE (CONTRACT_MODE (NODE)))
-
-/* The parsed condition of the contract. */
-#define CONTRACT_CONDITION(NODE) \
- (TREE_OPERAND (CONTRACT_CHECK (NODE), 1))
-
-/* True iff the condition of the contract NODE is not yet parsed. */
-#define CONTRACT_CONDITION_DEFERRED_P(NODE) \
- (TREE_CODE (CONTRACT_CONDITION (NODE)) == DEFERRED_PARSE)
-
-/* The raw comment of the contract. */
-#define CONTRACT_COMMENT(NODE) \
- (TREE_OPERAND (CONTRACT_CHECK (NODE), 2))
-
-/* The VAR_DECL of a postcondition result. For deferred contracts, this
- is an IDENTIFIER. */
-#define POSTCONDITION_IDENTIFIER(NODE) \
- (TREE_OPERAND (POSTCONDITION_STMT_CHECK (NODE), 3))
-
struct GTY (()) tree_argument_pack_select {
struct tree_common common;
tree argument_pack;
extern tree push_throw_library_fn (tree, tree);
extern void warn_misplaced_attr_for_class_type (location_t location,
tree class_type);
-extern bool diagnose_misapplied_contracts (tree);
extern tree check_tag_decl (cp_decl_specifier_seq *, bool);
extern tree shadow_tag (cp_decl_specifier_seq *);
extern tree groktypename (cp_decl_specifier_seq *, const cp_declarator *, bool);
DECL_ATTRIBUTES (decl) = chainon (DECL_ATTRIBUTES (decl), contract_attrs);
}
+/* Returns the computed semantic of the node. */
+
+inline contract_semantic
+get_contract_semantic (const_tree t)
+{
+ return (contract_semantic) (TREE_LANG_FLAG_3 (CONTRACT_CHECK (t))
+ | (TREE_LANG_FLAG_2 (t) << 1)
+ | (TREE_LANG_FLAG_0 ((t)) << 2));
+}
+
+/* Sets the computed semantic of the node. */
+
+inline void
+set_contract_semantic (tree t, contract_semantic semantic)
+{
+ TREE_LANG_FLAG_3 (CONTRACT_CHECK (t)) = semantic & 0x01;
+ TREE_LANG_FLAG_2 (t) = (semantic & 0x02) >> 1;
+ TREE_LANG_FLAG_0 (t) = (semantic & 0x04) >> 2;
+}
+
/* Inline bodies. */
inline tree
returned_attrs = attr_chainon (returned_attrs, att);
}
- /* Contract attributes appertain to the declaration. */
+ /* Actually apply the contract attributes to the declaration. */
for (tree *p = &attrs; *p;)
{
tree l = *p;
if (cxx_contract_attribute_p (l))
{
*p = TREE_CHAIN (l);
- /* Intentially reverse order of contracts so they're
+ /* Intentionally reverse order of contracts so they're
reversed back into their lexical order. */
TREE_CHAIN (l) = NULL_TREE;
returned_attrs = chainon (l, returned_attrs);
return fndecl;
}
-
\f
/* Create the FUNCTION_DECL for a function definition.
DECLSPECS and DECLARATOR are the parts of the declaration;
&& (!DECL_IS_UNDECLARED_BUILTIN (m_inner)
|| !DECL_EXTERN_C_P (m_inner)
|| DECL_EXTERN_C_P (d_inner))
- /* Reject if one is they're different member of a
+ /* Reject if one is a different member of a
guarded/pre/post fn set. */
&& (!flag_contracts
|| (DECL_IS_PRE_FN_P (d_inner)
/* TRUE if the decl-specifier-seq preceding a declarator includes
the 'friend' specifier. This prevents attributes on friend function
declarations from being parsed in the complete class context. */
- /* ??? Maybe use defer_guarded_contract_match instead? */
+ /* ??? But they should be; maybe use defer_guarded_contract_match? */
bool declaring_friend_p;
/* TRUE if we are presently parsing a template-argument-list. */