On 7/2/21 5:47 PM, Trevor Saunders wrote:
On Fri, Jul 02, 2021 at 01:20:14PM -0600, Martin Sebor wrote:
On 6/29/21 11:35 PM, Trevor Saunders wrote:
This makes it possible to assert if input_location is used during the lifetime
of a scope.  This will allow us to find places that currently use it within a
function and its callees, or prevent adding uses within the lifetime of a
function after all existing uses are removed.

I of course support removing global state but I have questions about
this approach.  I'm probably missing some context but I don't
understand how it's better than replacing the variables with
functions now (defining the variables as static in some .c file).

Other than requiring either hiding the function calls behind a macro,
rahter than operator overloading, or needing to update all references I
think they do more or less the same thing.

Also, it seems as though the mechanism to enforce this policy of not
using global variables directly is to trigger an ICE when the piece
code that does end up using runs.  If this is correct, I would be
very uncomfortable with this approach, and not just because it would
expose our users to a GCC-internal policy but generally because
the enforcement of a policy should happen as early as possible so
that violators can fix them before they submit code for review.

Perhaps the asserts should be gcc_checking_assert, to avoid any overhead
in release builds if nothing else.  One would really like to think that
the changed code is covered by the testsuite, if not exercised in
bootstraps, so in most cases it would be caught before patches are
submitted.  Certainly something will eventually slip through, probably
because it depends on the host or target, but that should be the
exception.

It's always the exception when these things slip through, but they
do.  I don't think the risks in this case justify the benefits of
enforcing an internal policy whose violations are otherwise entirely
benign.

  Its a rather useful property to know that a global's value
is not significant in a scope, to say remove save and restore of
input_location, or even more importantly remove push / pop of cfun, and
I can't see a way to do that statically, other than possibly a IPA
pass that depends on a LTO build, or analysis of the binary either of
which would be orders of magnitude more work.

My concern is that poisoning a variable in one scope/file could
expose latent violations in other files far removed from it, and
that could easily happen under conditions not be exercised during
testing because of less than complete coverage.  We would have to
carry this risk potentially for a number of releases, until a full
replacement took place.

IMO, a safer and less costly solution to the global state problem
is to fully remove accesses to one variable at a time, replacing
each with the preferred alternative.  A piecemeal approach seems
fraught with too much risk for what to me seems like very little
immediate gain.  I don't see a value in enforcing this policy one
scope at a time.

Martin


Finally, I've been under the impression that defining global objects
that require dynamic initialization is discouraged in GCC.  This patch
seems to do just that: define poisonable objects in each file that
defines such a variable.  I don't see any uses of auto_poison in
this patch, so it looks as though the poisonable definitions aren't
actually doing anything useful yet but might start enforcing
the policy if some other patch defines an auto_poison variable
referring to the same global in a file/scope from which functions
changed in this patch that access the variable are called?  (This
probably exposes my overall confusion with how this works.)

As for dynamic initialization, that's technically true, but would be
fixed by making the constructor constexpr.
The first three patches in the series do just add infrastructure with
out making use of it to actually block anything, and the final patch
blocks usage in a minimal function as a somewhat toyish example of what
can be done.

thanks

Trev


Martin


bootstrapped and regtested on x86_64-linux-gnu, ok?

Trev

gcc/cp/ChangeLog:

        * call.c (add_builtin_candidate): Adjust.
        * decl.c (compute_array_index_type_loc): Likewise.
        * decl2.c (get_guard_cond): Likewise.
        (one_static_initialization_or_destruction): Likewise.
        (do_static_initialization_or_destruction): Likewise.
        * init.c (build_new_1): Likewise.
        (build_vec_init): Likewise.
        * module.cc (finish_module_processing): Likewise.
        * parser.c (cp_convert_range_for): Likewise.
        (cp_parser_perform_range_for_lookup): Likewise.
        (cp_parser_omp_for_incr): Likewise.
        (cp_convert_omp_range_for): Likewise.
        * pt.c (fold_expression): Likewise.
        (tsubst_copy_and_build): Likewise.
        * typeck.c (common_pointer_type): Likewise.
        (cp_build_array_ref): Likewise.
        (get_member_function_from_ptrfunc): Likewise.
        (cp_build_unary_op): Likewise.
        (convert_ptrmem): Likewise.
        (cp_build_modify_expr): Likewise.
        (build_ptrmemfunc): Likewise.

