On 12-05-17 10:52 , Michael Matz wrote:

Cross the bridge when you reach it, not before.  Not everybody agrees that
the splitting of tree would be a good idea.  Right now templates aren't
necessary, so you shouldn't use them.  (well, and an investigation why
they come up with smaller .text would be in order anyway).

I've been playing around with this patch a little bit. The main motivation for using templates here is to preserve the existing semantics. Note that the return type from the function mimics the type of the argument passed in. So, if the user passes a const_tree, the function returns a const_tree.

The way to do this in C++ is to: (a) use templates (as in Lawrence's patch), or (b) produce overloaded variants for tree and const_tree.

For trunk, we have a third option: (c) make these functions out-of-line functions that take const_tree and return tree. This slightly weakens the semantics of the checks, but it does not rely on C++ features.

Options (a) or (b) are the same to me. Option (b) has the slight advantage that the code can be taken out of tree.h and buried in tree.c.

The attached patch implements option (c). Should we consider this for trunk now and then just replace the CONST_CAST_TREE into C++ overloads?


Thanks.  Diego.


2012-05-17  Lawrence Crowl  <cr...@google.com>

        * tree.h (tree_check): Declare.
        (TREE_CHECK): Use function above instead of __extension__.
        (tree_not_check): Declare.
        (TREE_NOT_CHECK): Use function above instead of __extension__.
        (tree_check2): Declare.
        (TREE_CHECK2): Use function above instead of __extension__.
        (tree_not_check2): Declare.
        (TREE_NOT_CHECK2): Use function above instead of __extension__.
        (tree_check3): Declare.
        (TREE_CHECK3): Use function above instead of __extension__.
        (tree_not_check3): Declare.
        (TREE_NOT_CHECK3): Use function above instead of __extension__.
        (tree_check4): Declare.
        (TREE_CHECK4): Use function above instead of __extension__.
        (tree_not_check4): Declare.
        (TREE_NOT_CHECK4): Use function above instead of __extension__.
        (tree_check5): Declare.
        (TREE_CHECK5): Use function above instead of __extension__.
        (tree_not_check5): Declare.
        (TREE_NOT_CHECK5): Use function above instead of __extension__.
        (contains_struct_check): Declare.
        (CONTAINS_STRUCT_CHECK): Use function above instead of
        __extension__.
        (tree_class_check): Declare.
        (TREE_CLASS_CHECK): Use function above instead of __extension__.
        (tree_range_check): Declare.
        (TREE_RANGE_CHECK): Use function above instead of __extension__.
        (omp_clause_subcode_check): Declare.
        (OMP_CLAUSE_SUBCODE_CHECK): Use function above instead of
        __extension__.
        (omp_clause_range_check): Declare.
        (OMP_CLAUSE_RANGE_CHECK): Use function above instead of
        __extension__.
        (expr_check): Declare.
        (EXPR_CHECK): Use function above instead of __extension__.
        (non_type_check): Declare.
        (NON_TYPE_CHECK): Use function above instead of __extension__.
        (tree_vec_elt_check): Declare.
        (TREE_VEC_ELT_CHECK): Use function above instead of
        __extension__.
        (omp_clause_elt_check): Declare.
        (OMP_CLAUSE_ELT_CHECK): Use function above instead of
        __extension__.
        (tree_operand_check): Declare.
        (TREE_OPERAND_CHECK): Use function above instead of
        __extension__.
        (tree_operand_check_code): Declare.
        (TREE_OPERAND_CHECK_CODE): Use function above instead of
        __extension__.
        (TREE_CHAIN): Simplify implementation.
        (TREE_TYPE): Simplify implementation.
        (tree_operand_length): Move for compilation dependences.
        * tree.c (tree_check): New.
        (tree_not_check): New.
        (tree_check2): New.
        (tree_not_check2): New.
        (tree_check3): New.
        (tree_not_check3): New.
        (tree_check4): New.
        (tree_not_check4): New.
        (tree_check5): New.
        (tree_not_check5): New.
        (contains_struct_check): New.
        (tree_range_check): New.
        (omp_clause_subcode_check): New.
        (omp_clause_range_check): New.
        (expr_check): New.
        (non_type_check): New.
        (tree_vec_elt_check): New.
        (omp_clause_elt_check): New.
        (tree_operand_check): New.
        (tree_operand_check_code): New.
        * gdbinit.in: (macro define __FILE__): New.
        (macro define __LINE__): New.
        (skip "tree.h"): New.
2012-05-17  Lawrence Crowl  <cr...@google.com>

        * tree.h (tree_check): Declare.
        (TREE_CHECK): Use function above instead of __extension__.
        (tree_not_check): Declare.
        (TREE_NOT_CHECK): Use function above instead of __extension__.
        (tree_check2): Declare.
        (TREE_CHECK2): Use function above instead of __extension__.
        (tree_not_check2): Declare.
        (TREE_NOT_CHECK2): Use function above instead of __extension__.
        (tree_check3): Declare.
        (TREE_CHECK3): Use function above instead of __extension__.
        (tree_not_check3): Declare.
        (TREE_NOT_CHECK3): Use function above instead of __extension__.
        (tree_check4): Declare.
        (TREE_CHECK4): Use function above instead of __extension__.
        (tree_not_check4): Declare.
        (TREE_NOT_CHECK4): Use function above instead of __extension__.
        (tree_check5): Declare.
        (TREE_CHECK5): Use function above instead of __extension__.
        (tree_not_check5): Declare.
        (TREE_NOT_CHECK5): Use function above instead of __extension__.
        (contains_struct_check): Declare.
        (CONTAINS_STRUCT_CHECK): Use function above instead of
        __extension__.
        (tree_class_check): Declare.
        (TREE_CLASS_CHECK): Use function above instead of __extension__.
        (tree_range_check): Declare.
        (TREE_RANGE_CHECK): Use function above instead of __extension__.
        (omp_clause_subcode_check): Declare.
        (OMP_CLAUSE_SUBCODE_CHECK): Use function above instead of
        __extension__.
        (omp_clause_range_check): Declare.
        (OMP_CLAUSE_RANGE_CHECK): Use function above instead of
        __extension__.
        (expr_check): Declare.
        (EXPR_CHECK): Use function above instead of __extension__.
        (non_type_check): Declare.
        (NON_TYPE_CHECK): Use function above instead of __extension__.
        (tree_vec_elt_check): Declare.
        (TREE_VEC_ELT_CHECK): Use function above instead of
        __extension__.
        (omp_clause_elt_check): Declare.
        (OMP_CLAUSE_ELT_CHECK): Use function above instead of
        __extension__.
        (tree_operand_check): Declare.
        (TREE_OPERAND_CHECK): Use function above instead of
        __extension__.
        (tree_operand_check_code): Declare.
        (TREE_OPERAND_CHECK_CODE): Use function above instead of
        __extension__.
        (TREE_CHAIN): Simplify implementation.
        (TREE_TYPE): Simplify implementation.
        (tree_operand_length): Move for compilation dependences.
        * tree.c (tree_check): New.
        (tree_not_check): New.
        (tree_check2): New.
        (tree_not_check2): New.
        (tree_check3): New.
        (tree_not_check3): New.
        (tree_check4): New.
        (tree_not_check4): New.
        (tree_check5): New.
        (tree_not_check5): New.
        (contains_struct_check): New.
        (tree_class_check): New.
        (tree_range_check): New.
        (omp_clause_subcode_check): New.
        (omp_clause_range_check): New.
        (expr_check): New.
        (non_type_check): New.
        (tree_vec_elt_check): New.
        (omp_clause_elt_check): New.
        (tree_operand_check): New.
        (tree_operand_check_code): New.
        * gdbinit.in: (macro define __FILE__): New.
        (macro define __LINE__): New.
        (skip "tree.h"): New.

Index: tree.h
===================================================================
--- tree.h      (revision 187471)
+++ tree.h      (working copy)
@@ -727,195 +727,80 @@
    is accessed incorrectly. The macros die with a fatal error.  */
 #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
 
-#define TREE_CHECK(T, CODE) __extension__                              \
-({  __typeof (T) const __t = (T);                                      \
-    if (TREE_CODE (__t) != (CODE))                                     \
-      tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__,        \
-                        (CODE), 0);                                    \
-    __t; })
+#define TREE_CHECK(T, CODE) \
+(tree_check ((T), __FILE__, __LINE__, __FUNCTION__, (CODE)))
 
