diff mbox

Turn check macros into functions. (issue6188088)

Message ID 4FB54511.6010604@google.com
State New
Headers show

Commit Message

Diego Novillo May 17, 2012, 6:36 p.m. UTC
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  <crowl@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  <crowl@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.

Comments

Richard Biener May 18, 2012, 10:14 a.m. UTC | #1
On Thu, May 17, 2012 at 8:36 PM, Diego Novillo <dnovillo@google.com> wrote:
> 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?

As you retain the macros anyway you can simply not return anything
from the C++ checking functions define to a stmt expression
({ check_in_cxx (t); t; })

Btw, what breaks if the check functions always return a const_tree and
take a const_tree?

Richard.

>
> Thanks.  Diego.
>
>
> 2012-05-17  Lawrence Crowl  <crowl@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.
Diego Novillo May 18, 2012, 11:46 a.m. UTC | #2
On 12-05-18 06:14 , Richard Guenther wrote:

> As you retain the macros anyway you can simply not return anything
> from the C++ checking functions define to a stmt expression
> ({ check_in_cxx (t); t; })

Sure, but that takes us back to the original gdb issue: it does not 
understand statement expressions.

> Btw, what breaks if the check functions always return a const_tree and
> take a const_tree?

You get a stream of "invalid conversion from 'tree_node* const*' to 
'tree_node**'".


Diego.
Richard Biener May 18, 2012, 12:06 p.m. UTC | #3
On Fri, May 18, 2012 at 1:46 PM, Diego Novillo <dnovillo@google.com> wrote:
> On 12-05-18 06:14 , Richard Guenther wrote:
>
>> As you retain the macros anyway you can simply not return anything
>> from the C++ checking functions define to a stmt expression
>> ({ check_in_cxx (t); t; })
>
>
> Sure, but that takes us back to the original gdb issue: it does not
> understand statement expressions.
>
>
>> Btw, what breaks if the check functions always return a const_tree and
>> take a const_tree?
>
>
> You get a stream of "invalid conversion from 'tree_node* const*' to
> 'tree_node**'".

Can you locate those?  I mean, most uses look like

#define DECL_NONSHAREABLE(NODE) \
  (TREE_CHECK2 (NODE, VAR_DECL, \
                RESULT_DECL)->decl_common.decl_nonshareable_flag)

thus they only dereference the result, not assign it anywhere.

Richard.

>
> Diego.
Jay Foad May 18, 2012, 12:23 p.m. UTC | #4
On 18 May 2012 12:46, Diego Novillo <dnovillo@google.com> wrote:
> On 12-05-18 06:14 , Richard Guenther wrote:
>
>> As you retain the macros anyway you can simply not return anything
>> from the C++ checking functions define to a stmt expression
>> ({ check_in_cxx (t); t; })
>
>
> Sure, but that takes us back to the original gdb issue: it does not
> understand statement expressions.

What's wrong with:

(check_in_cxx(t), t)

?

Jay.
Richard Henderson May 18, 2012, 10:14 p.m. UTC | #5
On 05/18/12 05:06, Richard Guenther wrote:
> Can you locate those?  I mean, most uses look like
> 
> #define DECL_NONSHAREABLE(NODE) \
>   (TREE_CHECK2 (NODE, VAR_DECL, \
>                 RESULT_DECL)->decl_common.decl_nonshareable_flag)
> 
> thus they only dereference the result, not assign it anywhere.

const_tree vs tree for NODE is the difference between the
entire expression being writable, or read-only.

  DECL_NONSHARABLE (d) = true;



r~
Diego Novillo May 18, 2012, 11:48 p.m. UTC | #6
On 12-05-18 18:14 , Richard Henderson wrote:
> On 05/18/12 05:06, Richard Guenther wrote:
>> Can you locate those?  I mean, most uses look like
>>
>> #define DECL_NONSHAREABLE(NODE) \
>>    (TREE_CHECK2 (NODE, VAR_DECL, \
>>                  RESULT_DECL)->decl_common.decl_nonshareable_flag)
>>
>> thus they only dereference the result, not assign it anywhere.
>
> const_tree vs tree for NODE is the difference between the
> entire expression being writable, or read-only.
>
>    DECL_NONSHARABLE (d) = true;

