aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/contracts.h
diff options
context:
space:
mode:
authorJeff Chapman II <jchapman@lock3software.com>2021-06-29 16:52:56 -0400
committerJason Merrill <jason@redhat.com>2022-11-18 21:41:14 -0500
commit2efb237ffc68ec9bb17982434f5941bfa14f8b50 (patch)
tree1c4cc161c09a6cb9a87cd38f752ac9846e86fc54 /gcc/cp/contracts.h
parentea63396f6b08f88f1cde827e6cab94cd488f7fa7 (diff)
downloadgcc-2efb237ffc68ec9bb17982434f5941bfa14f8b50.zip
gcc-2efb237ffc68ec9bb17982434f5941bfa14f8b50.tar.gz
gcc-2efb237ffc68ec9bb17982434f5941bfa14f8b50.tar.bz2
c++: implement P1492 contracts
Implement the P1492 versions of contracts, along with extensions that support the emulation of N4820 and other proposals. This implementation assigns a concrete semantic (one of: ignore, assume, enforce, or observe) to each contract attribute depending on its labels and configuration options. Co-authored-by: Andrew Sutton <asutton@lock3software.com> Co-authored-by: Andrew Marmaduke <amarmaduke@lock3software.com> Co-authored-by: Michael Lopez <mlopez@lock3software.com> Co-authored-by: Jason Merrill <jason@redhat.com> gcc/ChangeLog: * doc/invoke.texi: Document contracts flags. gcc/c-family/ChangeLog: * c.opt: Add contracts flags. * c-cppbuiltin.cc (c_cpp_builtins): Add contracts feature-test macros. gcc/cp/ChangeLog: * cp-tree.h (enum cp_tree_index): Add CPTI_PSEUDO_CONTRACT_VIOLATION. (pseudo_contract_violation_type): New macro. (struct saved_scope): Add x_processing_contract_condition. (processing_contract_condition): New macro. (comparing_override_contracts): New variable decl. (find_contract): New inline. (set_decl_contracts): New inline. (get_contract_semantic): New inline. (set_contract_semantic): New inline. * constexpr.cc (cxx_eval_assert): Split out from... (cxx_eval_internal_function): ...here. (cxx_eval_constant_expression): Use it for contracts. (potential_constant_expression_1): Handle contracts. * cp-gimplify.cc (cp_genericize_r): Handle contracts. * cp-objcp-common.cc (cp_tree_size): Handle contracts. (cp_common_init_ts): Handle contracts. (cp_handle_option): Handle contracts. * decl.cc (duplicate_decls): Handle contracts. (check_tag_decl): Check for bogus contracts. (start_decl): Check flag_contracts. (grokfndecl): Call rebuild_postconditions. (grokdeclarator): Handle contract attributes. (start_preparsed_function): Call start_function_contracts. (finish_function): Call finish_function_contracts. * decl2.cc (cp_check_const_attributes): Skip contracts. (comdat_linkage): Handle outlined contracts. * error.cc (dump_type): Handle null TYPE_IDENTIFIER. * g++spec.cc (EXPERIMENTAL): New macro. (lang_specific_driver): Add -lstdc++exp if -fcontracts. * mangle.cc (write_encoding): Handle outlined contracts. * module.cc (trees_out::fn_parms_init): Handle outlined contracts. (trees_in::fn_parms_init): Likewise. (check_mergeable_decl): Likewise. (module_state_config::get_dialect): Record -fcontracts. * parser.h (struct cp_unparsed_functions_entry): Add contracts. * parser.cc (unparsed_contracts): New macro. (push_unparsed_function_queues): Adjust. (contract_attribute_p): New. (cp_parser_statement): Check contracts. (cp_parser_decl_specifier_seq): Handle contracts. (cp_parser_skip_to_closing_square_bracket): Split out... (cp_parser_skip_up_to_closing_square_bracket): ...this fn. (cp_parser_class_specifier): Do contract late parsing. (cp_parser_class_head): Check contracts. (cp_parser_contract_role): New. (cp_parser_contract_mode_opt): New. (find_error, contains_error_p): New. (cp_parser_contract_attribute_spec): New. (cp_parser_late_contract_condition): New. (cp_parser_std_attribute_spec): Handle contracts. (cp_parser_save_default_args): Also save contracts. * pt.cc (register_parameter_specializations): No longer static. (register_local_identity): New. (check_explicit_specialization): Call remove_contract_attributes. (tsubst_contract, tsubst_contract_attribute): New. (tsubst_contract_attributes): New. (tsubst_attribute): Add comment. (tsubst_copy): Also allow parm when processing_contract_condition. (tsubst_expr): Handle contracts. (regenerate_decl_from_template): Handle contracts. * search.cc (check_final_overrider): Compare contracts. * semantics.cc (set_cleanup_locs): Skip POSTCONDITION_STMT. (finish_non_static_data_member): Check contracts. (finish_this_expr): Check contracts. (process_outer_var_ref): Handle contracts. (finish_id_expression_1): Handle contracts. (apply_deduced_return_type): Adjust contracts. * tree.cc (handle_contract_attribute): New. (get_innermost_component, is_this_expression): New. (comparing_this_references): New. (equivalent_member_references): New. (cp_tree_equal): Check it. * typeck.cc (check_return_expr): Apply contracts. * Make-lang.in: Add contracts.o. * config-lang.in: Add contracts.cc. * cp-tree.def (ASSERTION_STMT, PRECONDITION_STMT) (POSTCONDITION_STMT): New. * contracts.h: New file. * contracts.cc: New file. gcc/testsuite/ChangeLog: * g++.dg/modules/modules.exp: Pass dg-options to link command. * lib/g++.exp: Add -L for libstdc++exp.a. * g++.dg/contracts/backtrace_handler/assert_fail.cpp: New test. * g++.dg/contracts/backtrace_handler/handle_contract_violation.cpp: New test. * g++.dg/contracts/contracts-access1.C: New test. * g++.dg/contracts/contracts-assume1.C: New test. * g++.dg/contracts/contracts-assume2.C: New test. * g++.dg/contracts/contracts-assume3.C: New test. * g++.dg/contracts/contracts-assume4.C: New test. * g++.dg/contracts/contracts-assume5.C: New test. * g++.dg/contracts/contracts-assume6.C: New test. * g++.dg/contracts/contracts-comdat1.C: New test. * g++.dg/contracts/contracts-config1.C: New test. * g++.dg/contracts/contracts-constexpr1.C: New test. * g++.dg/contracts/contracts-constexpr2.C: New test. * g++.dg/contracts/contracts-constexpr3.C: New test. * g++.dg/contracts/contracts-conversion1.C: New test. * g++.dg/contracts/contracts-ctor-dtor1.C: New test. * g++.dg/contracts/contracts-ctor-dtor2.C: New test. * g++.dg/contracts/contracts-cv1.C: New test. * g++.dg/contracts/contracts-deduced1.C: New test. * g++.dg/contracts/contracts-deduced2.C: New test. * g++.dg/contracts/contracts-friend1.C: New test. * g++.dg/contracts/contracts-ft1.C: New test. * g++.dg/contracts/contracts-ignore1.C: New test. * g++.dg/contracts/contracts-ignore2.C: New test. * g++.dg/contracts/contracts-large-return.C: New test. * g++.dg/contracts/contracts-multiline1.C: New test. * g++.dg/contracts/contracts-multiple-inheritance1.C: New test. * g++.dg/contracts/contracts-multiple-inheritance2.C: New test. * g++.dg/contracts/contracts-nested-class1.C: New test. * g++.dg/contracts/contracts-nested-class2.C: New test. * g++.dg/contracts/contracts-nocopy1.C: New test. * g++.dg/contracts/contracts-override.C: New test. * g++.dg/contracts/contracts-post1.C: New test. * g++.dg/contracts/contracts-post2.C: New test. * g++.dg/contracts/contracts-post3.C: New test. * g++.dg/contracts/contracts-post4.C: New test. * g++.dg/contracts/contracts-post5.C: New test. * g++.dg/contracts/contracts-post6.C: New test. * g++.dg/contracts/contracts-pre1.C: New test. * g++.dg/contracts/contracts-pre10.C: New test. * g++.dg/contracts/contracts-pre2.C: New test. * g++.dg/contracts/contracts-pre2a1.C: New test. * g++.dg/contracts/contracts-pre2a2.C: New test. * g++.dg/contracts/contracts-pre3.C: New test. * g++.dg/contracts/contracts-pre4.C: New test. * g++.dg/contracts/contracts-pre5.C: New test. * g++.dg/contracts/contracts-pre6.C: New test. * g++.dg/contracts/contracts-pre7.C: New test. * g++.dg/contracts/contracts-pre9.C: New test. * g++.dg/contracts/contracts-redecl1.C: New test. * g++.dg/contracts/contracts-redecl2.C: New test. * g++.dg/contracts/contracts-redecl3.C: New test. * g++.dg/contracts/contracts-redecl4.C: New test. * g++.dg/contracts/contracts-redecl5.C: New test. * g++.dg/contracts/contracts-redecl6.C: New test. * g++.dg/contracts/contracts-redecl7.C: New test. * g++.dg/contracts/contracts-redecl8.C: New test. * g++.dg/contracts/contracts-tmpl-attr1.C: New test. * g++.dg/contracts/contracts-tmpl-spec1.C: New test. * g++.dg/contracts/contracts-tmpl-spec2.C: New test. * g++.dg/contracts/contracts-tmpl-spec3.C: New test. * g++.dg/contracts/contracts1.C: New test. * g++.dg/contracts/contracts10.C: New test. * g++.dg/contracts/contracts11.C: New test. * g++.dg/contracts/contracts12.C: New test. * g++.dg/contracts/contracts13.C: New test. * g++.dg/contracts/contracts14.C: New test. * g++.dg/contracts/contracts15.C: New test. * g++.dg/contracts/contracts16.C: New test. * g++.dg/contracts/contracts17.C: New test. * g++.dg/contracts/contracts18.C: New test. * g++.dg/contracts/contracts19.C: New test. * g++.dg/contracts/contracts2.C: New test. * g++.dg/contracts/contracts20.C: New test. * g++.dg/contracts/contracts22.C: New test. * g++.dg/contracts/contracts24.C: New test. * g++.dg/contracts/contracts25.C: New test. * g++.dg/contracts/contracts3.C: New test. * g++.dg/contracts/contracts35.C: New test. * g++.dg/contracts/contracts4.C: New test. * g++.dg/contracts/contracts5.C: New test. * g++.dg/contracts/contracts6.C: New test. * g++.dg/contracts/contracts7.C: New test. * g++.dg/contracts/contracts8.C: New test. * g++.dg/contracts/contracts9.C: New test. * g++.dg/modules/contracts-1_a.C: New test. * g++.dg/modules/contracts-1_b.C: New test. * g++.dg/modules/contracts-2_a.C: New test. * g++.dg/modules/contracts-2_b.C: New test. * g++.dg/modules/contracts-2_c.C: New test. * g++.dg/modules/contracts-3_a.C: New test. * g++.dg/modules/contracts-3_b.C: New test. * g++.dg/modules/contracts-4_a.C: New test. * g++.dg/modules/contracts-4_b.C: New test. * g++.dg/modules/contracts-4_c.C: New test. * g++.dg/modules/contracts-4_d.C: New test. * g++.dg/modules/contracts-tpl-friend-1_a.C: New test. * g++.dg/modules/contracts-tpl-friend-1_b.C: New test. * g++.dg/contracts/backtrace_handler/Makefile: New test. * g++.dg/contracts/backtrace_handler/README: New test. * g++.dg/contracts/backtrace_handler/example_out.txt: New test. * g++.dg/contracts/backtrace_handler/example_pretty.txt: New test. * g++.dg/contracts/backtrace_handler/prettytrace.sh: New test. * g++.dg/contracts/except_preload_handler/Makefile: New test. * g++.dg/contracts/except_preload_handler/README: New test. * g++.dg/contracts/except_preload_handler/assert_fail.cpp: New test. * g++.dg/contracts/except_preload_handler/handle_contract_violation.cpp: New test. * g++.dg/contracts/noexcept_preload_handler/Makefile: New test. * g++.dg/contracts/noexcept_preload_handler/README: New test. * g++.dg/contracts/noexcept_preload_handler/assert_fail.cpp: New test. * g++.dg/contracts/noexcept_preload_handler/handle_contract_violation.cpp: New test. * g++.dg/contracts/preload_handler/Makefile: New test. * g++.dg/contracts/preload_handler/README: New test. * g++.dg/contracts/preload_handler/assert_fail.cpp: New test. * g++.dg/contracts/preload_handler/handle_contract_violation.cpp: New test. * g++.dg/contracts/preload_nocontinue_handler/Makefile: New test. * g++.dg/contracts/preload_nocontinue_handler/README: New test. * g++.dg/contracts/preload_nocontinue_handler/assert_fail.cpp: New test. * g++.dg/contracts/preload_nocontinue_handler/handle_contract_violation.cpp: New test. * g++.dg/contracts/preload_nocontinue_handler/nocontinue.cpp: New test.
Diffstat (limited to 'gcc/cp/contracts.h')
-rw-r--r--gcc/cp/contracts.h305
1 files changed, 305 insertions, 0 deletions
diff --git a/gcc/cp/contracts.h b/gcc/cp/contracts.h
new file mode 100644
index 0000000..4050a38
--- /dev/null
+++ b/gcc/cp/contracts.h
@@ -0,0 +1,305 @@
+/* Definitions for C++ contract levels. Implements functionality described in
+ the N4820 working draft version of contracts, P1290, P1332, and P1429.
+ Copyright (C) 2020-2022 Free Software Foundation, Inc.
+ Contributed by Jeff Chapman II (jchapman@lock3software.com)
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_CP_CONTRACT_H
+#define GCC_CP_CONTRACT_H
+
+/* Contract levels approximate the complexity of the expression. */
+
+enum contract_level
+{
+ CONTRACT_INVALID,
+ CONTRACT_DEFAULT,
+ CONTRACT_AUDIT,
+ CONTRACT_AXIOM
+};
+
+/* The concrete semantics determine the behavior of a contract. */
+
+enum contract_semantic
+{
+ CCS_INVALID,
+ CCS_IGNORE,
+ CCS_ASSUME,
+ CCS_NEVER,
+ CCS_MAYBE
+};
+
+/* True if the contract is unchecked. */
+
+inline bool
+unchecked_contract_p (contract_semantic cs)
+{
+ return cs == CCS_IGNORE || cs == CCS_ASSUME;
+}
+
+/* True if the contract is checked. */
+
+inline bool
+checked_contract_p (contract_semantic cs)
+{
+ return cs >= CCS_NEVER;
+}
+
+/* Must match std::contract_violation_continuation_mode in <contract>. */
+enum contract_continuation
+{
+ NEVER_CONTINUE,
+ MAYBE_CONTINUE
+};
+
+/* Assertion role info. */
+struct contract_role
+{
+ const char *name;
+ contract_semantic default_semantic;
+ contract_semantic audit_semantic;
+ contract_semantic axiom_semantic;
+};
+
+/* Information for configured contract semantics. */
+
+struct contract_configuration
+{
+ contract_level level;
+ contract_role* role;
+};
+
+/* A contract mode contains information used to derive the checking
+ and assumption semantics of a contract. This is either a dynamic
+ configuration, meaning it derives from the build mode, or it is
+ explicitly specified. */
+
+struct contract_mode
+{
+ contract_mode () : kind(cm_invalid) {}
+ contract_mode (contract_level level, contract_role *role = NULL)
+ : kind(cm_dynamic)
+ {
+ contract_configuration cc;
+ cc.level = level;
+ cc.role = role;
+ u.config = cc;
+ }
+ contract_mode (contract_semantic semantic) : kind(cm_explicit)
+ {
+ u.semantic = semantic;
+ }
+
+ contract_level get_level () const
+ {
+ gcc_assert (kind == cm_dynamic);
+ return u.config.level;
+ }
+
+ contract_role *get_role () const
+ {
+ gcc_assert (kind == cm_dynamic);
+ return u.config.role;
+ }
+
+ contract_semantic get_semantic () const
+ {
+ gcc_assert (kind == cm_explicit);
+ return u.semantic;
+ }
+
+ enum { cm_invalid, cm_dynamic, cm_explicit } kind;
+
+ union
+ {
+ contract_configuration config;
+ contract_semantic semantic;
+ } u;
+};
+
+extern contract_role *get_contract_role (const char *);
+extern contract_role *add_contract_role (const char *,
+ contract_semantic,
+ contract_semantic,
+ contract_semantic,
+ bool = true);
+extern void validate_contract_role (contract_role *);
+extern void setup_default_contract_role (bool = true);
+extern contract_semantic lookup_concrete_semantic (const char *);
+
+/* Map a source level semantic or level name to its value, or invalid. */
+extern contract_semantic map_contract_semantic (const char *);
+extern contract_level map_contract_level (const char *);
+
+/* Check if an attribute is a cxx contract attribute. */
+extern bool cxx_contract_attribute_p (const_tree);
+extern bool cp_contract_assertion_p (const_tree);
+
+/* Returns the default role. */
+
+inline contract_role *
+get_default_contract_role ()
+{
+ return get_contract_role ("default");
+}
+
+/* Handle various command line arguments related to semantic mapping. */
+extern void handle_OPT_fcontract_build_level_ (const char *);
+extern void handle_OPT_fcontract_assumption_mode_ (const char *);
+extern void handle_OPT_fcontract_continuation_mode_ (const char *);
+extern void handle_OPT_fcontract_role_ (const char *);
+extern void handle_OPT_fcontract_semantic_ (const char *);
+
+enum contract_matching_context
+{
+ cmc_declaration,
+ 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)
+
+/* For a FUNCTION_DECL of a guarded function, this points to a list of the pre
+ and post contracts of the first decl of NODE in original order. */
+#define DECL_CONTRACTS(NODE) \
+ (find_contract (DECL_ATTRIBUTES (NODE)))
+
+/* The next contract (if any) after this one in an attribute list. */
+#define CONTRACT_CHAIN(NODE) \
+ (find_contract (TREE_CHAIN (NODE)))
+
+/* The wrapper of the original source location of a list of contracts. */
+#define CONTRACT_SOURCE_LOCATION_WRAPPER(NODE) \
+ (TREE_PURPOSE (TREE_VALUE (NODE)))
+
+/* The original source location of a list of contracts. */
+#define CONTRACT_SOURCE_LOCATION(NODE) \
+ (EXPR_LOCATION (CONTRACT_SOURCE_LOCATION_WRAPPER (NODE)))
+
+/* The actual code _STMT for a contract attribute. */
+#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) \
+ (get_precondition_function ((NODE)))
+
+/* For a FUNCTION_DECL of a guarded function, this holds the function decl
+ where post contract checks are emitted. */
+#define DECL_POST_FN(NODE) \
+ (get_postcondition_function ((NODE)))
+
+/* True iff the FUNCTION_DECL is the pre function for a guarded function. */
+#define DECL_IS_PRE_FN_P(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_ABSTRACT_ORIGIN (NODE) && DECL_POST_FN (DECL_ABSTRACT_ORIGIN (NODE)) == NODE)
+
+extern void remove_contract_attributes (tree);
+extern void copy_contract_attributes (tree, tree);
+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 void match_deferred_contracts (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 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 build_contract_check (tree);
+extern void emit_assertion (tree);
+
+#endif /* ! GCC_CP_CONTRACT_H */