-#define TREE_NOT_CHECK(T, CODE) __extension__                          \
-({  __typeof (T) const __t = (T);                                      \
-    if (TREE_CODE (__t) == (CODE))                                     \
-      tree_not_check_failed (__t, __FILE__, __LINE__, __FUNCTION__,    \
-                            (CODE), 0);                                \
-    __t; })
+#define TREE_NOT_CHECK(T, CODE) \
+(tree_not_check ((T), __FILE__, __LINE__, __FUNCTION__, (CODE)))
 
-#define TREE_CHECK2(T, CODE1, CODE2) __extension__                     \
-({  __typeof (T) const __t = (T);                                      \
-    if (TREE_CODE (__t) != (CODE1)                                     \
-       && TREE_CODE (__t) != (CODE2))                                  \
-      tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__,                
\
-                        (CODE1), (CODE2), 0);                          \
-    __t; })
+#define TREE_CHECK2(T, CODE1, CODE2) \
+(tree_check2 ((T), __FILE__, __LINE__, __FUNCTION__, (CODE1), (CODE2)))
 
-#define TREE_NOT_CHECK2(T, CODE1, CODE2) __extension__                 \
-({  __typeof (T) const __t = (T);                                      \
-    if (TREE_CODE (__t) == (CODE1)                                     \
-       || TREE_CODE (__t) == (CODE2))                                  \
-      tree_not_check_failed (__t, __FILE__, __LINE__, __FUNCTION__,    \
-                            (CODE1), (CODE2), 0);                      \
-    __t; })
+#define TREE_NOT_CHECK2(T, CODE1, CODE2) \
+(tree_not_check2 ((T), __FILE__, __LINE__, __FUNCTION__, (CODE1), (CODE2)))
 
