This is the mail archive of the
java@gcc.gnu.org
mailing list for the Java project.
Re: PATCH for better assertion control.
- From: Per Bothner <per at bothner dot com>
- To: Per Bothner <per at bothner dot com>
- Cc: gcc-patches at gcc dot gnu dot org, java at gcc dot gnu dot org
- Date: Sat, 13 Mar 2004 14:47:14 -0800
- Subject: Re: PATCH for better assertion control.
- References: <40526AED.6070807@bothner.com>
And here's the actual patch ...
--
--Per Bothner
per@bothner.com http://per.bothner.com/
2004-03-12 Per Bothner <per@bothner.com>
* class.c (assume_compiled_node_struct): Rename type to
class_flag_node_struct, as it is now also used for enable_assertions.
Rename assume_compiled_node typedef. Rename excludep field to value.
(find_assume_compiled_node): Rename function to find_class_flag_node.
Minor optimization - avoid needless strlen.
(add_assume_compiled): Some tweaking and optimization.
Rename and generalize to add_class_flag takem an extra parameter.
(add_assume_compled): New just calls add_class_flag.
(add_enable_assert, enable_assertions): New functions.
(enable_assert_tree): New static.
* java-tree.h (add_enable_assert, enable_assertions): New declarations.
* lang.opt (fenable-assertions, fenable-assertions=,
fdisable-assertions, fdisable-assertions=): New options.
* lang.c (java_handle_option): Handle new options.
* parse.y (build_incomplete_class_ref): Handle class$ in an inner
class in an interface - create helpe r class nested in outer interface.
(build_assertion): Short-circuit if enable_assertions is false.
Index: class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/class.c,v
retrieving revision 1.178
diff -u -p -r1.178 class.c
--- class.c 26 Feb 2004 15:34:05 -0000 1.178
+++ class.c 13 Mar 2004 01:48:11 -0000
@@ -70,30 +70,32 @@ struct obstack temporary_obstack;
it can assume certain classes have been compiled down to native
code or not. The compiler options -fassume-compiled= and
-fno-assume-compiled= are used to create a tree of
- assume_compiled_node objects. This tree is queried to determine if
+ class_flag_node objects. This tree is queried to determine if
a class is assume to be compiled or not. Each node in the tree
represents either a package or a specific class. */
-typedef struct assume_compiled_node_struct
+typedef struct class_flag_node_struct
{
/* The class or package name. */
const char *ident;
/* Nonzero if this represents an exclusion. */
- int excludep;
+ int value;
/* Pointers to other nodes in the tree. */
- struct assume_compiled_node_struct *parent;
- struct assume_compiled_node_struct *sibling;
- struct assume_compiled_node_struct *child;
-} assume_compiled_node;
+ struct class_flag_node_struct *parent;
+ struct class_flag_node_struct *sibling;
+ struct class_flag_node_struct *child;
+} class_flag_node;
-static assume_compiled_node *find_assume_compiled_node (assume_compiled_node *,
- const char *);
+static class_flag_node *find_class_flag_node (class_flag_node *, const char *);
+static void add_class_flag (class_flag_node **, const char *, int);
/* This is the root of the include/exclude tree. */
-static assume_compiled_node *assume_compiled_tree;
+static class_flag_node *assume_compiled_tree;
+
+static class_flag_node *enable_assert_tree;
static GTY(()) tree class_roots[5];
#define registered_class class_roots[0]
@@ -103,11 +105,11 @@ static GTY(()) tree class_roots[5];
#define class_dtable_decl class_roots[4]
/* Return the node that most closely represents the class whose name
- is IDENT. Start the search from NODE. Return NULL if an
- appropriate node does not exist. */
+ is IDENT. Start the search from NODE (followed by its siblings).
+ Return NULL if an appropriate node does not exist. */
-static assume_compiled_node *
-find_assume_compiled_node (assume_compiled_node *node, const char *ident)
+static class_flag_node *
+find_class_flag_node (class_flag_node *node, const char *ident)
{
while (node)
{
@@ -120,14 +122,13 @@ find_assume_compiled_node (assume_compil
if (node_ident_length == 0
|| (strncmp (ident, node->ident, node_ident_length) == 0
- && (strlen (ident) == node_ident_length
+ && (ident[node_ident_length] == '\0'
|| ident[node_ident_length] == '.')))
{
/* We've found a match, however, there might be a more
specific match. */
- assume_compiled_node *found = find_assume_compiled_node (node->child,
- ident);
+ class_flag_node *found = find_class_flag_node (node->child, ident);
if (found)
return found;
else
@@ -142,54 +143,77 @@ find_assume_compiled_node (assume_compil
return NULL;
}
-/* Add a new IDENT to the include/exclude tree. It's an exclusion
- if EXCLUDEP is nonzero. */
-
void
-add_assume_compiled (const char *ident, int excludep)
+add_class_flag (class_flag_node **rootp, const char *ident, int value)
{
- int len;
- assume_compiled_node *parent;
- assume_compiled_node *node = xmalloc (sizeof (assume_compiled_node));
-
- node->ident = xstrdup (ident);
- node->excludep = excludep;
- node->child = NULL;
+ class_flag_node *root = *rootp;
+ class_flag_node *parent, *node;
/* Create the root of the tree if it doesn't exist yet. */
- if (NULL == assume_compiled_tree)
+ if (NULL == root)
{
- assume_compiled_tree = xmalloc (sizeof (assume_compiled_node));
- assume_compiled_tree->ident = "";
- assume_compiled_tree->excludep = 0;
- assume_compiled_tree->sibling = NULL;
- assume_compiled_tree->child = NULL;
- assume_compiled_tree->parent = NULL;
+ root = xmalloc (sizeof (class_flag_node));
+ root->ident = "";
+ root->value = 0;
+ root->sibling = NULL;
+ root->child = NULL;
+ root->parent = NULL;
+ *rootp = root;
}
/* Calling the function with the empty string means we're setting
- excludep for the root of the hierarchy. */
+ value for the root of the hierarchy. */
if (0 == ident[0])
{
- assume_compiled_tree->excludep = excludep;
+ root->value = value;
return;
}
/* Find the parent node for this new node. PARENT will either be a
class or a package name. Adjust PARENT accordingly. */
- parent = find_assume_compiled_node (assume_compiled_tree, ident);
- len = strlen (parent->ident);
- if (parent->ident[len] && parent->ident[len] != '.')
- parent = parent->parent;
-
- /* Insert NODE into the tree. */
-
- node->parent = parent;
- node->sibling = parent->child;
- parent->child = node;
+ parent = find_class_flag_node (root, ident);
+ if (strcmp (ident, parent->ident) == 0)
+ parent->value = value;
+ else
+ {
+ /* Insert new node into the tree. */
+ node = xmalloc (sizeof (class_flag_node));
+
+ node->ident = xstrdup (ident);
+ node->value = value;
+ node->child = NULL;
+
+ node->parent = parent;
+ node->sibling = parent->child;
+ parent->child = node;
+ }
+}
+
+/* Add a new IDENT to the include/exclude tree. It's an exclusion
+ if EXCLUDEP is nonzero. */
+
+void
+add_assume_compiled (const char *ident, int excludep)
+{
+ add_class_flag (&assume_compiled_tree, ident, excludep);
+}
+
+/* The default value returned by enable_asserstions. */
+
+#define DEFAULT_ENABLE_ASSERT (flag_emit_class_files || optimize == 0)
+
+/* Enter IDENT (a class or package name) into the enable-assertions table.
+ VALUE is true to enable and false to disable. *.
+
+void
+add_enable_assert (const char *ident, int value)
+{
+ if (enable_assert_tree == NULL)
+ add_class_flag (&enable_assert_tree, "", DEFAULT_ENABLE_ASSERT);
+ add_class_flag (&enable_assert_tree, ident, value);
}
/* Returns nonzero if IDENT is the name of a class that the compiler
@@ -198,18 +222,37 @@ add_assume_compiled (const char *ident,
static int
assume_compiled (const char *ident)
{
- assume_compiled_node *i;
+ class_flag_node *i;
int result;
if (NULL == assume_compiled_tree)
return 1;
- i = find_assume_compiled_node (assume_compiled_tree,
- ident);
+ i = find_class_flag_node (assume_compiled_tree, ident);
- result = ! i->excludep;
+ result = ! i->value;
return (result);
+}
+
+/* Return true if we should generate code to check assertions within KLASS. */
+
+bool
+enable_assertions (tree klass)
+{
+ /* Check if command-line specifies whether we should check asserrtions. */
+
+ if (klass != NULL_TREE && DECL_NAME (klass) && enable_assert_tree != NULL)
+ {
+ const char *ident = IDENTIFIER_POINTER (DECL_NAME (klass));
+ class_flag_node *node
+ = find_class_flag_node (enable_assert_tree, ident);
+ return node->value;
+ }
+
+ /* The default is to enable assertions if generating class files,
+ or not optimizing. */
+ return DEFAULT_ENABLE_ASSERT;
}
/* Return an IDENTIFIER_NODE the same as (OLD_NAME, OLD_LENGTH).
Index: java-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/java-tree.h,v
retrieving revision 1.195
diff -u -p -r1.195 java-tree.h
--- java-tree.h 26 Feb 2004 04:58:07 -0000 1.195
+++ java-tree.h 13 Mar 2004 01:48:11 -0000
@@ -1128,6 +1128,8 @@ extern tree java_signed_type (tree);
extern tree java_signed_or_unsigned_type (int, tree);
extern tree java_truthvalue_conversion (tree);
extern void add_assume_compiled (const char *, int);
+extern void add_enable_assert (const char *, int);
+extern bool enable_assertions (tree);
extern tree lookup_class (tree);
extern tree lookup_java_constructor (tree, tree);
extern tree lookup_java_method (tree, tree, tree);
Index: lang.opt
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/lang.opt,v
retrieving revision 1.6
diff -u -p -r1.6 lang.opt
--- lang.opt 19 Jul 2003 08:13:58 -0000 1.6
+++ lang.opt 13 Mar 2004 01:48:11 -0000
@@ -90,6 +90,18 @@ Java
fassume-compiled=
Java JoinedOrMissing
+fenable-assertions
+Java
+
+fenable-assertions=
+Java JoinedOrMissing
+
+fdisable-assertions
+Java
+
+fdisable-assertions=
+Java JoinedOrMissing
+
fbootclasspath=
Java JoinedOrMissing RejectNegative
--bootclasspath=<path> Replace system path
Index: lang.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/lang.c,v
retrieving revision 1.149
diff -u -p -r1.149 lang.c
--- lang.c 13 Jan 2004 23:14:04 -0000 1.149
+++ lang.c 13 Mar 2004 01:48:12 -0000
@@ -354,6 +354,22 @@ java_handle_option (size_t scode, const
flag_assert = value;
break;
+ case OPT_fenable_assertions_:
+ add_enable_assert (arg, value);
+ break;
+
+ case OPT_fenable_assertions:
+ add_enable_assert ("", value);
+ break;
+
+ case OPT_fdisable_assertions_:
+ add_enable_assert (arg, !value);
+ break;
+
+ case OPT_fdisable_assertions:
+ add_enable_assert ("", !value);
+ break;
+
case OPT_fassume_compiled_:
add_assume_compiled (arg, !value);
break;
Index: parse.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/parse.y,v
retrieving revision 1.472
diff -u -p -r1.472 parse.y
--- parse.y 28 Feb 2004 00:34:25 -0000 1.472
+++ parse.y 13 Mar 2004 01:48:16 -0000
@@ -13991,25 +13991,32 @@ build_incomplete_class_ref (int location
&& !JPRIMITIVE_TYPE_P (class_name)
&& !(TREE_CODE (class_name) == VOID_TYPE))
{
+ tree cpc_list = GET_CPC_LIST();
+ tree cpc = cpc_list;
tree target_class;
- if (CLASS_INTERFACE (TYPE_NAME (this_class)))
+ /* For inner classes, add a 'class$' method to their outermost
+ context, creating it if necessary. */
+
+ while (GET_NEXT_ENCLOSING_CPC(cpc))
+ cpc = GET_NEXT_ENCLOSING_CPC(cpc);
+ class_decl = TREE_VALUE (cpc);
+
+ target_class = TREE_TYPE (class_decl);
+
+ if (CLASS_INTERFACE (TYPE_NAME (target_class)))
{
/* For interfaces, adding a static 'class$' method directly
is illegal. So create an inner class to contain the new
method. Empirically this matches the behavior of javac. */
- tree t = build_wfl_node (DECL_NAME (TYPE_NAME (object_type_node)));
- tree inner = create_anonymous_class (0, t);
+ tree t, inner;
+ /* We want the generated inner class inside the outermost class. */
+ GET_CPC_LIST() = cpc;
+ t = build_wfl_node (DECL_NAME (TYPE_NAME (object_type_node)));
+ inner = create_anonymous_class (0, t);
target_class = TREE_TYPE (inner);
end_class_declaration (1);
- }
- else
- {
- /* For inner classes, add a 'class$' method to their outermost
- context, creating it if necessary. */
- while (INNER_CLASS_DECL_P (class_decl))
- class_decl = DECL_CONTEXT (class_decl);
- target_class = TREE_TYPE (class_decl);
+ GET_CPC_LIST() = cpc_list;
}
if (TYPE_DOT_CLASS (target_class) == NULL_TREE)
@@ -15297,6 +15304,16 @@ build_assertion (int location, tree cond
{
tree node;
tree klass = GET_CPC ();
+
+ if (! enable_assertions (klass))
+ {
+ condition = build (TRUTH_ANDIF_EXPR, NULL_TREE,
+ boolean_false_node, condition);
+ if (value == NULL_TREE)
+ value = empty_stmt_node;
+ return build_if_else_statement (location, condition,
+ value, NULL_TREE);
+ }
if (! CLASS_USES_ASSERTIONS (klass))
{