public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/c++-contracts] c++: move duplicate_contracts to contracts.cc
@ 2022-11-01 11:43 Jason Merrill
0 siblings, 0 replies; only message in thread
From: Jason Merrill @ 2022-11-01 11:43 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:5080aec5f3f0eae334883c099f93070e6c3a5b64
commit 5080aec5f3f0eae334883c099f93070e6c3a5b64
Author: Jason Merrill <jason@redhat.com>
Date: Fri Oct 28 11:37:23 2022 -0400
c++: move duplicate_contracts to contracts.cc
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.
Diff:
---
gcc/cp/cp-tree.h | 1 +
gcc/cp/contracts.cc | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++
gcc/cp/decl.cc | 101 ----------------------------------------------------
gcc/cp/parser.cc | 2 +-
4 files changed, 103 insertions(+), 102 deletions(-)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 11ac082c89f..a212aa2659d 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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)
diff --git a/gcc/cp/contracts.cc b/gcc/cp/contracts.cc
index 214be7c671f..272448d07d8 100644
--- a/gcc/cp/contracts.cc
+++ b/gcc/cp/contracts.cc
@@ -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"
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 9740129456b..d6eb50a260b 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -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
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 7399c2f8a36..a911a660178 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -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
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2022-11-01 11:43 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-01 11:43 [gcc/devel/c++-contracts] c++: move duplicate_contracts to contracts.cc Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).