-#define TREE_CHECK3(T, CODE1, CODE2, CODE3) __extension__              \
-({  __typeof (T) const __t = (T);                                      \
-    if (TREE_CODE (__t) != (CODE1)                                     \
-       && TREE_CODE (__t) != (CODE2)                                   \
-       && TREE_CODE (__t) != (CODE3))                                  \
-      tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__,                
\
-                            (CODE1), (CODE2), (CODE3), 0);             \
-    __t; })
+#define TREE_CHECK3(T, CODE1, CODE2, CODE3) \
+(tree_check3 ((T), __FILE__, __LINE__, __FUNCTION__, (CODE1), (CODE2), 
(CODE3)))
 
-#define TREE_NOT_CHECK3(T, CODE1, CODE2, CODE3) __extension__          \
-({  __typeof (T) const __t = (T);                                      \
-    if (TREE_CODE (__t) == (CODE1)                                     \
-       || TREE_CODE (__t) == (CODE2)                                   \
-       || TREE_CODE (__t) == (CODE3))                                  \
-      tree_not_check_failed (__t, __FILE__, __LINE__, __FUNCTION__,    \
-                            (CODE1), (CODE2), (CODE3), 0);             \
-    __t; })
+#define TREE_NOT_CHECK3(T, CODE1, CODE2, CODE3) \
+(tree_not_check3 ((T), __FILE__, __LINE__, __FUNCTION__, \
+                               (CODE1), (CODE2), (CODE3)))
 
-#define TREE_CHECK4(T, CODE1, CODE2, CODE3, CODE4) __extension__       \
-({  __typeof (T) const __t = (T);                                      \
-    if (TREE_CODE (__t) != (CODE1)                                     \
-       && TREE_CODE (__t) != (CODE2)                                   \
-       && TREE_CODE (__t) != (CODE3)                                   \
-       && TREE_CODE (__t) != (CODE4))                                  \
-      tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__,                
\
-                            (CODE1), (CODE2), (CODE3), (CODE4), 0);    \
-    __t; })
+#define TREE_CHECK4(T, CODE1, CODE2, CODE3, CODE4) \
+(tree_check4 ((T), __FILE__, __LINE__, __FUNCTION__, \
+                           (CODE1), (CODE2), (CODE3), (CODE4)))
 
-#define TREE_NOT_CHECK4(T, CODE1, CODE2, CODE3, CODE4) __extension__   \
-({  __typeof (T) const __t = (T);                                      \
-    if (TREE_CODE (__t) == (CODE1)                                     \
-       || TREE_CODE (__t) == (CODE2)                                   \
-       || TREE_CODE (__t) == (CODE3)                                   \
-       || TREE_CODE (__t) == (CODE4))                                  \
-      tree_not_check_failed (__t, __FILE__, __LINE__, __FUNCTION__,    \
-                            (CODE1), (CODE2), (CODE3), (CODE4), 0);    \
-    __t; })
+#define TREE_NOT_CHECK4(T, CODE1, CODE2, CODE3, CODE4) \
+(tree_not_check4 ((T), __FILE__, __LINE__, __FUNCTION__, \
+                               (CODE1), (CODE2), (CODE3), (CODE4)))
 
-#define TREE_CHECK5(T, CODE1, CODE2, CODE3, CODE4, CODE5) __extension__        
\
-({  __typeof (T) const __t = (T);                                      \
-    if (TREE_CODE (__t) != (CODE1)                                     \
-       && TREE_CODE (__t) != (CODE2)                                   \
-       && TREE_CODE (__t) != (CODE3)                                   \
-       && TREE_CODE (__t) != (CODE4)                                   \
-       && TREE_CODE (__t) != (CODE5))                                  \
-      tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__,                
\
-                            (CODE1), (CODE2), (CODE3), (CODE4), (CODE5), 0);\
-    __t; })
+#define TREE_CHECK5(T, CODE1, CODE2, CODE3, CODE4, CODE5) \
+(tree_check5 ((T), __FILE__, __LINE__, __FUNCTION__, \
+                           (CODE1), (CODE2), (CODE3), (CODE4), (CODE5)))
 
