]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: move duplicate_contracts to contracts.cc
authorJason Merrill <jason@redhat.com>
Fri, 28 Oct 2022 15:37:23 +0000 (11:37 -0400)
committerJason Merrill <jason@redhat.com>
Fri, 28 Oct 2022 20:36:10 +0000 (16:36 -0400)
gcc/cp/ChangeLog:

* cp-tree.h (duplicate_contracts): Add prototype.
* contracts.cc (duplicate_contracts): Move from...
* decl.cc (duplicate_contracts): ...here.
* parser.cc (cp_parser_contract_attribute_spec): Fix typo.

gcc/cp/contracts.cc
gcc/cp/cp-tree.h
gcc/cp/decl.cc
gcc/cp/parser.cc

index 214be7c671f11a3028c3613e4aecbf42c61faf1b..272448d07d83c1983ad3a5aa36d34054c5b7b997 100644 (file)
@@ -2087,4 +2087,105 @@ apply_postcondition_to_return (tree expr)
   return call;
 }
 
+/* A subroutine of duplicate_decls. Diagnose issues in the redeclaration of
+   guarded functions.  Note that attributes on new friend declarations have not
+   been processed yet, so we take those from the global above.  */
+
+void
+duplicate_contracts (tree newdecl, tree olddecl)
+{
+  /* Compare contracts to see if they match.    */
+  tree old_contracts = DECL_CONTRACTS (olddecl);
+  tree new_contracts = DECL_CONTRACTS (newdecl);
+
+  if (!old_contracts && !new_contracts)
+    return;
+
+  location_t old_loc = DECL_SOURCE_LOCATION (olddecl);
+  location_t new_loc = DECL_SOURCE_LOCATION (newdecl);
+
+  /* If both declarations specify contracts, ensure they match.
+
+     TODO: This handles a potential error a little oddly. Consider:
+
+       struct B {
+         virtual void f(int n) [[pre: n == 0]];
+       };
+       struct D : B {
+         void f(int n) override; // inherits contracts
+       };
+       void D::f(int n) [[pre: n == 0]] // OK
+       { }
+
+    It's okay because we're explicitly restating the inherited contract.
+    Changing the precondition on the definition D::f causes match_contracts
+    to complain about the mismatch.
+
+    This would previously have been diagnosed as adding contracts to an
+    override, but this seems like it should be well-formed.  */
+  if (old_contracts && new_contracts)
+    {
+      if (!match_contract_conditions (old_loc, old_contracts,
+                                     new_loc, new_contracts,
+                                     cmc_declaration))
+       return;
+    }
+
+  /* Handle cases where contracts are omitted in one or the other
+     declaration.  */
+  if (old_contracts)
+    {
+      /* Contracts have been previously specified by are no omitted. The
+        new declaration inherits the existing contracts. */
+      if (!new_contracts)
+       copy_contract_attributes (newdecl, olddecl);
+
+      /* In all cases, remove existing contracts from OLDDECL to prevent the
+        attribute merging function from adding excess contracts.  */
+      remove_contract_attributes (olddecl);
+    }
+  else if (!old_contracts)
+    {
+      /* We are adding contracts to a declaration.  */
+      if (new_contracts)
+       {
+         /* We can't add to a previously defined function.  */
+         if (DECL_INITIAL (olddecl))
+           {
+             auto_diagnostic_group d;
+             error_at (new_loc, "cannot add contracts after definition");
+             inform (DECL_SOURCE_LOCATION (olddecl), "original definition here");
+             return;
+           }
+
+         /* We can't add to an unguarded virtual function declaration.  */
+         if (DECL_VIRTUAL_P (olddecl) && new_contracts)
+           {
+             auto_diagnostic_group d;
+             error_at (new_loc, "cannot add contracts to a virtual function");
+             inform (DECL_SOURCE_LOCATION (olddecl), "original declaration here");
+             return;
+           }
+
+         /* Depending on the "first declaration" rule, we may not be able
+            to add contracts to a function after the fact.  */
+         if (flag_contract_strict_declarations)
+           {
+             warning_at (new_loc,
+                         OPT_fcontract_strict_declarations_,
+                         "declaration adds contracts to %q#D",
+                         olddecl);
+             return;
+           }
+
+         /* Copy the contracts from NEWDECL to OLDDECL. We shouldn't need to
+            remap them because NEWDECL's parameters will replace those of
+            OLDDECL.  Remove the contracts from NEWDECL so they aren't
+            cloned when merging.  */
+         copy_contract_attributes (olddecl, newdecl);
+         remove_contract_attributes (newdecl);
+       }
+    }
+}
+
 #include "gt-cp-contracts.h"
index 11ac082c89f44ad4a08ba29974404f5eaad51cdf..a212aa2659d457eeeb25dfe339d1bab19b69ce8b 100644 (file)
@@ -7788,6 +7788,7 @@ 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);
 
 inline void
 set_decl_contracts (tree decl, tree contract_attrs)
