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

Reply via email to