-#define TREE_NOT_CHECK5(T, CODE1, CODE2, CODE3, CODE4, CODE5) __extension__ \
-({  __typeof (T) const __t = (T);                                      \
-    if (TREE_CODE (__t) == (CODE1)                                     \
-       || TREE_CODE (__t) == (CODE2)                                   \
-       || TREE_CODE (__t) == (CODE3)                                   \
-       || TREE_CODE (__t) == (CODE4)                                   \
-       || TREE_CODE (__t) == (CODE5))                                  \
-      tree_not_check_failed (__t, __FILE__, __LINE__, __FUNCTION__,    \
-                            (CODE1), (CODE2), (CODE3), (CODE4), (CODE5), 0);\
-    __t; })
+#define TREE_NOT_CHECK5(T, CODE1, CODE2, CODE3, CODE4, CODE5) \
+(tree_not_check5 ((T), __FILE__, __LINE__, __FUNCTION__, \
+                               (CODE1), (CODE2), (CODE3), (CODE4), (CODE5)))
 
-#define CONTAINS_STRUCT_CHECK(T, STRUCT) __extension__                 \
-({  __typeof (T) const __t = (T);                                      \
-  if (tree_contains_struct[TREE_CODE(__t)][(STRUCT)] != 1)             \
-      tree_contains_struct_check_failed (__t, (STRUCT), __FILE__, __LINE__,    
\
-                              __FUNCTION__);                           \
-    __t; })
+#define CONTAINS_STRUCT_CHECK(T, STRUCT) \
+(contains_struct_check ((T), (STRUCT), __FILE__, __LINE__, __FUNCTION__))
 
-#define TREE_CLASS_CHECK(T, CLASS) __extension__                       \
-({  __typeof (T) const __t = (T);                                      \
-    if (TREE_CODE_CLASS (TREE_CODE(__t)) != (CLASS))                   \
-      tree_class_check_failed (__t, (CLASS), __FILE__, __LINE__,       \
-                              __FUNCTION__);                           \
-    __t; })
+#define TREE_CLASS_CHECK(T, CLASS) \
+(tree_class_check ((T), (CLASS), __FILE__, __LINE__, __FUNCTION__))
 
-#define TREE_RANGE_CHECK(T, CODE1, CODE2) __extension__                        
\
-({  __typeof (T) const __t = (T);                                      \
-    if (TREE_CODE (__t) < (CODE1) || TREE_CODE (__t) > (CODE2))                
\
-      tree_range_check_failed (__t, __FILE__, __LINE__, __FUNCTION__,  \
-                              (CODE1), (CODE2));                       \
-    __t; })
+#define TREE_RANGE_CHECK(T, CODE1, CODE2) \
+(tree_range_check ((T), (CODE1), (CODE2), __FILE__, __LINE__, __FUNCTION__))
 
-#define OMP_CLAUSE_SUBCODE_CHECK(T, CODE) __extension__                        
\
-({  __typeof (T) const __t = (T);                                      \
-    if (TREE_CODE (__t) != OMP_CLAUSE)                                 \
-      tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__,        \
-                        OMP_CLAUSE, 0);                                \
-    if (__t->omp_clause.code != (CODE))                                        
\
-      omp_clause_check_failed (__t, __FILE__, __LINE__, __FUNCTION__,  \
-                              (CODE));                                 \
-    __t; })
+#define OMP_CLAUSE_SUBCODE_CHECK(T, CODE) \
+(omp_clause_subcode_check ((T), (CODE), __FILE__, __LINE__, __FUNCTION__))
 
-#define OMP_CLAUSE_RANGE_CHECK(T, CODE1, CODE2) __extension__          \
-({  __typeof (T) const __t = (T);                                      \
-    if (TREE_CODE (__t) != OMP_CLAUSE)                                 \
-      tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__,        \
-                        OMP_CLAUSE, 0);                                \
-    if ((int) __t->omp_clause.code < (int) (CODE1)                     \
-        || (int) __t->omp_clause.code > (int) (CODE2))                 \
-      omp_clause_range_check_failed (__t, __FILE__, __LINE__,          \
-                                    __FUNCTION__, (CODE1), (CODE2));   \
-    __t; })
+#define OMP_CLAUSE_RANGE_CHECK(T, CODE1, CODE2) \
+(omp_clause_range_check ((T), (CODE1), (CODE2), \
+                                      __FILE__, __LINE__, __FUNCTION__))
 
 /* These checks have to be special cased.  */
