Hi Richard.
Your last patch for this PR suggested we verify our assumptions wrt a
least common C++ compiler to build trunk with. Since I already had the
offended system at hand (Red Hat Linux 8.0), I decided to investigate a
bit further.
g++ 3.4 builds trunk just fine, but anything prior to this chokes on a
variety of inputs. The patch below fixes them all, and gets 4.8 to
bootstrap with a GCC 3.2 system.
I don't know how much of this is a fool's errand, and if we want to
commit to supporting < GCC 3.4, but your patch suggested c++98, and GCC
3.2 claims such.
The fixed issues are as follows:
1. Older G++ cannot understand attributes among arguments:
int foo(int bar __attribute__ ((__unused__)))
It looks like we already have ARG_UNUSED for this precise problem,
and it is already predicated on !__cplusplus || GCC_VERSION >= 3004.
However, we've deviated from using ARG_UNUSED
throughout the compiler, and I spent hours changing
ATTRIBUTE_UNUSED into ARG_UNUSED until I gave up. It's EVERYWHERE
in the compiler-- all the way into our gen*.c files. It seemed a lot
simpler just changing the definition of ATTRIBUTE_UNUSED.
Perhaps we could even deprecate ARG_UNUSED?
2. gcov-io.c uses __builtin_popcountll and __builtin_clzll. Older
GCC's do not have this. For that matter, how does this even work on
non-GCC systems?
I have abstracted the non built-in versions we have for these in
hwint.c, which seem written for older GCC's and non GCC's.
I am not a huge fan of the new include file, but I really didn't
want to duplicate code. I'm open to suggestions.
3. Derived classes that include a union template die miserably on g++
3.2. Thankfully, this works:
-struct ssa_name_var_hash : typed_noop_remove <union tree_node>
+struct ssa_name_var_hash : typed_noop_remove <tree_node>
4. Type checking as part of a `for' initializer segfaults on g++ 3.2:
for (type = TYPE_MAIN_VARIANT (blah); ....)
The only reasonable thing I could think of, was disabling the tree
checking code for older compilers.
I really don't want to spend much more time on this, but at the same
time, I don't want to throw away a day's work, especially if it could
conceivably help us with (older) non-GCC bootstrap compilers.
The attached patch bootstraps trunk on GCC 3.2 on a Red Hat Linux 8.0
system (i686) configured with:
blah/configure --enable-languages=c,c++ --disable-libsanitizer
libsanitizer seems to be a moving target and it currently has issues
with the RHL8.0 header files (earlier today it had other problems :)).
What are your thoughts on this?
PR other/54324
* Makefile.in (GCOV_IO_C): New.
(hwint.o): Depend on hwint-helper.c
(coverage.o): Depend on $(GCOV_IO_C).
(gcov.o): Same.
(gcov-dump.o): Same.
* basic-block.h (gt_ggc_mx): Fix prototype to work on older
compilers.
(gt_pch_nx): Same.
* gcov-io.c: Include hwint-helper.c.
(gcov_read_summary): Rename __builtin_popcountll to my_popcount.
(gcov_histo_index): Rename __builtin_clzll to my_clz_hwi.
* hwint.c: Move floor_log2, ceil_log2, exact_log2, ctz_hwi,
clz_hwi, ffs_hwi, and popcount_hwi into...
* hwint-helper.c: New file.
* tree-ssa-coalesce.c (struct ssa_name_var_hash): Remove union
specifier.
* tree.h: Disable checking code for GCC < 3.4.
* cp/cp-tree.h: Disable checking code for GCC < 3.4.
* include/ansidecl.h: Do not set __attribute__ for GCC < 3.4.
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 9efc2d3..e04e365 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -879,6 +879,7 @@ GIMPLE_H = gimple.h gimple.def gsstruct.def pointer-set.h
$(VEC_H) \
tree-ssa-alias.h $(INTERNAL_FN_H)
TRANS_MEM_H = trans-mem.h
GCOV_IO_H = gcov-io.h gcov-iov.h auto-host.h
+GCOV_IO_C = gcov-io.c hwint-helper.c
COVERAGE_H = coverage.h $(GCOV_IO_H)
DEMANGLE_H = $(srcdir)/../include/demangle.h
RECOG_H = recog.h
@@ -2700,7 +2701,7 @@ toplev.o : toplev.c $(CONFIG_H) $(SYSTEM_H) coretypes.h
$(TM_H) $(TREE_H) \
$(TREE_PRETTY_PRINT_H) opts-diagnostic.h $(COMMON_TARGET_H) \
tsan.h
-hwint.o : hwint.c $(CONFIG_H) $(SYSTEM_H) $(DIAGNOSTIC_CORE_H)
+hwint.o : hwint.c $(CONFIG_H) $(SYSTEM_H) $(DIAGNOSTIC_CORE_H) hwint-helper.c
passes.o : passes.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(RTL_H) $(FUNCTION_H) $(FLAGS_H) $(INPUT_H) $(INSN_ATTR_H) output.h \
@@ -2945,7 +2946,7 @@ ipa-pure-const.o : ipa-pure-const.c $(CONFIG_H)
$(SYSTEM_H) \
coverage.o : coverage.c $(GCOV_IO_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h
dumpfile.h \
$(TM_H) $(RTL_H) $(TREE_H) $(FLAGS_H) output.h $(REGS_H) $(EXPR_H) \
$(FUNCTION_H) $(BASIC_BLOCK_H) toplev.h $(DIAGNOSTIC_CORE_H) $(GGC_H)
langhooks.h $(COVERAGE_H) \
- tree-iterator.h $(CGRAPH_H) gcov-io.c $(TM_P_H) \
+ tree-iterator.h $(CGRAPH_H) $(GCOV_IO_C) $(TM_P_H) \
$(DIAGNOSTIC_CORE_H) intl.h gt-coverage.h $(TARGET_H) $(HASH_TABLE_H)
cselib.o : cselib.c $(CONFIG_H) $(SYSTEM_H) coretypes.h dumpfile.h $(TM_H)
$(RTL_H) \
$(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h $(RECOG_H) \
@@ -4041,9 +4042,9 @@ s-iov: build/gcov-iov$(build_exeext) $(BASEVER)
$(DEVPHASE)
$(SHELL) $(srcdir)/../move-if-change tmp-gcov-iov.h gcov-iov.h
$(STAMP) s-iov
-gcov.o: gcov.c gcov-io.c $(GCOV_IO_H) intl.h $(SYSTEM_H) coretypes.h $(TM_H) \
+gcov.o: gcov.c $(GCOV_IO_C) $(GCOV_IO_H) intl.h $(SYSTEM_H) coretypes.h
$(TM_H) \
$(CONFIG_H) version.h $(DIAGNOSTIC_H)
-gcov-dump.o: gcov-dump.c gcov-io.c $(GCOV_IO_H) $(SYSTEM_H) coretypes.h \
+gcov-dump.o: gcov-dump.c $(GCOV_IO_C) $(GCOV_IO_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(CONFIG_H) version.h intl.h $(DIAGNOSTIC_H)
GCOV_OBJS = gcov.o
diff --git a/gcc/basic-block.h b/gcc/basic-block.h
index 03ba0ce..8262a99 100644
--- a/gcc/basic-block.h
+++ b/gcc/basic-block.h
@@ -63,9 +63,9 @@ struct GTY((user)) edge_def {
/* Garbage collection and PCH support for edge_def. */
-extern void gt_ggc_mx (edge_def *e);
-extern void gt_pch_nx (edge_def *e);
-extern void gt_pch_nx (edge_def *e, gt_pointer_operator, void *);
+extern void gt_ggc_mx (edge_def *& e);
+extern void gt_pch_nx (edge_def *& e);
+extern void gt_pch_nx (edge_def *& e, gt_pointer_operator, void *);
/* Masks for edge.flags. */
#define DEF_EDGE_FLAG(NAME,IDX) EDGE_##NAME = 1 << IDX ,
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 465fa0f..b9fce12 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -223,7 +223,7 @@ c-common.h, not after.
#define BOUND_TEMPLATE_TEMPLATE_PARM_TYPE_CHECK(NODE) \
TREE_CHECK(NODE,BOUND_TEMPLATE_TEMPLATE_PARM)
-#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 3004)
#define THUNK_FUNCTION_CHECK(NODE) __extension__ \
({ __typeof (NODE) const __t = (NODE);
\
if (TREE_CODE (__t) != FUNCTION_DECL || !__t->decl_common.lang_specific \
@@ -1437,7 +1437,7 @@ struct GTY((variable_size)) lang_type {
} GTY((desc ("%h.h.is_lang_type_class"))) u;
};
-#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 3004)
#define LANG_TYPE_CLASS_CHECK(NODE) __extension__ \
({ struct lang_type *lt = TYPE_LANG_SPECIFIC (NODE); \
@@ -2019,7 +2019,7 @@ struct GTY((variable_size)) lang_decl {
#define STRIP_TEMPLATE(NODE) \
(TREE_CODE (NODE) == TEMPLATE_DECL ? DECL_TEMPLATE_RESULT (NODE) : NODE)
-#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 3004)
#define LANG_DECL_MIN_CHECK(NODE) __extension__ \
({ struct lang_decl *lt = DECL_LANG_SPECIFIC (NODE); \
diff --git a/gcc/gcov-io.c b/gcc/gcov-io.c
index f45c32c..ec73aec 100644
--- a/gcc/gcov-io.c
+++ b/gcc/gcov-io.c
@@ -517,6 +517,17 @@ gcov_read_string (void)
}
#endif
+#if GCC_VERSION < 3004
+#define HWINT_STATIC(TYPE) static TYPE ATTRIBUTE_UNUSED
+#define HWINT_PREFIX(NAME) my_##NAME
+#include "hwint-helper.c"
+#undef HWINT_STATIC
+#undef HWINT_PREFIX
+#else
+# define my_popcount_hwi __builtin_popcountll
+# define my_clz_hwi __builtin_clzll
+#endif
+
GCOV_LINKAGE void
gcov_read_summary (struct gcov_summary *summary)
{
@@ -538,7 +549,7 @@ gcov_read_summary (struct gcov_summary *summary)
for (bv_ix = 0; bv_ix < GCOV_HISTOGRAM_BITVECTOR_SIZE; bv_ix++)
{
histo_bitvector[bv_ix] = gcov_read_unsigned ();
- h_cnt += __builtin_popcountll (histo_bitvector[bv_ix]);
+ h_cnt += my_popcount_hwi (histo_bitvector[bv_ix]);
}
bv_ix = 0;
h_ix = 0;
@@ -642,7 +653,7 @@ gcov_histo_index (gcov_type value)
/* Find the place of the most-significant bit set. */
if (v > 0)
- r = 63 - __builtin_clzll (v);
+ r = 63 - my_clz_hwi (v);
/* If at most the 2 least significant bits are set (value is
0 - 3) then that value is our index into the lowest set of
diff --git a/gcc/hwint-helper.c b/gcc/hwint-helper.c
new file mode 100644
index 0000000..2ece45a
--- /dev/null
+++ b/gcc/hwint-helper.c
@@ -0,0 +1,130 @@
+/* Supporting bit functions for older versions of GCC, and non-GCC
+ bootstrap compilers.
+
+ Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+ 2012 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+<http://www.gnu.org/licenses/>. */
+
+#if GCC_VERSION < 3004
+
+/* The functions clz_hwi, ctz_hwi, ffs_hwi, floor_log2, ceil_log2,
+ and exact_log2 are defined as inline functions in hwint.h
+ if GCC_VERSION >= 3004.
+ The definitions here are used for older versions of GCC and
+ non-GCC bootstrap compilers. */
+
+/* Given X, an unsigned number, return the largest int Y such that 2**Y <= X.
+ If X is 0, return -1. */
+
+HWINT_STATIC (int)
+HWINT_PREFIX (floor_log2) (unsigned HOST_WIDE_INT x)
+{
+ int t = 0;
+
+ if (x == 0)
+ return -1;
+
+ if (HOST_BITS_PER_WIDE_INT > 64)
+ if (x >= (unsigned HOST_WIDE_INT) 1 << (t + 64))
+ t += 64;
+ if (HOST_BITS_PER_WIDE_INT > 32)
+ if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 32))
+ t += 32;
+ if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 16))
+ t += 16;
+ if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 8))
+ t += 8;
+ if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 4))
+ t += 4;
+ if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 2))
+ t += 2;
+ if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 1))
+ t += 1;
+
+ return t;
+}
+
+/* Given X, an unsigned number, return the largest Y such that 2**Y >= X. */
+
+HWINT_STATIC (int)
+HWINT_PREFIX (ceil_log2) (unsigned HOST_WIDE_INT x)
+{
+ return HWINT_PREFIX (floor_log2) (x - 1) + 1;
+}
+
+/* Return the logarithm of X, base 2, considering X unsigned,
+ if X is a power of 2. Otherwise, returns -1. */
+
+HWINT_STATIC (int)
+HWINT_PREFIX (exact_log2) (unsigned HOST_WIDE_INT x)
+{
+ if (x != (x & -x))
+ return -1;
+ return HWINT_PREFIX (floor_log2) (x);
+}
+
+/* Given X, an unsigned number, return the number of least significant bits
+ that are zero. When X == 0, the result is the word size. */
+
+HWINT_STATIC (int)
+HWINT_PREFIX (ctz_hwi) (unsigned HOST_WIDE_INT x)
+{
+ return x ? HWINT_PREFIX (floor_log2) (x & -x) : HOST_BITS_PER_WIDE_INT;
+}
+
+/* Similarly for most significant bits. */
+
+HWINT_STATIC (int)
+HWINT_PREFIX (clz_hwi) (unsigned HOST_WIDE_INT x)
+{
+ return HOST_BITS_PER_WIDE_INT - 1 - HWINT_PREFIX (floor_log2) (x);
+}
+
+/* Similar to ctz_hwi, except that the least significant bit is numbered
+ starting from 1, and X == 0 yields 0. */
+
+HWINT_STATIC (int)
+HWINT_PREFIX (ffs_hwi) (unsigned HOST_WIDE_INT x)
+{
+ return 1 + HWINT_PREFIX (floor_log2) (x & -x);
+}
+
+/* Return the number of set bits in X. */
+
+HWINT_STATIC (int)
+HWINT_PREFIX (popcount_hwi) (unsigned HOST_WIDE_INT x)
+{
+ int i, ret = 0;
+ size_t bits = sizeof (x) * CHAR_BIT;
+
+ for (i = 0; i < bits; i += 1)
+ {
+ ret += x & 1;
+ x >>= 1;
+ }
+
+ return ret;
+}
+
+#endif /* GCC_VERSION < 3004 */
diff --git a/gcc/hwint.c b/gcc/hwint.c
index b7bcfa5..07447e1 100644
--- a/gcc/hwint.c
+++ b/gcc/hwint.c
@@ -23,108 +23,11 @@ along with GCC; see the file COPYING3. If not see
#include "system.h"
#include "diagnostic-core.h"
-#if GCC_VERSION < 3004
-
-/* The functions clz_hwi, ctz_hwi, ffs_hwi, floor_log2, ceil_log2,
- and exact_log2 are defined as inline functions in hwint.h
- if GCC_VERSION >= 3004.
- The definitions here are used for older versions of GCC and
- non-GCC bootstrap compilers. */
-
-/* Given X, an unsigned number, return the largest int Y such that 2**Y <= X.
- If X is 0, return -1. */
-
-int
-floor_log2 (unsigned HOST_WIDE_INT x)
-{
- int t = 0;
-
- if (x == 0)
- return -1;
-
- if (HOST_BITS_PER_WIDE_INT > 64)
- if (x >= (unsigned HOST_WIDE_INT) 1 << (t + 64))
- t += 64;
- if (HOST_BITS_PER_WIDE_INT > 32)
- if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 32))
- t += 32;
- if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 16))
- t += 16;
- if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 8))
- t += 8;
- if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 4))
- t += 4;
- if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 2))
- t += 2;
- if (x >= ((unsigned HOST_WIDE_INT) 1) << (t + 1))
- t += 1;
-
- return t;
-}
-
-/* Given X, an unsigned number, return the largest Y such that 2**Y >= X. */
-
-int
-ceil_log2 (unsigned HOST_WIDE_INT x)
-{
- return floor_log2 (x - 1) + 1;
-}
-
-/* Return the logarithm of X, base 2, considering X unsigned,
- if X is a power of 2. Otherwise, returns -1. */
-
-int
-exact_log2 (unsigned HOST_WIDE_INT x)
-{
- if (x != (x & -x))
- return -1;
- return floor_log2 (x);
-}
-
-/* Given X, an unsigned number, return the number of least significant bits
- that are zero. When X == 0, the result is the word size. */
-
-int
-ctz_hwi (unsigned HOST_WIDE_INT x)
-{
- return x ? floor_log2 (x & -x) : HOST_BITS_PER_WIDE_INT;
-}
-
-/* Similarly for most significant bits. */
-
-int
-clz_hwi (unsigned HOST_WIDE_INT x)
-{
- return HOST_BITS_PER_WIDE_INT - 1 - floor_log2(x);
-}
-
-/* Similar to ctz_hwi, except that the least significant bit is numbered
- starting from 1, and X == 0 yields 0. */
-
-int
-ffs_hwi (unsigned HOST_WIDE_INT x)
-{
- return 1 + floor_log2 (x & -x);
-}
-
-/* Return the number of set bits in X. */
-
-int
-popcount_hwi (unsigned HOST_WIDE_INT x)
-{
- int i, ret = 0;
- size_t bits = sizeof (x) * CHAR_BIT;
-
- for (i = 0; i < bits; i += 1)
- {
- ret += x & 1;
- x >>= 1;
- }
-
- return ret;
-}
-
-#endif /* GCC_VERSION < 3004 */
+#define HWINT_STATIC(TYPE) TYPE
+#define HWINT_PREFIX(NAME) NAME
+#include "hwint-helper.c"
+#undef HWINT_STATIC
+#undef HWINT_PREFIX
/* Compute the absolute value of X. */
diff --git a/gcc/tree-ssa-coalesce.c b/gcc/tree-ssa-coalesce.c
index ce04fdf..47eba97 100644
--- a/gcc/tree-ssa-coalesce.c
+++ b/gcc/tree-ssa-coalesce.c
@@ -1259,7 +1259,7 @@ coalesce_partitions (var_map map, ssa_conflicts_p graph,
coalesce_list_p cl,
/* Hashtable support for storing SSA names hashed by their SSA_NAME_VAR. */
-struct ssa_name_var_hash : typed_noop_remove <union tree_node>
+struct ssa_name_var_hash : typed_noop_remove <tree_node>
{
typedef union tree_node value_type;
typedef union tree_node compare_type;
diff --git a/gcc/tree.h b/gcc/tree.h
index 9f17253..ec5cf94 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -743,7 +743,7 @@ enum tree_node_structure_enum {
/* When checking is enabled, errors will be generated if a tree node
is accessed incorrectly. The macros die with a fatal error. */
-#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 3004)
#define TREE_CHECK(T, CODE) \
(tree_check ((T), __FILE__, __LINE__, __FUNCTION__, (CODE)))
@@ -3662,7 +3662,7 @@ union GTY ((ptr_alias (union lang_tree_node),
struct tree_target_option GTY ((tag ("TS_TARGET_OPTION"))) target_option;
};
-#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 3004)
inline tree
tree_check (tree __t, const char *__f, int __l, const char *__g, tree_code __c)
@@ -4094,7 +4094,7 @@ tree_operand_length (const_tree node)
return TREE_CODE_LENGTH (TREE_CODE (node));
}
-#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 3004)
/* Special checks for TREE_OPERANDs. */
inline tree *
diff --git a/include/ansidecl.h b/include/ansidecl.h
index 23d85bf..e67123d 100644
--- a/include/ansidecl.h
+++ b/include/ansidecl.h
@@ -280,7 +280,11 @@ So instead we use the macro below and test it against
specific values. */
#endif
#ifndef ATTRIBUTE_UNUSED
-#define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+#if GCC_VERSION >= 3004
+# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+#else
+#define ATTRIBUTE_UNUSED
+#endif
#endif /* ATTRIBUTE_UNUSED */
/* Before GCC 3.4, the C++ frontend couldn't parse attributes placed after the