summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2010-01-20 12:27:49 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2010-01-20 12:27:49 +0100
commit66c57cb805854d5d3989992869678c32d3a21d0c (patch)
treeb0b0d01735e1f5f343bd52123bcb1818777a98f7
parente3079365b6e100fefa34dc7d14d32ecb5fdc7ef1 (diff)
downloadgcc-66c57cb805854d5d3989992869678c32d3a21d0c.tar.gz
re PR middle-end/42803 (c++ compilation hang)
PR middle-end/42803 * varasm.c (narrowing_initializer_constant_valid_p): Add CACHE argument, call initializer_constant_valid_p_1 instead of initializer_constant_valid_p, pass CACHE to it, return NULL immediately if first call returns NULL. (initializer_constant_valid_p_1): New function. (initializer_constant_valid_p): Use it. * g++.dg/parse/limits-initializer1.C: New test. From-SVN: r156070
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/g++.dg/parse/limits-initializer1.C37
-rw-r--r--gcc/varasm.c169
4 files changed, 163 insertions, 54 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 14dc7a6ce92..5c2e3ba5a3c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -5,6 +5,14 @@
* unwind-dw2.c (execute_stack_op): Handle DW_OP_mod using unsigned
modulo instead of signed.
+ PR middle-end/42803
+ * varasm.c (narrowing_initializer_constant_valid_p): Add CACHE
+ argument, call initializer_constant_valid_p_1 instead of
+ initializer_constant_valid_p, pass CACHE to it, return NULL
+ immediately if first call returns NULL.
+ (initializer_constant_valid_p_1): New function.
+ (initializer_constant_valid_p): Use it.
+
2010-01-18 Uros Bizjak <ubizjak@gmail.com>
PR target/42774
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index dcfb2482456..98a2c4ebcba 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -3,6 +3,9 @@
* gcc.dg/cleanup-13.c: Expect DW_OP_mod to do unsigned modulo instead
of signed, add a few new tests.
+ PR middle-end/42803
+ * g++.dg/parse/limits-initializer1.C: New test.
+
2010-01-18 Uros Bizjak <ubizjak@gmail.com>
PR target/42774
diff --git a/gcc/testsuite/g++.dg/parse/limits-initializer1.C b/gcc/testsuite/g++.dg/parse/limits-initializer1.C
new file mode 100644
index 00000000000..4b507912f36
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/limits-initializer1.C
@@ -0,0 +1,37 @@
+// PR middle-end/42803
+// { dg-do compile }
+// { dg-options "-O0" }
+
+#define X2 (a + a)
+#define X4 (X2 + X2)
+#define X8 (X4 + X4)
+#define X16 (X8 + X8)
+#define X32 (X16 + X16)
+#define X64 (X32 + X32)
+#define X128 (X64 + X64)
+#define X256 (X128 + X128)
+#define X512 (X256 + X256)
+#define X1024 (X512 + X512)
+#define X2048 (X1024 + X1024)
+#define X4096 (X2048 + X2048)
+#define X8192 (X4096 + X4096)
+#define X16384 (X8192 + X8192)
+#define X32768 (X16384 + X16384)
+#define X65536 (X32768 + X32768)
+#define X131072 (X65536 + X65536)
+#define X262144 (X131072 + X131072)
+
+int
+foo (int a)
+{
+ int v = X262144;
+ return v;
+}
+
+// Emit an error to just make sure we don't waste too much time
+// in the middle-end compiling this.
+int
+bar (void)
+{
+ return x; // { dg-error "was not declared in this scope" }
+}
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 9c6dec520d2..9385b47704c 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -1,7 +1,7 @@
/* Output variables, constants and external declarations, for GNU compiler.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
- 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
- Free Software Foundation, Inc.
+ 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
+ 2010 Free Software Foundation, Inc.
This file is part of GCC.
@@ -4072,6 +4072,9 @@ constructor_static_from_elts_p (const_tree ctor)
&& !VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (ctor)));
}
+static tree initializer_constant_valid_p_1 (tree value, tree endtype,
+ tree *cache);
+
/* A subroutine of initializer_constant_valid_p. VALUE is a MINUS_EXPR,
PLUS_EXPR or POINTER_PLUS_EXPR. This looks for cases of VALUE
which are valid when ENDTYPE is an integer of any size; in
@@ -4081,7 +4084,7 @@ constructor_static_from_elts_p (const_tree ctor)
returns NULL. */
static tree
-narrowing_initializer_constant_valid_p (tree value, tree endtype)
+narrowing_initializer_constant_valid_p (tree value, tree endtype, tree *cache)
{
tree op0, op1;
@@ -4120,11 +4123,14 @@ narrowing_initializer_constant_valid_p (tree value, tree endtype)
op1 = inner;
}
- op0 = initializer_constant_valid_p (op0, endtype);
- op1 = initializer_constant_valid_p (op1, endtype);
+ op0 = initializer_constant_valid_p_1 (op0, endtype, cache);
+ if (!op0)
+ return NULL_TREE;
+ op1 = initializer_constant_valid_p_1 (op1, endtype,
+ cache ? cache + 2 : NULL);
/* Both initializers must be known. */
- if (op0 && op1)
+ if (op1)
{
if (op0 == op1
&& (op0 == null_pointer_node
@@ -4145,7 +4151,8 @@ narrowing_initializer_constant_valid_p (tree value, tree endtype)
return NULL_TREE;
}
-/* Return nonzero if VALUE is a valid constant-valued expression
+/* Helper function of initializer_constant_valid_p.
+ Return nonzero if VALUE is a valid constant-valued expression
for use in initializing a static variable; one that can be an
element of a "constant" initializer.
@@ -4153,10 +4160,12 @@ narrowing_initializer_constant_valid_p (tree value, tree endtype)
if it is relocatable, return the variable that determines the relocation.
We assume that VALUE has been folded as much as possible;
therefore, we do not need to check for such things as
- arithmetic-combinations of integers. */
+ arithmetic-combinations of integers.
-tree
-initializer_constant_valid_p (tree value, tree endtype)
+ Use CACHE (pointer to 2 tree values) for caching if non-NULL. */
+
+static tree
+initializer_constant_valid_p_1 (tree value, tree endtype, tree *cache)
{
tree ret;
@@ -4169,18 +4178,33 @@ initializer_constant_valid_p (tree value, tree endtype)
tree elt;
bool absolute = true;
+ if (cache && cache[0] == value)
+ return cache[1];
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (value), idx, elt)
{
tree reloc;
- reloc = initializer_constant_valid_p (elt, TREE_TYPE (elt));
+ reloc = initializer_constant_valid_p_1 (elt, TREE_TYPE (elt),
+ NULL);
if (!reloc)
- return NULL_TREE;
+ {
+ if (cache)
+ {
+ cache[0] = value;
+ cache[1] = NULL_TREE;
+ }
+ return NULL_TREE;
+ }
if (reloc != null_pointer_node)
absolute = false;
}
/* For a non-absolute relocation, there is no single
variable that can be "the variable that determines the
relocation." */
+ if (cache)
+ {
+ cache[0] = value;
+ cache[1] = absolute ? null_pointer_node : error_mark_node;
+ }
return absolute ? null_pointer_node : error_mark_node;
}
@@ -4221,7 +4245,8 @@ initializer_constant_valid_p (tree value, tree endtype)
}
case NON_LVALUE_EXPR:
- return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
+ return initializer_constant_valid_p_1 (TREE_OPERAND (value, 0),
+ endtype, cache);
case VIEW_CONVERT_EXPR:
{
@@ -4236,13 +4261,13 @@ initializer_constant_valid_p (tree value, tree endtype)
if (AGGREGATE_TYPE_P (src_type) && !AGGREGATE_TYPE_P (dest_type))
{
if (TYPE_MODE (endtype) == TYPE_MODE (dest_type))
- return initializer_constant_valid_p (src, endtype);
+ return initializer_constant_valid_p_1 (src, endtype, cache);
else
return NULL_TREE;
}
/* Allow all other kinds of view-conversion. */
- return initializer_constant_valid_p (src, endtype);
+ return initializer_constant_valid_p_1 (src, endtype, cache);
}
CASE_CONVERT:
@@ -4257,18 +4282,18 @@ initializer_constant_valid_p (tree value, tree endtype)
|| (FLOAT_TYPE_P (dest_type) && FLOAT_TYPE_P (src_type))
|| (TREE_CODE (dest_type) == OFFSET_TYPE
&& TREE_CODE (src_type) == OFFSET_TYPE))
- return initializer_constant_valid_p (src, endtype);
+ return initializer_constant_valid_p_1 (src, endtype, cache);
/* Allow length-preserving conversions between integer types. */
if (INTEGRAL_TYPE_P (dest_type) && INTEGRAL_TYPE_P (src_type)
&& (TYPE_PRECISION (dest_type) == TYPE_PRECISION (src_type)))
- return initializer_constant_valid_p (src, endtype);
+ return initializer_constant_valid_p_1 (src, endtype, cache);
/* Allow conversions between other integer types only if
explicit value. */
if (INTEGRAL_TYPE_P (dest_type) && INTEGRAL_TYPE_P (src_type))
{
- tree inner = initializer_constant_valid_p (src, endtype);
+ tree inner = initializer_constant_valid_p_1 (src, endtype, cache);
if (inner == null_pointer_node)
return null_pointer_node;
break;
@@ -4277,7 +4302,7 @@ initializer_constant_valid_p (tree value, tree endtype)
/* Allow (int) &foo provided int is as wide as a pointer. */
if (INTEGRAL_TYPE_P (dest_type) && POINTER_TYPE_P (src_type)
&& (TYPE_PRECISION (dest_type) >= TYPE_PRECISION (src_type)))
- return initializer_constant_valid_p (src, endtype);
+ return initializer_constant_valid_p_1 (src, endtype, cache);
/* Likewise conversions from int to pointers, but also allow
conversions from 0. */
@@ -4291,14 +4316,14 @@ initializer_constant_valid_p (tree value, tree endtype)
if (integer_zerop (src))
return null_pointer_node;
else if (TYPE_PRECISION (dest_type) <= TYPE_PRECISION (src_type))
- return initializer_constant_valid_p (src, endtype);
+ return initializer_constant_valid_p_1 (src, endtype, cache);
}
/* Allow conversions to struct or union types if the value
inside is okay. */
if (TREE_CODE (dest_type) == RECORD_TYPE
|| TREE_CODE (dest_type) == UNION_TYPE)
- return initializer_constant_valid_p (src, endtype);
+ return initializer_constant_valid_p_1 (src, endtype, cache);
}
break;
@@ -4308,66 +4333,102 @@ initializer_constant_valid_p (tree value, tree endtype)
with -frounding-math we hit this with addition of two constants. */
if (TREE_CODE (endtype) == REAL_TYPE)
return NULL_TREE;
+ if (cache && cache[0] == value)
+ return cache[1];
if (! INTEGRAL_TYPE_P (endtype)
|| TYPE_PRECISION (endtype) >= POINTER_SIZE)
{
- tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
- endtype);
- tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
- endtype);
+ tree ncache[4] = { NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE };
+ tree valid0
+ = initializer_constant_valid_p_1 (TREE_OPERAND (value, 0),
+ endtype, ncache);
+ tree valid1
+ = initializer_constant_valid_p_1 (TREE_OPERAND (value, 1),
+ endtype, ncache + 2);
/* If either term is absolute, use the other term's relocation. */
if (valid0 == null_pointer_node)
- return valid1;
- if (valid1 == null_pointer_node)
- return valid0;
+ ret = valid1;
+ else if (valid1 == null_pointer_node)
+ ret = valid0;
+ /* Support narrowing pointer differences. */
+ else
+ ret = narrowing_initializer_constant_valid_p (value, endtype,
+ ncache);
}
-
+ else
/* Support narrowing pointer differences. */
- ret = narrowing_initializer_constant_valid_p (value, endtype);
- if (ret != NULL_TREE)
- return ret;
-
- break;
+ ret = narrowing_initializer_constant_valid_p (value, endtype, NULL);
+ if (cache)
+ {
+ cache[0] = value;
+ cache[1] = ret;
+ }
+ return ret;
case MINUS_EXPR:
if (TREE_CODE (endtype) == REAL_TYPE)
return NULL_TREE;
+ if (cache && cache[0] == value)
+ return cache[1];
if (! INTEGRAL_TYPE_P (endtype)
|| TYPE_PRECISION (endtype) >= POINTER_SIZE)
{
- tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
- endtype);
- tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
- endtype);
+ tree ncache[4] = { NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE };
+ tree valid0
+ = initializer_constant_valid_p_1 (TREE_OPERAND (value, 0),
+ endtype, ncache);
+ tree valid1
+ = initializer_constant_valid_p_1 (TREE_OPERAND (value, 1),
+ endtype, ncache + 2);
/* Win if second argument is absolute. */
if (valid1 == null_pointer_node)
- return valid0;
+ ret = valid0;
/* Win if both arguments have the same relocation.
Then the value is absolute. */
- if (valid0 == valid1 && valid0 != 0)
- return null_pointer_node;
-
+ else if (valid0 == valid1 && valid0 != 0)
+ ret = null_pointer_node;
/* Since GCC guarantees that string constants are unique in the
generated code, a subtraction between two copies of the same
constant string is absolute. */
- if (valid0 && TREE_CODE (valid0) == STRING_CST
- && valid1 && TREE_CODE (valid1) == STRING_CST
- && operand_equal_p (valid0, valid1, 1))
- return null_pointer_node;
+ else if (valid0 && TREE_CODE (valid0) == STRING_CST
+ && valid1 && TREE_CODE (valid1) == STRING_CST
+ && operand_equal_p (valid0, valid1, 1))
+ ret = null_pointer_node;
+ /* Support narrowing differences. */
+ else
+ ret = narrowing_initializer_constant_valid_p (value, endtype,
+ ncache);
}
-
- /* Support narrowing differences. */
- ret = narrowing_initializer_constant_valid_p (value, endtype);
- if (ret != NULL_TREE)
- return ret;
-
- break;
+ else
+ /* Support narrowing differences. */
+ ret = narrowing_initializer_constant_valid_p (value, endtype, NULL);
+ if (cache)
+ {
+ cache[0] = value;
+ cache[1] = ret;
+ }
+ return ret;
default:
break;
}
- return 0;
+ return NULL_TREE;
+}
+
+/* Return nonzero if VALUE is a valid constant-valued expression
+ for use in initializing a static variable; one that can be an
+ element of a "constant" initializer.
+
+ Return null_pointer_node if the value is absolute;
+ if it is relocatable, return the variable that determines the relocation.
+ We assume that VALUE has been folded as much as possible;
+ therefore, we do not need to check for such things as
+ arithmetic-combinations of integers. */
+tree
+initializer_constant_valid_p (tree value, tree endtype)
+{
+ return initializer_constant_valid_p_1 (value, endtype, NULL);
}
/* Output assembler code for constant EXP to FILE, with no label.