-#define EXPR_CHECK(T) __extension__                                    \
-({  __typeof (T) const __t = (T);                                      \
-    char const __c = TREE_CODE_CLASS (TREE_CODE (__t));                        
\
-    if (!IS_EXPR_CODE_CLASS (__c))                                     \
-      tree_class_check_failed (__t, tcc_expression, __FILE__, __LINE__,        
\
-                              __FUNCTION__);                           \
-    __t; })
+#define EXPR_CHECK(T) \
+(expr_check ((T), __FILE__, __LINE__, __FUNCTION__))
 
 /* These checks have to be special cased.  */
-#define NON_TYPE_CHECK(T) __extension__                                        
\
-({  __typeof (T) const __t = (T);                                      \
-    if (TYPE_P (__t))                                                  \
-      tree_not_class_check_failed (__t, tcc_type, __FILE__, __LINE__,  \
-                                  __FUNCTION__);                       \
-    __t; })
+#define NON_TYPE_CHECK(T) \
+(non_type_check ((T), __FILE__, __LINE__, __FUNCTION__))
 
-#define TREE_VEC_ELT_CHECK(T, I) __extension__                         \
-(*({__typeof (T) const __t = (T);                                      \
-    const int __i = (I);                                               \
-    if (TREE_CODE (__t) != TREE_VEC)                                   \
-      tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__,                
\
-                        TREE_VEC, 0);                                  \
-    if (__i < 0 || __i >= __t->vec.length)                             \
-      tree_vec_elt_check_failed (__i, __t->vec.length,                 \
-                                __FILE__, __LINE__, __FUNCTION__);     \
-    &__t->vec.a[__i]; }))
+#define TREE_VEC_ELT_CHECK(T, I) \
+(*(CONST_CAST2 (tree *, typeof (T)*, \
+     tree_vec_elt_check ((T), (I), __FILE__, __LINE__, __FUNCTION__))))
 
-#define OMP_CLAUSE_ELT_CHECK(T, I) __extension__                       \
-(*({__typeof (T) const __t = (T);                                      \
-    const int __i = (I);                                               \
-    if (TREE_CODE (__t) != OMP_CLAUSE)                                 \
-      tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__,        \
-                        OMP_CLAUSE, 0);                                \
-    if (__i < 0 || __i >= omp_clause_num_ops [__t->omp_clause.code])   \
-      omp_clause_operand_check_failed (__i, __t, __FILE__, __LINE__,   \
-                                      __FUNCTION__);                   \
-    &__t->omp_clause.ops[__i]; }))
+#define OMP_CLAUSE_ELT_CHECK(T, I) \
+(*(omp_clause_elt_check ((T), (I), __FILE__, __LINE__, __FUNCTION__)))
 
 /* Special checks for TREE_OPERANDs.  */
-#define TREE_OPERAND_CHECK(T, I) __extension__                         \
-(*({__typeof (T) const __t = EXPR_CHECK (T);                           \
-    const int __i = (I);                                               \
-    if (__i < 0 || __i >= TREE_OPERAND_LENGTH (__t))                   \
-      tree_operand_check_failed (__i, __t,                             \
-                                __FILE__, __LINE__, __FUNCTION__);     \
-    &__t->exp.operands[__i]; }))
+#define TREE_OPERAND_CHECK(T, I) \
+(*(CONST_CAST2 (tree*, typeof (T)*, \
+     tree_operand_check ((T), (I), __FILE__, __LINE__, __FUNCTION__))))
 
-#define TREE_OPERAND_CHECK_CODE(T, CODE, I) __extension__              \
-(*({__typeof (T) const __t = (T);                                      \
-    const int __i = (I);                                               \
-    if (TREE_CODE (__t) != CODE)                                       \
-      tree_check_failed (__t, __FILE__, __LINE__, __FUNCTION__, (CODE), 0);\
-    if (__i < 0 || __i >= TREE_OPERAND_LENGTH (__t))                   \
-      tree_operand_check_failed (__i, __t,                             \
-                                __FILE__, __LINE__, __FUNCTION__);     \
-    &__t->exp.operands[__i]; }))
+#define TREE_OPERAND_CHECK_CODE(T, CODE, I) \
+(*(tree_operand_check_code ((T), (CODE), (I), \
+                                         __FILE__, __LINE__, __FUNCTION__)))
 
 /* Nodes are chained together for many purposes.
    Types are chained together to record them for being output to the debugger
@@ -926,17 +811,15 @@
    Often lists of things are represented by TREE_LIST nodes that
    are chained together.  */
 
-#define TREE_CHAIN(NODE) __extension__ \
-(*({__typeof (NODE) const __t = CONTAINS_STRUCT_CHECK (NODE, TS_COMMON);\
-    &__t->common.chain; }))
+#define TREE_CHAIN(NODE) \
+(CONTAINS_STRUCT_CHECK (NODE, TS_COMMON)->common.chain)
 
 /* In all nodes that are expressions, this is the data type of the expression.
    In POINTER_TYPE nodes, this is the type that the pointer points to.
    In ARRAY_TYPE nodes, this is the type of the elements.
    In VECTOR_TYPE nodes, this is the type of the elements.  */