gcc/ChangeLog:

        * diagnostic.c (internal_error): Remove use of input_location.
        * input.c (input_location): Change type to poisonable<location_t>.
        * input.h (input_location): Adjust prototype.

gcc/objc/ChangeLog:

        * objc-next-runtime-abi-02.c (build_v2_objc_method_fixup_call): Adjust.
---
   gcc/cp/call.c                       |  2 +-
   gcc/cp/decl.c                       |  2 +-
   gcc/cp/decl2.c                      | 12 +++++------
   gcc/cp/init.c                       | 14 ++++++------
   gcc/cp/module.cc                    |  2 +-
   gcc/cp/parser.c                     | 11 +++++-----
   gcc/cp/pt.c                         |  4 ++--
   gcc/cp/typeck.c                     | 33 ++++++++++++++++-------------
   gcc/diagnostic.c                    |  2 +-
   gcc/input.c                         |  2 +-
   gcc/input.h                         |  3 ++-
   gcc/objc/objc-next-runtime-abi-02.c |  2 +-
   12 files changed, 47 insertions(+), 42 deletions(-)

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index e4df72ec1a3..c94fe0b3bd2 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -3126,7 +3126,7 @@ add_builtin_candidate (struct z_candidate **candidates, 
enum tree_code code,
       {
         if (TYPE_PTR_OR_PTRMEM_P (type1))
        {
-         tree cptype = composite_pointer_type (input_location,
+         tree cptype = composite_pointer_type (op_location_t (input_location),
                                                type1, type2,
                                                error_mark_node,
                                                error_mark_node,
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index fa6af6fec11..84e2bdae6bf 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -10884,7 +10884,7 @@ compute_array_index_type_loc (location_t name_loc, tree 
name, tree size,
         cp_build_binary_op will be appropriately folded.  */
         {
        processing_template_decl_sentinel s;
-       itype = cp_build_binary_op (input_location,
+       itype = cp_build_binary_op (op_location_t (input_location),
                                    MINUS_EXPR,
                                    cp_convert (ssizetype, size, complain),
                                    cp_convert (ssizetype, integer_one_node,
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 090a83bd670..ddb7e248c63 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -3386,7 +3386,7 @@ get_guard_cond (tree guard, bool thread_safe)
         guard_value = integer_one_node;
         if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
        guard_value = fold_convert (TREE_TYPE (guard), guard_value);
-      guard = cp_build_binary_op (input_location,
+      guard = cp_build_binary_op (location_t (input_location),
                                  BIT_AND_EXPR, guard, guard_value,
                                  tf_warning_or_error);
       }
@@ -3394,7 +3394,7 @@ get_guard_cond (tree guard, bool thread_safe)
     guard_value = integer_zero_node;
     if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
       guard_value = fold_convert (TREE_TYPE (guard), guard_value);
-  return cp_build_binary_op (input_location,
+  return cp_build_binary_op (location_t (input_location),
                             EQ_EXPR, guard, guard_value,
                             tf_warning_or_error);
   }
@@ -4056,7 +4056,7 @@ one_static_initialization_or_destruction (tree decl, tree 
init, bool initp)
         last to destroy the variable.  */
         else if (initp)
        guard_cond
-         = cp_build_binary_op (input_location,
+         = cp_build_binary_op (location_t (input_location),
                                EQ_EXPR,
                                cp_build_unary_op (PREINCREMENT_EXPR,
                                                   guard,
@@ -4066,7 +4066,7 @@ one_static_initialization_or_destruction (tree decl, tree 
init, bool initp)
                                tf_warning_or_error);
         else
        guard_cond
-         = cp_build_binary_op (input_location,
+         = cp_build_binary_op (location_t (input_location),
                                EQ_EXPR,
                                cp_build_unary_op (PREDECREMENT_EXPR,
                                                   guard,
@@ -4132,7 +4132,7 @@ do_static_initialization_or_destruction (tree vars, bool 
initp)
     /* Build the outer if-stmt to check for initialization or destruction.  */
     init_if_stmt = begin_if_stmt ();
     cond = initp ? integer_one_node : integer_zero_node;
-  cond = cp_build_binary_op (input_location,
+  cond = cp_build_binary_op (location_t (input_location),
                             EQ_EXPR,
                             initialize_p_decl,
                             cond,
@@ -4176,7 +4176,7 @@ do_static_initialization_or_destruction (tree vars, bool 
initp)
       /* Conditionalize this initialization on being in the right priority
          and being initializing/finalizing appropriately.  */
       priority_if_stmt = begin_if_stmt ();
-    cond = cp_build_binary_op (input_location,
+    cond = cp_build_binary_op (location_t (input_location),
                               EQ_EXPR,
                               priority_decl,
                               build_int_cst (NULL_TREE, priority),
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 88f6f90a800..d9acdefae7c 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -2907,7 +2907,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, 
tree nelts,
          nelts = error_mark_node;
        }
         if (nelts != error_mark_node)
-       nelts = cp_build_binary_op (input_location,
+       nelts = cp_build_binary_op (location_t (input_location),
                                    MULT_EXPR, nelts,
                                    inner_nelts_cst,
                                    complain);
@@ -3428,7 +3428,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, 
tree nelts,
               }
          init_expr
            = build_vec_init (data_addr,
-                             cp_build_binary_op (input_location,
+                             cp_build_binary_op (location_t (input_location),
                                                  MINUS_EXPR, outer_nelts,
                                                  integer_one_node,
                                                  complain),
@@ -3600,12 +3600,12 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, 
tree nelts,
       {
         if (check_new)
        {
-         tree ifexp = cp_build_binary_op (input_location,
+         tree ifexp = cp_build_binary_op (location_t (input_location),
                                           NE_EXPR, alloc_node,
                                           nullptr_node,
                                           complain);
-         rval = build_conditional_expr (input_location, ifexp, rval,
-                                        alloc_node, complain);
+         rval = build_conditional_expr (location_t (input_location), ifexp,
+                                        rval, alloc_node, complain);
        }
         /* Perform the allocation before anything else, so that ALLOC_NODE
@@ -4612,14 +4612,14 @@ build_vec_init (tree base, tree maxindex, tree init,
         && from_array != 2)
       {
         tree e;
-      tree m = cp_build_binary_op (input_location,
+      tree m = cp_build_binary_op (location_t (input_location),
                                   MINUS_EXPR, maxindex, iterator,
                                   complain);
         /* Flatten multi-dimensional array since build_vec_delete only
         expects one-dimensional array.  */
         if (TREE_CODE (type) == ARRAY_TYPE)
-       m = cp_build_binary_op (input_location,
+       m = cp_build_binary_op (location_t (input_location),
                                MULT_EXPR, m,
                                /* Avoid mixing signed and unsigned.  */
                                convert (TREE_TYPE (m),
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index f259515a498..72f32487e51 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -19852,7 +19852,7 @@ finish_module_processing (cpp_reader *reader)
          elf_out to (fd, e);
          if (to.begin ())
            {
-             auto loc = input_location;
+             location_t loc = input_location;
              /* So crashes finger-point the module decl.  */
              input_location = state->loc;
              state->write (&to, reader);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 02daa7a6f6a..e90ee873a94 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -13206,7 +13206,7 @@ cp_convert_range_for (tree statement, tree range_decl, 
tree range_expr,
     finish_init_stmt (statement);
     /* The new for condition.  */
-  condition = build_x_binary_op (input_location, NE_EXPR,
+  condition = build_x_binary_op (location_t (input_location), NE_EXPR,
                                 begin, ERROR_MARK,
                                 end, ERROR_MARK,
                                 NULL, tf_warning_or_error);
@@ -13326,7 +13326,7 @@ cp_parser_perform_range_for_lookup (tree range, tree 
*begin, tree *end)
          if (!same_type_p (iter_type, cv_unqualified (TREE_TYPE (*end))))
            {
              if (cxx_dialect >= cxx17
-                 && (build_x_binary_op (input_location, NE_EXPR,
+                 && (build_x_binary_op (location_t (input_location), NE_EXPR,
                                         *begin, ERROR_MARK,
                                         *end, ERROR_MARK,
                                         NULL, tf_none)
@@ -39961,8 +39961,9 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
                                        tf_warning_or_error);
            }
          else
-           lhs = build_x_binary_op (input_location, op, lhs, ERROR_MARK, rhs,
-                                    ERROR_MARK, NULL, tf_warning_or_error);
+           lhs = build_x_binary_op (location_t (input_location), op, lhs,
+                                    ERROR_MARK, rhs, ERROR_MARK, NULL,
+                                    tf_warning_or_error);
        }
       }
     while (token->type == CPP_PLUS || token->type == CPP_MINUS);
@@ -40309,7 +40310,7 @@ cp_convert_omp_range_for (tree &this_pre_body, vec<tree, 
va_gc> *for_block,
     if (CLASS_TYPE_P (iter_type))
       cond = build2 (NE_EXPR, boolean_type_node, begin, end);
     else
-    cond = build_x_binary_op (input_location, NE_EXPR,
+    cond = build_x_binary_op (location_t (input_location), NE_EXPR,
                              begin, ERROR_MARK,
                              end, ERROR_MARK,
                              NULL, tf_warning_or_error);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index f2039e09cd7..b679e34bfa4 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -12624,7 +12624,7 @@ fold_expression (tree t, tree left, tree right, 
tsubst_flags_t complain)
       case COMPOUND_EXPR:
         return build_x_compound_expr (input_location, left, right, complain);
       default:
-      return build_x_binary_op (input_location, code,
+      return build_x_binary_op (location_t (input_location), code,
                                   left, TREE_CODE (left),
                                   right, TREE_CODE (right),
                                   /*overload=*/NULL,
@@ -19854,7 +19854,7 @@ tsubst_copy_and_build (tree t,
        warning_sentinel s4(warn_tautological_compare, was_dep);
        tree r = build_x_binary_op
-         (input_location, TREE_CODE (t),
+         (location_t (input_location), TREE_CODE (t),
           op0,
           (warning_suppressed_p (TREE_OPERAND (t, 0))
            ? ERROR_MARK
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index a483e1f988d..98aa9e69612 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -982,7 +982,7 @@ common_pointer_type (tree t1, tree t2)
                 || (TYPE_PTRDATAMEM_P (t1) && TYPE_PTRDATAMEM_P (t2))
                 || (TYPE_PTRMEMFUNC_P (t1) && TYPE_PTRMEMFUNC_P (t2)));
-  return composite_pointer_type (input_location, t1, t2,
+  return composite_pointer_type (location_t (input_location), t1, t2,
                                 error_mark_node, error_mark_node,
                                    CPO_CONVERSION, tf_warning_or_error);
   }
@@ -3702,7 +3702,8 @@ cp_build_array_ref (location_t loc, tree array, tree idx,
       warn_array_subscript_with_type_char (loc, idx);
-    ret = cp_build_binary_op (input_location, PLUS_EXPR, ar, ind, complain);
+    ret = cp_build_binary_op (location_t (input_location), PLUS_EXPR, ar, ind,
+                             complain);
       if (first)
         ret = build2_loc (loc, COMPOUND_EXPR, TREE_TYPE (ret), first, ret);
       ret = cp_build_indirect_ref (loc, ret, RO_ARRAY_INDEXING, complain);
@@ -3793,10 +3794,10 @@ get_member_function_from_ptrfunc (tree 
*instance_ptrptr, tree function,
        {
          int flag_sanitize_save;
        case ptrmemfunc_vbit_in_pfn:
-         e1 = cp_build_binary_op (input_location,
+         e1 = cp_build_binary_op (location_t (input_location),
                                   BIT_AND_EXPR, idx, integer_one_node,
                                   complain);
-         idx = cp_build_binary_op (input_location,
+         idx = cp_build_binary_op (location_t (input_location),
                                    MINUS_EXPR, idx, integer_one_node,
                                    complain);
          if (idx == error_mark_node)
@@ -3804,7 +3805,7 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, 
tree function,
          break;
        case ptrmemfunc_vbit_in_delta:
-         e1 = cp_build_binary_op (input_location,
+         e1 = cp_build_binary_op (location_t (input_location),
                                   BIT_AND_EXPR, delta, integer_one_node,
                                   complain);
          /* Don't instrument the RSHIFT_EXPR we're about to create because
@@ -3812,7 +3813,7 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, 
tree function,
             well with SAVE_EXPRs therein.  */
          flag_sanitize_save = flag_sanitize;
          flag_sanitize = 0;
-         delta = cp_build_binary_op (input_location,
+         delta = cp_build_binary_op (location_t (input_location),
                                      RSHIFT_EXPR, delta, integer_one_node,
                                      complain);
          flag_sanitize = flag_sanitize_save;
@@ -3874,7 +3875,8 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, 
tree function,
                     cp_build_addr_expr (e2, complain));
         e2 = fold_convert (TREE_TYPE (e3), e2);
-      e1 = build_conditional_expr (input_location, e1, e2, e3, complain);
+      e1 = build_conditional_expr (location_t (input_location), e1, e2, e3,
+                                  complain);
         if (e1 == error_mark_node)
        return error_mark_node;
@@ -6754,7 +6756,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool 
noconvert,
       case TRUTH_NOT_EXPR:
         if (gnu_vector_type_p (TREE_TYPE (arg)))
-       return cp_build_binary_op (input_location, EQ_EXPR, arg,
+       return cp_build_binary_op (location_t (input_location), EQ_EXPR, arg,
                                   build_zero_cst (TREE_TYPE (arg)), complain);
         arg = perform_implicit_conversion (boolean_type_node, arg,
                                         complain);
@@ -7501,12 +7503,13 @@ convert_ptrmem (tree type, tree expr, bool 
allow_inverse_p,
          if (TREE_CODE (expr) == PTRMEM_CST)
            expr = cplus_expand_constant (expr);
-         tree cond = cp_build_binary_op (input_location, EQ_EXPR, expr,
+         tree cond = cp_build_binary_op (location_t (input_location), EQ_EXPR,
+                                         expr,
                                          build_int_cst (TREE_TYPE (expr), -1),
                                          complain);
          tree op1 = build_nop (ptrdiff_type_node, expr);
-         tree op2 = cp_build_binary_op (input_location, PLUS_EXPR, op1, delta,
-                                        complain);
+         tree op2 = cp_build_binary_op (location_t (input_location),
+                                        PLUS_EXPR, op1, delta, complain);
          expr = fold_build3_loc (input_location,
                                  COND_EXPR, ptrdiff_type_node, cond, op1, op2);
@@ -8686,7 +8689,7 @@ cp_build_modify_expr (location_t loc, tree lhs, enum 
tree_code modifycode,
        tree op2 = TREE_OPERAND (lhs, 2);
        if (TREE_CODE (op2) != THROW_EXPR)
          op2 = cp_build_modify_expr (loc, op2, modifycode, rhs, complain);
-       tree cond = build_conditional_expr (input_location,
+       tree cond = build_conditional_expr (location_t (input_location),
                                            TREE_OPERAND (lhs, 0), op1, op2,
                                            complain);
@@ -8767,7 +8770,7 @@ cp_build_modify_expr (location_t loc, tree lhs, enum 
tree_code modifycode,
            /* Do the default thing.  */;
          else
            {
-             result = build_new_op (input_location, MODIFY_EXPR,
+             result = build_new_op (location_t (input_location), MODIFY_EXPR,
                                     LOOKUP_NORMAL, lhs, rhs,
                                     make_node (NOP_EXPR), /*overload=*/NULL,
                                     complain);
@@ -9263,10 +9266,10 @@ build_ptrmemfunc (tree type, tree pfn, int force, bool 
c_cast_p,
         if (!integer_zerop (n))
        {
          if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_delta)
-           n = cp_build_binary_op (input_location,
+           n = cp_build_binary_op (location_t (input_location),
                                    LSHIFT_EXPR, n, integer_one_node,
                                    complain);
-         delta = cp_build_binary_op (input_location,
+         delta = cp_build_binary_op (location_t (input_location),
                                      PLUS_EXPR, delta, n, complain);
        }
         return build_ptrmemfunc1 (to_type, delta, npfn);
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index d58586f2526..3f68d1d79eb 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -1835,7 +1835,7 @@ internal_error (const char *gmsgid, ...)
     auto_diagnostic_group d;
     va_list ap;
     va_start (ap, gmsgid);
-  rich_location richloc (line_table, input_location);
+  rich_location richloc (line_table, UNKNOWN_LOCATION);
     diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
     va_end (ap);
diff --git a/gcc/input.c b/gcc/input.c
index 9e39e7df83c..1843c3077aa 100644
--- a/gcc/input.c
+++ b/gcc/input.c
@@ -122,7 +122,7 @@ public:
   /* Current position in real source file.  */
-location_t input_location = UNKNOWN_LOCATION;
+poisonable<location_t> input_location (UNKNOWN_LOCATION);
   class line_maps *line_table;
diff --git a/gcc/input.h b/gcc/input.h
index f1ef5d76cfd..2b96ce8008e 100644
--- a/gcc/input.h
+++ b/gcc/input.h
@@ -21,6 +21,7 @@ along with GCC; see the file COPYING3.  If not see
   #ifndef GCC_INPUT_H
   #define GCC_INPUT_H
+#include "poison.h"
   #include "line-map.h"
   extern GTY(()) class line_maps *line_table;
@@ -95,7 +96,7 @@ expand_location_to_spelling_point (location_t,
   extern location_t expansion_point_location_if_in_system_header (location_t);
   extern location_t expansion_point_location (location_t);
-extern location_t input_location;
+extern poisonable<location_t> input_location;
   #define LOCATION_FILE(LOC) ((expand_location (LOC)).file)
   #define LOCATION_LINE(LOC) ((expand_location (LOC)).line)
diff --git a/gcc/objc/objc-next-runtime-abi-02.c 
b/gcc/objc/objc-next-runtime-abi-02.c
index 3cfcd0b1a57..9ecb91cc56b 100644
--- a/gcc/objc/objc-next-runtime-abi-02.c
+++ b/gcc/objc/objc-next-runtime-abi-02.c
@@ -1690,7 +1690,7 @@ build_v2_objc_method_fixup_call (int super_flag, tree 
method_prototype,
                               fold_convert (rcv_p, integer_zero_node), 1);
   #ifdef OBJCPLUS
-      ret_val = build_conditional_expr (input_location,
+      ret_val = build_conditional_expr (location_t (input_location),
                                        ifexp, ret_val, ftree,
                                        tf_warning_or_error);
   #else



Reply via email to