On 8/30/25 12:45 PM, Iain Sandoe wrote:
A small amount of preparation for upstreaming the C++26 implementation.
We need to add (and share) some APIs and then, at some point, remove the
c++2a edition which was not adopted.  Keeping the related material
together is helpful at this stage.

Tested on x86_64-darwin and powerpc64le-linux, OK for trunk?

OK.

thanks
Iain

--- 8< ---

We have contracts-related declarations and macros split between contracts.h
and cp-tree.h, and then contracts.h is included in the latter, which means
that it is included in all c++ front end files.

This patch:
  - moves all the contracts-related material to contracts.h.
  - makes some functions that are only used in contracts.cc static.
  - tries to group the external API for contracts into related topics.
  - includes contracts.h in the front end sources that need it.

gcc/cp/ChangeLog:

        * constexpr.cc: Include contracts.h
         * coroutines.cc: Likewise.
         * cp-gimplify.cc: Likewise.
         * decl.cc: Likewise.
         * decl2.cc: Likewise.
         * mangle.cc: Likewise.
         * module.cc: Likewise.
         * pt.cc: Likewise.
         * search.cc: Likewise.
         * semantics.cc: Likewise.
        * contracts.cc (validate_contract_role, setup_default_contract_role,
        add_contract_role, get_concrete_axiom_semantic,
        get_default_contract_role): Make static.
         * cp-tree.h (make_postcondition_variable, grok_contract,
        finish_contract_condition, find_contract, set_decl_contracts,
         get_contract_semantic, set_contract_semantic): Move to contracts.h.
        * contracts.h (get_contract_role, add_contract_role,
        validate_contract_role, setup_default_contract_role,
        lookup_concrete_semantic, get_default_contract_role): Remove.

Signed-off-by: Iain Sandoe <[email protected]>
---
  gcc/cp/constexpr.cc   |  1 +
  gcc/cp/contracts.cc   | 22 +++++++---
  gcc/cp/contracts.h    | 98 ++++++++++++++++++++++++++++---------------
  gcc/cp/coroutines.cc  |  1 +
  gcc/cp/cp-gimplify.cc |  1 +
  gcc/cp/cp-tree.h      | 45 --------------------
  gcc/cp/decl.cc        |  1 +
  gcc/cp/decl2.cc       |  1 +
  gcc/cp/mangle.cc      |  1 +
  gcc/cp/module.cc      |  1 +
  gcc/cp/pt.cc          |  1 +
  gcc/cp/search.cc      |  1 +
  gcc/cp/semantics.cc   |  1 +
  13 files changed, 91 insertions(+), 84 deletions(-)

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 701420ca8ec..c3d05248a9a 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -41,6 +41,7 @@ along with GCC; see the file COPYING3.  If not see
  #include "fold-const.h"
  #include "intl.h"
  #include "toplev.h"
+#include "contracts.h"
static bool verify_constant (tree, bool, bool *, bool *);
  #define VERIFY_CONSTANT(X)                                            \
diff --git a/gcc/cp/contracts.cc b/gcc/cp/contracts.cc
index d0cfd2efd55..042524dca38 100644
--- a/gcc/cp/contracts.cc
+++ b/gcc/cp/contracts.cc
@@ -159,7 +159,7 @@ bool valid_configs[CCS_MAYBE + 1][CCS_MAYBE + 1] = {
    { 0, 1, 0, 0, 1, },
  };
-void
+static void
  validate_contract_role (contract_role *role)
  {
    gcc_assert (role);
@@ -171,7 +171,7 @@ validate_contract_role (contract_role *role)
                "the %<default%> semantic");
  }
-contract_semantic
+static contract_semantic
  lookup_concrete_semantic (const char *name)
  {
    if (strcmp (name, "ignore") == 0)
@@ -210,7 +210,9 @@ role_name_equal (contract_role *role, const char *name)
    return role_name_equal (role->name, name);
  }
-contract_role *
+static void setup_default_contract_role (bool update = true);
+
+static contract_role *
  get_contract_role (const char *name)
  {
    for (int i = 0; i < max_custom_roles; ++i)
@@ -227,12 +229,12 @@ get_contract_role (const char *name)
    return NULL;
  }