-#define TREE_TYPE(NODE) __extension__ \
-(*({__typeof (NODE) const __t = CONTAINS_STRUCT_CHECK (NODE, TS_TYPED); \
-    &__t->typed.type; }))
+#define TREE_TYPE(NODE) \
+(CONTAINS_STRUCT_CHECK (NODE, TS_TYPED)->typed.type)
 
 extern void tree_contains_struct_check_failed (const_tree,
                                               const enum 
tree_node_structure_enum,
@@ -3718,6 +3601,52 @@
   struct tree_optimization_option GTY ((tag ("TS_OPTIMIZATION"))) optimization;
   struct tree_target_option GTY ((tag ("TS_TARGET_OPTION"))) target_option;
 };
+
+
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
+
+tree tree_check (const_tree, const char *, int, const char *, enum tree_code);
+tree tree_not_check (const_tree, const char *, int, const char *,
+                    enum tree_code);
+tree tree_check2 (const_tree, const char *, int, const char *, enum tree_code,
+                 enum tree_code);
+tree tree_not_check2 (const_tree, const char *, int, const char *,
+                     enum tree_code, enum tree_code);
+tree tree_check3 (const_tree, const char *, int, const char *,
+                 enum tree_code, enum tree_code, enum tree_code);
+tree tree_not_check3 (const_tree, const char *, int, const char *,
+                     enum tree_code, enum tree_code, enum tree_code);
+tree tree_check4 (const_tree, const char *, int, const char *,
+                 enum tree_code, enum tree_code, enum tree_code,
+                 enum tree_code);
+tree tree_not_check4 (const_tree, const char *, int, const char *,
+                     enum tree_code, enum tree_code, enum tree_code,
+                     enum tree_code);
+tree tree_check5 (const_tree, const char *, int, const char *,
+                 enum tree_code, enum tree_code, enum tree_code,
+                 enum tree_code, enum tree_code);
+tree tree_not_check5 (const_tree, const char *, int, const char *,
+                     enum tree_code, enum tree_code, enum tree_code,
+                     enum tree_code, enum tree_code);
+tree contains_struct_check (const_tree, const enum tree_node_structure_enum,
+                           const char *, int, const char *);
+tree tree_class_check (const_tree, const enum tree_code_class, const char *,
+                      int, const char *);
+tree tree_range_check (const_tree, enum tree_code, enum tree_code,
+                      const char *, int, const char *);
+tree omp_clause_subcode_check (const_tree, enum omp_clause_code,
+                               const char *, int, const char *);
+tree omp_clause_range_check (const_tree, enum omp_clause_code,
+                            enum omp_clause_code, const char *, int,
+                            const char *);
+tree expr_check (const_tree, const char *, int, const char *);
+tree non_type_check (const_tree, const char *, int, const char *);
+tree *tree_vec_elt_check (const_tree, int, const char *, int, const char *);
+tree *omp_clause_elt_check (const_tree, int, const char *, int, const char *);
+tree *tree_operand_check (const_tree, int, const char *, int, const char *);
+tree *tree_operand_check_code (const_tree, enum tree_code, int, const char *,
+                              int, const char *);
+#endif
 
 /* Standard named or nameless data types of the C compiler.  */
 
Index: gdbinit.in
===================================================================
--- gdbinit.in  (revision 187471)
+++ gdbinit.in  (working copy)
@@ -182,6 +182,14 @@
 Dump the bitmap that is in $ as a comma-separated list of numbers.
 end
 
+# Define some macros helpful to gdb when it is expanding macros.
+macro define __FILE__ "gdb"
+macro define __LINE__ 1
+
+# Skip all inline functions in tree.h.
+# These are used in accessor macros.
+skip "tree.h"
+
 # Put breakpoints at exit and fancy_abort in case abort is mapped
 # to either fprintf/exit or fancy_abort.
 b fancy_abort
Index: tree.c
===================================================================
--- tree.c      (revision 187616)
+++ tree.c      (working copy)
@@ -11495,4 +11495,238 @@
     }
 }
 
