On 1/4/21 9:58 AM, Jeff Chapman wrote:
Ping. re:
https://gcc.gnu.org/pipermail/gcc-patches/2020-December/561135.html
<https://gcc.gnu.org/pipermail/gcc-patches/2020-December/561135.html>
> OK, I'll start with -alt then, thanks.
Andrew is exactly correct, contracts-jac-alt is still the current
branch we're focusing our upstreaming efforts on.
It's trailing upstream master by a fair bit at this point. I'll get
a merge pushed shortly.
The latest is still on the same branch, which hasn't been updated since
that last merge:
https://github.com/lock3/gcc/tree/contracts-jac-alt
<https://github.com/lock3/gcc/tree/contracts-jac-alt>
Would you prefer me to keep it from trailing upstream too much through
regular merges, or would it be more beneficial for it to be left alone
so you have a more stable review target?
Please let me know if there's initial feedback I can start addressing,
or anything I can do to help the review process along in general.
Why is some of the code in c-family? From the modules merge there is
now a cp_handle_option function that you could add the option handling
to, and I don't see a reason for cxx-contracts.c to be in c-family/
rather than cp/.
And then much of the code you add to decl.c could also move to the
contracts file, and some of the contracts stuff in cp-tree.h could move
to cxx-contracts.h?
+extern bool cxx23_contract_attribute_p (const_tree);
This name seems optimistic. :)
Let's call it cxx_contract_attribute_p.
+/* Return TRUE iff ATTR has been parsed by the fornt-end as a c++2a contract
"front"
@@ -566,7 +566,11 @@ decl_attributes (tree *node, tree attributes, int flags,
{
if (!(flags & (int) ATTR_FLAG_BUILT_IN))
{
- if (ns == NULL_TREE || !cxx11_attr_p)
+ if (cxx23_contract_attribute_p (attr))
+ {
+ ; /* Do not warn about contract "attributes". */
+ }
I don't want the language-independent code to have to know about this.
If you want decl_attributes to ignore these attributes, you could give
these attributes a dummy spec that just returns?
+set_decl_contracts (tree decl, tree contract_attrs)
+{
+ remove_contract_attributes (decl);
+ if (!DECL_ATTRIBUTES (decl))
+ {
+ DECL_ATTRIBUTES (decl) = contract_attrs;
+ return;
+ }
+ tree last_attr = DECL_ATTRIBUTES (decl);
+ while (TREE_CHAIN (last_attr))
+ last_attr = TREE_CHAIN (last_attr);
+ TREE_CHAIN (last_attr) = contract_attrs;
I think you want to use 'chainon' here.
@@ -5498,10 +5863,17 @@ start_decl (const cp_declarator *declarator,
if (DECL_EXTERNAL (decl) && ! DECL_TEMPLATE_SPECIALIZATION (decl)
/* Aliases are definitions. */
- && !alias)
+ && !alias
+ && (DECL_VIRTUAL_P (decl) || !flag_contracts))
permerror (declarator->id_loc,
"declaration of %q#D outside of class is not definition",
decl);
+ else if (DECL_EXTERNAL (decl) && ! DECL_TEMPLATE_SPECIALIZATION (decl)
+ /* Aliases are definitions. */
+ && !alias
+ && flag_contract_strict_declarations)
+ warning_at (declarator->id_loc, OPT_fcontract_strict_declarations_,
+ "non-defining declaration of %q#D outside of class", decl);
Let's keep the same message for the two cases.
+void
+finish_function_contracts (tree fndecl, bool is_inline)
This function needs a comment.
+/* cp_tree_defined_p helper -- returns TP if TP is undefined. */
+
+static tree
+cp_tree_defined_p_r (tree *tp, int *, void *)
+{
+ enum tree_code code = TREE_CODE (*tp);
+ if ((code == FUNCTION_DECL || code == VAR_DECL)
+ && !decl_defined_p (*tp))
+ return *tp;
+ /* We never want to accidentally instantiate templates. */
+ if (code == TEMPLATE_DECL)
+ return *tp; /* FIXME? */
In what context are you getting a TEMPLATE_DECL here? I don't see how
this would have an effect on instantiations.
+/* Parse a conditional-expression. */
+/* FIXME: should callers use cp_parser_constant_expression? */
+
+static cp_expr
+cp_parser_conditional_expression (cp_parser *parser)
...
+ /* FIXME: can we use constant_expression for this? */
+ cp_expr cond = cp_parser_conditional_expression (parser);
I don't think we want to use cp_parser_constant_expression for
expressions that are not intended to be constant.
+ bool finishing_guarded_p = true//!processing_template_decl
?
+ /* FIXME: Is this going to leak? */
+ comment_str = xstrdup (expr_to_string (cond));
There's no need to strdup here (and free a few lines later);
build_string_literal copies the bytes. The return value of
expr_to_string is in GC memory.
+ /* If we have contracts, check that they're valid in this context. */
+ // FIXME: These aren't entirely correct.
How not? Can local extern function decls have contract attributes?
+ if (tree pre = lookup_attribute ("pre", contract_attrs))
+ error_at (EXPR_LOCATION (TREE_VALUE (pre)),
+ "preconditions cannot be statements");
+ else if (tree post = lookup_attribute ("post", contract_attrs))
+ error_at (EXPR_LOCATION (TREE_VALUE (post)),
+ "postconditions cannot be statements");
+
+ /* FIXME: move fallthrough up here so it applies to decls/etc? */
That would make sense.
+ temp_override<tree> saved_cct(current_class_type);
+ temp_override<tree> saved_ccp(current_class_ptr);
+ temp_override<tree> saved_ccr(current_class_ref);
Are these actually needed?
+++ b/gcc/tree-inline.c
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see
#include "ssa.h"
#include "cgraph.h"
#include "tree-pretty-print.h"
+#include "cp/cp-tree.h"
Can't include cp-tree.h in a language-independent file. We already call
the tree-inline machinery from the front-end in clone_body; can't you do
the same for contracts?
+build_arg_list (tree fn)
+{
+ gcc_assert (TREE_CODE (fn) == FUNCTION_DECL);
+
+ vec<tree, va_gc> *args = make_tree_vector ();
+ for (tree t = DECL_ARGUMENTS (fn); t != NULL_TREE; t = TREE_CHAIN (t))
+ {
+ if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE
+ && DECL_NAME (t) != NULL_TREE
+ && IDENTIFIER_POINTER (DECL_NAME (t)) != NULL
+ && id_equal (DECL_NAME (t), "this"))
You can use is_this_parameter here.
+ /* FIXME when we instatiate a template class with guarded
+ * members, particularly guarded template members, the resulting
+ * pre/post functions end up being inaccessible because their
+ * template info's context is the original uninstantiated class.
This sounds like a significant functionality gap. I'm guessing you want
to reconsider the unshare_template approach.
+// FIXME: are we sure we shouldn't just mangle or use some existing machinery?
+static const char *
+get_contracts_internal_decl_name (const char *ident)
Definitely use the mangling machinery.
+ /* FIXME do we need magic to perfectly forward this so we don't clobber
+ RVO/NRVO etc? */
Yes. CALL_FROM_THUNK_P will probably get you some of the magic you want.
More soon.
Jason