-contract_role *
+static contract_role *
  add_contract_role (const char *name,
                   contract_semantic des,
                   contract_semantic aus,
                   contract_semantic axs,
-                  bool update)
+                  bool update = true)
  {
    for (int i = 0; i < max_custom_roles; ++i)
      {
@@ -271,7 +273,7 @@ get_concrete_axiom_semantic ()
    return flag_contract_assumption_mode ? CCS_ASSUME : CCS_IGNORE;
  }
-void
+static void
  setup_default_contract_role (bool update)
  {
    contract_semantic check = get_concrete_check ();
@@ -491,6 +493,14 @@ handle_OPT_fcontract_semantic_ (const char *arg)
    validate_contract_role (role);
  }
+/* Returns the default role. */
+
+static contract_role *
+get_default_contract_role ()
+{
+  return get_contract_role ("default");
+}
+
  /* Convert a contract CONFIG into a contract_mode.  */
static contract_mode
diff --git a/gcc/cp/contracts.h b/gcc/cp/contracts.h
index 7d955f7881d..ead07d19fb7 100644
--- a/gcc/cp/contracts.h
+++ b/gcc/cp/contracts.h
@@ -131,38 +131,20 @@ struct contract_mode
    } 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");
-}
+extern bool cxx_contract_attribute_p           (const_tree);
+extern bool cp_contract_assertion_p            (const_tree);
/* Handle various command line arguments related to semantic mapping. */
-extern void handle_OPT_fcontract_build_level_ (const char *);
+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 *);
+extern void handle_OPT_fcontract_role_         (const char *);
+extern void handle_OPT_fcontract_semantic_     (const char *);
enum contract_matching_context
  {
@@ -277,29 +259,79 @@ enum contract_matching_context
  #define DECL_IS_POST_FN_P(NODE) \
    (DECL_ABSTRACT_ORIGIN (NODE) && DECL_POST_FN (DECL_ABSTRACT_ORIGIN (NODE)) 
== NODE)
+/* contracts.cc */
+extern void emit_assertion                     (tree);
+
  extern void remove_contract_attributes                (tree);
+extern bool all_attributes_are_contracts_p     (tree);
+extern tree finish_contract_attribute          (tree, tree);
  extern void copy_contract_attributes          (tree, tree);
+extern bool diagnose_misapplied_contracts      (tree);
  extern void remap_contracts                   (tree, tree, tree, bool);
+extern tree splice_out_contracts               (tree);
+extern void inherit_base_contracts             (tree, tree);
+
+extern tree make_postcondition_variable                (cp_expr);
+extern tree make_postcondition_variable                (cp_expr, tree);
  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 tree grok_contract                      (tree, tree, tree, cp_expr,
+                                                location_t);
+extern tree finish_contract_condition          (cp_expr);
+extern void update_late_contract               (tree, tree, tree);
+extern tree invalidate_contract                        (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 get_precondition_function          (tree);
+extern tree get_postcondition_function         (tree);
  extern void start_function_contracts          (tree);
  extern void maybe_apply_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);
+
+/* Return the first contract in ATTRS, or NULL_TREE if there are none.  */
+
+inline tree
+find_contract (tree attrs)
+{
+  while (attrs && !cxx_contract_attribute_p (attrs))
+    attrs = TREE_CHAIN (attrs);
+  return attrs;
+}
+
+inline void
+set_decl_contracts (tree decl, tree contract_attrs)
+{
+  remove_contract_attributes (decl);
+  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;
+}
+
#endif /* ! GCC_CP_CONTRACT_H */
diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 690e5100707..af1c4bcb9c9 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3.  If not see
  #include "gcc-rich-location.h"
  #include "hash-map.h"
  #include "coroutines.h"
+#include "contracts.h"
/* ================= Debug. ================= */ diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
index 4ff8f36a9fb..39da4ff236a 100644
--- a/gcc/cp/cp-gimplify.cc
+++ b/gcc/cp/cp-gimplify.cc
@@ -43,6 +43,7 @@ along with GCC; see the file COPYING3.  If not see
  #include "omp-general.h"
  #include "opts.h"
  #include "gcc-urlifier.h"
+#include "contracts.h"
/* Keep track of forward references to immediate-escalating functions in
     case they become consteval.  This vector contains ADDR_EXPRs and
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 55e8e073627..8520ca05556 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -25,7 +25,6 @@ along with GCC; see the file COPYING3.  If not see
  #include "hard-reg-set.h"
  #include "function.h"
  #include "tristate.h"
-#include "contracts.h"
/* In order for the format checking to accept the C++ front end
     diagnostic framework extensions, you must include this file before
@@ -9110,50 +9109,6 @@ extern tree coro_get_ramp_function               (tree);
extern tree co_await_get_resume_call (tree await_expr); -
-/* contracts.cc */
-extern tree make_postcondition_variable                (cp_expr);
-extern tree make_postcondition_variable                (cp_expr, tree);
-extern tree grok_contract                      (tree, tree, tree, cp_expr, 
location_t);
-extern tree finish_contract_condition          (cp_expr);
-
-/* Return the first contract in ATTRS, or NULL_TREE if there are none.  */
-
-inline tree
-find_contract (tree attrs)
-{
-  while (attrs && !cxx_contract_attribute_p (attrs))
-    attrs = TREE_CHAIN (attrs);
-  return attrs;
-}
-
-inline void
-set_decl_contracts (tree decl, tree contract_attrs)
-{
-  remove_contract_attributes (decl);
-  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
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 4b1a335910b..f088d09f51e 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -60,6 +60,7 @@ along with GCC; see the file COPYING3.  If not see
  #include "opts.h"
  #include "langhooks-def.h"  /* For lhd_simulate_record_decl  */
  #include "coroutines.h"
+#include "contracts.h"
  #include "gcc-urlifier.h"
  #include "diagnostic-highlight-colors.h"
  #include "pretty-print-markup.h"
diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index c6c9dfc7723..6499be1d33b 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -52,6 +52,7 @@ along with GCC; see the file COPYING3.  If not see
  #include "omp-general.h"
  #include "tree-inline.h"
  #include "escaped_string.h"
+#include "contracts.h"
/* Id for dumping the raw trees. */
  int raw_dump_id;
diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
index f48cb22a3c0..80be40d2dce 100644
--- a/gcc/cp/mangle.cc
+++ b/gcc/cp/mangle.cc
@@ -55,6 +55,7 @@ along with GCC; see the file COPYING3.  If not see
  #include "stor-layout.h"
  #include "flags.h"
  #include "attribs.h"
+#include "contracts.h"
/* Debugging support. */ diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 9412f78ecd9..0404eae6ce3 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -232,6 +232,7 @@ Classes used:
  #include "attribs.h"
  #include "intl.h"
  #include "langhooks.h"
+#include "contracts.h"
  /* This TU doesn't need or want to see the networking.  */
  #define CODY_NETWORKING 0
  #include "mapper-client.h"
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 9b79267d16b..65de1cff0e6 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -49,6 +49,7 @@ along with GCC; see the file COPYING3.  If not see
  #include "builtins.h"
  #include "omp-general.h"
  #include "pretty-print-markup.h"
+#include "contracts.h"
/* The type of functions taking a tree, and some additional data, and
     returning an int.  */
diff --git a/gcc/cp/search.cc b/gcc/cp/search.cc
index cea9f7c689b..77b5b1da527 100644
--- a/gcc/cp/search.cc
+++ b/gcc/cp/search.cc
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3.  If not see
  #include "stringpool.h"
  #include "attribs.h"
  #include "tree-inline.h"
+#include "contracts.h"
static int is_subobject_of_p (tree, tree);
  static tree dfs_lookup_base (tree, void *);
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 58e6f946194..1937ace70b3 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -46,6 +46,7 @@ along with GCC; see the file COPYING3.  If not see
  #include "predict.h"
  #include "memmodel.h"
  #include "gimplify.h"
+#include "contracts.h"
/* There routines provide a modular interface to perform many parsing
     operations.  They may therefore be used during actual parsing, or

Reply via email to