+#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
+/* Tree checking routines.  */
+
+tree
+tree_check (const_tree __t, const char *__f, int __l, const char *__g, 
tree_code __c)
+{
+  if (TREE_CODE (__t) != __c)
+    tree_check_failed (__t, __f, __l, __g, __c, 0);
+  return CONST_CAST_TREE (__t);
+}
+
+tree
+tree_not_check (const_tree __t, const char *__f, int __l, const char *__g,
+                enum tree_code __c)
+{
+  if (TREE_CODE (__t) == __c)
+    tree_not_check_failed (__t, __f, __l, __g, __c, 0);
+  return CONST_CAST_TREE (__t);
+}
+
+tree
+tree_check2 (const_tree __t, const char *__f, int __l, const char *__g,
+             enum tree_code __c1, enum tree_code __c2)
+{
+  if (TREE_CODE (__t) != __c1
+      && TREE_CODE (__t) != __c2)
+    tree_check_failed (__t, __f, __l, __g, __c1, __c2, 0);
+  return CONST_CAST_TREE (__t);
+}
+
+tree
+tree_not_check2 (const_tree __t, const char *__f, int __l, const char *__g,
+                 enum tree_code __c1, enum tree_code __c2)
+{
+  if (TREE_CODE (__t) == __c1
+      || TREE_CODE (__t) == __c2)
+    tree_not_check_failed (__t, __f, __l, __g, __c1, __c2, 0);
+  return CONST_CAST_TREE (__t);
+}
+
+tree
+tree_check3 (const_tree __t, const char *__f, int __l, const char *__g,
+             enum tree_code __c1, enum tree_code __c2, enum tree_code __c3)
+{
+  if (TREE_CODE (__t) != __c1
+      && TREE_CODE (__t) != __c2
+      && TREE_CODE (__t) != __c3)
+    tree_check_failed (__t, __f, __l, __g, __c1, __c2, __c3, 0);
+  return CONST_CAST_TREE (__t);
+}
+
+tree
+tree_not_check3 (const_tree __t, const char *__f, int __l, const char *__g,
+                 enum tree_code __c1, enum tree_code __c2, enum tree_code __c3)
+{
+  if (TREE_CODE (__t) == __c1
+      || TREE_CODE (__t) == __c2
+      || TREE_CODE (__t) == __c3)
+    tree_not_check_failed (__t, __f, __l, __g, __c1, __c2, __c3, 0);
+  return CONST_CAST_TREE (__t);
+}
+
+tree
+tree_check4 (const_tree __t, const char *__f, int __l, const char *__g,
+             enum tree_code __c1, enum tree_code __c2, enum tree_code __c3,
+             enum tree_code __c4)
+{
+  if (TREE_CODE (__t) != __c1
+      && TREE_CODE (__t) != __c2
+      && TREE_CODE (__t) != __c3
+      && TREE_CODE (__t) != __c4)
+    tree_check_failed (__t, __f, __l, __g, __c1, __c2, __c3, __c4, 0);
+  return CONST_CAST_TREE (__t);
+}
+
+tree
+tree_not_check4 (const_tree __t, const char *__f, int __l, const char *__g,
+                 enum tree_code __c1, enum tree_code __c2, enum tree_code __c3,
+                 enum tree_code __c4)
+{
+  if (TREE_CODE (__t) == __c1
+      || TREE_CODE (__t) == __c2
+      || TREE_CODE (__t) == __c3
+      || TREE_CODE (__t) == __c4)
+    tree_not_check_failed (__t, __f, __l, __g, __c1, __c2, __c3, __c4, 0);
+  return CONST_CAST_TREE (__t);
+}
+
+tree
+tree_check5 (const_tree __t, const char *__f, int __l, const char *__g,
+             enum tree_code __c1, enum tree_code __c2, enum tree_code __c3,
+             enum tree_code __c4, enum tree_code __c5)
+{
+  if (TREE_CODE (__t) != __c1
+      && TREE_CODE (__t) != __c2
+      && TREE_CODE (__t) != __c3
+      && TREE_CODE (__t) != __c4
+      && TREE_CODE (__t) != __c5)
+    tree_check_failed (__t, __f, __l, __g, __c1, __c2, __c3, __c4, __c5, 0);
+  return CONST_CAST_TREE (__t);
+}
+
+tree
+tree_not_check5 (const_tree __t, const char *__f, int __l, const char *__g,
+                 enum tree_code __c1, enum tree_code __c2, enum tree_code __c3,
+                 enum tree_code __c4, enum tree_code __c5)
+{
+  if (TREE_CODE (__t) == __c1
+      || TREE_CODE (__t) == __c2
+      || TREE_CODE (__t) == __c3
+      || TREE_CODE (__t) == __c4
+      || TREE_CODE (__t) == __c5)
+    tree_not_check_failed (__t, __f, __l, __g, __c1, __c2, __c3, __c4, __c5, 
0);
+  return CONST_CAST_TREE (__t);
+}
+
+tree
+contains_struct_check (const_tree __t, const enum tree_node_structure_enum __s,
+                       const char *__f, int __l, const char *__g)
+{
+  if (tree_contains_struct[TREE_CODE(__t)][__s] != 1)
+      tree_contains_struct_check_failed (__t, __s, __f, __l, __g);
+  return CONST_CAST_TREE (__t);
+}
+
+tree
+tree_class_check (const_tree __t, const enum tree_code_class __class,
+                  const char *__f, int __l, const char *__g)
+{
+  if (TREE_CODE_CLASS (TREE_CODE(__t)) != __class)
+    tree_class_check_failed (__t, __class, __f, __l, __g);
+  return CONST_CAST_TREE (__t);
+}
+
+tree
+tree_range_check (const_tree __t,
+                  enum tree_code __code1, enum tree_code __code2,
+                  const char *__f, int __l, const char *__g)
+{
+  if (TREE_CODE (__t) < __code1 || TREE_CODE (__t) > __code2)
+    tree_range_check_failed (__t, __f, __l, __g, __code1, __code2);
+  return CONST_CAST_TREE (__t);
+}
+
+tree
+omp_clause_subcode_check (const_tree __t, enum omp_clause_code __code,
+                          const char *__f, int __l, const char *__g)
+{
+  if (TREE_CODE (__t) != OMP_CLAUSE)
+    tree_check_failed (__t, __f, __l, __g, OMP_CLAUSE, 0);
+  if (__t->omp_clause.code != __code)
+    omp_clause_check_failed (__t, __f, __l, __g, __code);
+  return CONST_CAST_TREE (__t);
+}
+
+tree
+omp_clause_range_check (const_tree __t,
+                        enum omp_clause_code __code1,
+                        enum omp_clause_code __code2,
+                        const char *__f, int __l, const char *__g)
+{
+  if (TREE_CODE (__t) != OMP_CLAUSE)
+    tree_check_failed (__t, __f, __l, __g, OMP_CLAUSE, 0);
+  if ((int) __t->omp_clause.code < (int) __code1
+      || (int) __t->omp_clause.code > (int) __code2)
+    omp_clause_range_check_failed (__t, __f, __l, __g, __code1, __code2);
+  return CONST_CAST_TREE (__t);
+}
+
+/* These checks have to be special cased.  */
+tree
+expr_check (const_tree __t, const char *__f, int __l, const char *__g)
+{
+  char const __c = TREE_CODE_CLASS (TREE_CODE (__t));
+  if (!IS_EXPR_CODE_CLASS (__c))
+    tree_class_check_failed (__t, tcc_expression, __f, __l, __g);
+  return CONST_CAST_TREE (__t);
+}
+
+/* These checks have to be special cased.  */
+tree
+non_type_check (const_tree __t, const char *__f, int __l, const char *__g)
+{
+  if (TYPE_P (__t))
+    tree_not_class_check_failed (__t, tcc_type, __f, __l, __g);
+  return CONST_CAST_TREE (__t);
+}
+
+tree *
+tree_vec_elt_check (const_tree __t, int __i,
+                    const char *__f, int __l, const char *__g)
+{
+  if (TREE_CODE (__t) != TREE_VEC)
+    tree_check_failed (__t, __f, __l, __g, TREE_VEC, 0);
+  if (__i < 0 || __i >= __t->vec.length)
+    tree_vec_elt_check_failed (__i, __t->vec.length, __f, __l, __g);
+  return &CONST_CAST_TREE (__t)->vec.a[__i];
+}
+
+tree *
+omp_clause_elt_check (const_tree __t, int __i,
+                      const char *__f, int __l, const char *__g)
+{
+  if (TREE_CODE (__t) != OMP_CLAUSE)
+    tree_check_failed (__t, __f, __l, __g, OMP_CLAUSE, 0);
+  if (__i < 0 || __i >= omp_clause_num_ops [__t->omp_clause.code])
+    omp_clause_operand_check_failed (__i, __t, __f, __l, __g);
+  return &CONST_CAST_TREE (__t)->omp_clause.ops[__i];
+}
+
+/* Special checks for TREE_OPERANDs.  */
+tree *
+tree_operand_check (const_tree __t, int __i,
+                    const char *__f, int __l, const char *__g)
+{
+  const_tree __u = EXPR_CHECK (__t);
+  if (__i < 0 || __i >= TREE_OPERAND_LENGTH (__u))
+    tree_operand_check_failed (__i, __u, __f, __l, __g);
+  return &CONST_CAST_TREE (__u)->exp.operands[__i];
+}
+
+tree *
+tree_operand_check_code (const_tree __t, enum tree_code __code, int __i,
+                         const char *__f, int __l, const char *__g)
+{
+  if (TREE_CODE (__t) != __code)
+    tree_check_failed (__t, __f, __l, __g, __code, 0);
+  if (__i < 0 || __i >= TREE_OPERAND_LENGTH (__t))
+    tree_operand_check_failed (__i, __t, __f, __l, __g);
+  return &CONST_CAST_TREE (__t)->exp.operands[__i];
+}
+
+#endif
+
 #include "gt-tree.h"

Reply via email to