index 9740129456b0d4753ba59465bb68098ec7a8b130..d6eb50a260bb2fadbf32c6cd27d800088184a3fa 100644 (file)
@@ -1475,107 +1475,6 @@ duplicate_function_template_decls (tree newdecl, tree olddecl)
   return false;
 }
 
-/* A subroutine of duplicate_decls. Diagnose issues in the redeclaration of
-   guarded functions.  Note that attributes on new friend declarations have not
-   been processed yet, so we take those from the global above.  */
-
-static void
-duplicate_contracts (tree newdecl, tree olddecl)
-{
-  /* Compare contracts to see if they match.    */
-  tree old_contracts = DECL_CONTRACTS (olddecl);
-  tree new_contracts = DECL_CONTRACTS (newdecl);
-
-  if (!old_contracts && !new_contracts)
-    return;
-
-  location_t old_loc = DECL_SOURCE_LOCATION (olddecl);
-  location_t new_loc = DECL_SOURCE_LOCATION (newdecl);
-
-  /* If both declarations specify contracts, ensure they match.
-
-     TODO: This handles a potential error a little oddly. Consider:
-
-       struct B {
-         virtual void f(int n) [[pre: n == 0]];
-       };
-       struct D : B {
-         void f(int n) override; // inherits contracts
-       };
-       void D::f(int n) [[pre: n == 0]] // OK
-       { }
-
-    It's okay because we're explicitly restating the inherited contract.
-    Changing the precondition on the definition D::f causes match_contracts
-    to complain about the mismatch.
-
-    This would previously have been diagnosed as adding contracts to an
-    override, but this seems like it should be well-formed.  */
-  if (old_contracts && new_contracts)
-    {
-      if (!match_contract_conditions (old_loc, old_contracts,
-                                     new_loc, new_contracts,
-                                     cmc_declaration))
-       return;
-    }
-
-  /* Handle cases where contracts are omitted in one or the other
-     declaration.  */
-  if (old_contracts)
-    {
-      /* Contracts have been previously specified by are no omitted. The
-        new declaration inherits the existing contracts. */
-      if (!new_contracts)
-       copy_contract_attributes (newdecl, olddecl);
-
-      /* In all cases, remove existing contracts from OLDDECL to prevent the
-        attribute merging function from adding excess contracts.  */
-      remove_contract_attributes (olddecl);
-    }
-  else if (!old_contracts)
-    {
-      /* We are adding contracts to a declaration.  */
-      if (new_contracts)
-       {
-         /* We can't add to a previously defined function.  */
-         if (DECL_INITIAL (olddecl))
-           {
-             auto_diagnostic_group d;
-             error_at (new_loc, "cannot add contracts after definition");
-             inform (DECL_SOURCE_LOCATION (olddecl), "original definition here");
-             return;
-           }
-
-         /* We can't add to an unguarded virtual function declaration.  */
-         if (DECL_VIRTUAL_P (olddecl) && new_contracts)
-           {
-             auto_diagnostic_group d;
-             error_at (new_loc, "cannot add contracts to a virtual function");
-             inform (DECL_SOURCE_LOCATION (olddecl), "original declaration here");
-             return;
-           }
-
-         /* Depending on the "first declaration" rule, we may not be able
-            to add contracts to a function after the fact.  */
-         if (flag_contract_strict_declarations)
-           {
-             warning_at (new_loc,
-                         OPT_fcontract_strict_declarations_,
-                         "declaration adds contracts to %q#D",
-                         olddecl);
-             return;
-           }
-
-         /* Copy the contracts from NEWDECL to OLDDECL. We shouldn't need to
-            remap them because NEWDECL's parameters will replace those of
-            OLDDECL.  Remove the contracts from NEWDECL so they aren't
-            cloned when merging.  */
-         copy_contract_attributes (olddecl, newdecl);
-         remove_contract_attributes (newdecl);
-       }
-    }
-}
-
 /* OLD_PARMS is the innermost set of template parameters for some template
    declaration, and NEW_PARMS is the corresponding set of template parameters
    for a redeclaration of that template.  Merge the default arguments within
index 7399c2f8a3685dec6e50eb80d50eb4aec5a73e42..a911a660178f8b7e8403f6c3c4bc7d793f00b9ec 100644 (file)
@@ -29688,7 +29688,7 @@ cp_parser_contract_attribute_spec (cp_parser *parser, tree attribute)
       DEFPARSE_TOKENS (condition) = cp_token_cache_new (first, last);
       DEFPARSE_INSTANTIATIONS (condition) = NULL;
 
-      /* And it's corresponding contract.  */
+      /* And its corresponding contract.  */
       contract = grok_contract (attribute, mode, identifier, condition, loc);
     }
   else