Right.  Returning a const_tree means that you can't write to anything in 
the resulting value.  To answer richi's original question, this produces 
~9,000 syntax errors in gcc/*.o.

So, I would like to figure out what to do with this.   We have a 
usability problem wrt deubgging that I would like to fix.  The only way 
we have of using all the tree accessor macros from GDB is to convert the 
checks into functions (converting the actual accessor macros would also 
work, but that's a different story).

Now that we have the ability to skip functions in gdb, making tree 
checking into functions should not be a problem.  Additionally, we can 
make gdb skip other common functions (like tree_code_length).

We can do this in trunk today using a variant of Lawrence's original 
patch (http://gcc.gnu.org/ml/gcc-patches/2011-09/msg01649.html).  This 
uses no C++ features, though it weakens type checking by removing away 
constness.

In the cxx-conversion branch, we can use overloads, which will DTRT with 
const.

My question is, what do folks prefer?

a) The trunk patch today, using no C++ features.
b) Wait for the cxx-conversion variant?

Incidentally, making these expression statements into out-of-line 
functions saves about 3% in the final binary size, but increases compile 
time by about 10% (tested on several large .o files in bld/gcc), so we 
likely want to keep them as inline functions.


Diego.
Diego Novillo May 19, 2012, midnight UTC | #7
On 12-05-18 08:23 , Jay Foad wrote:

> What's wrong with:
>
> (check_in_cxx(t), t)
>
> ?

This evaluates 't' twice.


Diego.
Lawrence Crowl May 19, 2012, 2:54 a.m. UTC | #8
On 5/18/12, Diego Novillo <dnovillo@google.com> wrote:
> So, I would like to figure out what to do with this.  We have
> a usability problem wrt deubgging that I would like to fix.
> The only way we have of using all the tree accessor macros from
> GDB is to convert the checks into functions (converting the actual
> accessor macros would also work, but that's a different story).
>
> Now that we have the ability to skip functions in gdb, making tree
> checking into functions should not be a problem.  Additionally, we
> can make gdb skip other common functions (like tree_code_length).
>
> We can do this in trunk today using a variant of Lawrence's original
> patch (http://gcc.gnu.org/ml/gcc-patches/2011-09/msg01649.html).  This
> uses no C++ features, though it weakens type checking by removing away
> constness.

The difference between then and now is that we now have the gdb
skip command, which fixes the problem of introducing another step
point into debugging code using the macros.

> In the cxx-conversion branch, we can use overloads, which will
> DTRT with const.
>
> My question is, what do folks prefer?
>
> a) The trunk patch today, using no C++ features.
> b) Wait for the cxx-conversion variant?
>
> Incidentally, making these expression statements into out-of-line
> functions saves about 3% in the final binary size, but increases
> compile time by about 10% (tested on several large .o files in
> bld/gcc), so we likely want to keep them as inline functions.

With the inline functions, if the compiler is doing no inlining,
we should still get near to that 3% reduction in binary size.
Richard Henderson May 20, 2012, 5:59 p.m. UTC | #9
On 05/18/2012 04:48 PM, Diego Novillo wrote:
> We can do this in trunk today using a variant of Lawrence's original patch (http://gcc.gnu.org/ml/gcc-patches/2011-09/msg01649.html).  This uses no C++ features, though it weakens type checking by removing away constness.
>
> In the cxx-conversion branch, we can use overloads, which will DTRT with const.
>
> My question is, what do folks prefer?
>
> a) The trunk patch today, using no C++ features.
> b) Wait for the cxx-conversion variant?

Surely (check(t), t) also works, and also strt wrt const.


r~
Diego Novillo May 20, 2012, 7:10 p.m. UTC | #10
On 12-05-20 13:59 , Richard Henderson wrote:
> On 05/18/2012 04:48 PM, Diego Novillo wrote:
>> We can do this in trunk today using a variant of Lawrence's original
>> patch (http://gcc.gnu.org/ml/gcc-patches/2011-09/msg01649.html). This
>> uses no C++ features, though it weakens type checking by removing away
>> constness.
>>
>> In the cxx-conversion branch, we can use overloads, which will DTRT
>> with const.
>>
>> My question is, what do folks prefer?
>>
>> a) The trunk patch today, using no C++ features.
>> b) Wait for the cxx-conversion variant?
>
> Surely (check(t), t) also works, and also strt wrt const.

My concern with (check(t), t) is that it evaluates 't' twice.  It may 
not be a big deal, however.  In which case, I'm OK with that alternative.


Diego.
Richard Biener May 21, 2012, 10:18 a.m. UTC | #11
On Sun, May 20, 2012 at 9:10 PM, Diego Novillo <dnovillo@google.com> wrote:
> On 12-05-20 13:59 , Richard Henderson wrote:
>>
>> On 05/18/2012 04:48 PM, Diego Novillo wrote:
>>>
>>> We can do this in trunk today using a variant of Lawrence's original
>>> patch (http://gcc.gnu.org/ml/gcc-patches/2011-09/msg01649.html). This
>>> uses no C++ features, though it weakens type checking by removing away
>>> constness.
>>>
>>> In the cxx-conversion branch, we can use overloads, which will DTRT
>>> with const.
>>>
>>> My question is, what do folks prefer?
>>>
>>> a) The trunk patch today, using no C++ features.
>>> b) Wait for the cxx-conversion variant?
>>
>>
>> Surely (check(t), t) also works, and also strt wrt const.
>
>
> My concern with (check(t), t) is that it evaluates 't' twice.  It may not be
> a big deal, however.  In which case, I'm OK with that alternative.

Hum.  A source of possibly nasty errors.

I'd like to avoid using templates here though.  Going with two overloads
for each function sounds like the best solution to me, thus delay the
change to cxx-switch time.

What's the effect on bootstrap times?  Remember we build stage1 with -O0
and checking enabled always ...

Richard.

>
> Diego.
>
Richard Biener May 21, 2012, 11:53 a.m. UTC | #12
On Mon, May 21, 2012 at 12:18 PM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Sun, May 20, 2012 at 9:10 PM, Diego Novillo <dnovillo@google.com> wrote:
>> On 12-05-20 13:59 , Richard Henderson wrote:
>>>
>>> On 05/18/2012 04:48 PM, Diego Novillo wrote:
>>>>
>>>> We can do this in trunk today using a variant of Lawrence's original
>>>> patch (http://gcc.gnu.org/ml/gcc-patches/2011-09/msg01649.html). This
>>>> uses no C++ features, though it weakens type checking by removing away
>>>> constness.
>>>>
>>>> In the cxx-conversion branch, we can use overloads, which will DTRT
>>>> with const.
>>>>
>>>> My question is, what do folks prefer?
>>>>
>>>> a) The trunk patch today, using no C++ features.
>>>> b) Wait for the cxx-conversion variant?
>>>
>>>
>>> Surely (check(t), t) also works, and also strt wrt const.
>>
>>
>> My concern with (check(t), t) is that it evaluates 't' twice.  It may not be
>> a big deal, however.  In which case, I'm OK with that alternative.
>
> Hum.  A source of possibly nasty errors.
>
> I'd like to avoid using templates here though.  Going with two overloads
> for each function sounds like the best solution to me, thus delay the
> change to cxx-switch time.
>
> What's the effect on bootstrap times?  Remember we build stage1 with -O0
> and checking enabled always ...

Btw, as of doing this all for the sake of debuggability of GCC - for debugging
you do _not_ want to have gdb invoke the checking functions, because then
you ICE in the inferior if you mis-type.  Instead ideally gdb would use the
non-checking variant or even better, diagnose misuse itself (which means
using a python implementation rather than the gcc macro or an inferior call).

So - why not provide proper (python) implementations of the various
accessors in .gdbinit?

Richard.

> Richard.
>
>>
>> Diego.
>>
diff mbox

Patch

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"