Hello,

I'd like to ask if anyone has any new thoughts on this patch.

Let me also point out that valgrind/memcheck.h is permissively
licensed (BSD-style, rest of Valgrind is GPLv2), with the intention
to allow importing into projects that are interested in using
client requests without build-time dependency on installed headers.
So maybe we have that as an option too.

Alexander

On Fri, 22 Dec 2023, Alexander Monakov wrote:

> From: Daniil Frolov <exactl...@ispras.ru>
> 
> PR 66487 is asking to provide sanitizer-like detection for C++ object
> lifetime violations that are worked around with -fno-lifetime-dse or
> -flifetime-dse=1 in Firefox, LLVM (PR 106943), OpenJade (PR 69534).
> 
> The discussion in the PR was centered around extending MSan, but MSan
> was not ported to GCC (and requires rebuilding everything with
> instrumentation).
> 
> Instead, allow Valgrind to see lifetime boundaries by emitting client
> requests along *this = { CLOBBER }.  The client request marks the
> "clobbered" memory as undefined for Valgrind; clobbering assignments
> mark the beginning of ctor and end of dtor execution for C++ objects.
> Hence, attempts to read object storage after the destructor, or
> "pre-initialize" its fields prior to the constructor will be caught.
> 
> Valgrind client requests are offered as macros that emit inline asm.
> For use in code generation, let's wrap them as libgcc builtins.
> 
> gcc/ChangeLog:
> 
>       * Makefile.in (OBJS): Add gimple-valgrind-interop.o.
>       * builtins.def (BUILT_IN_VALGRIND_MAKE_UNDEFINED): New.
>       * common.opt (-fvalgrind-annotations): New option.
>       * doc/install.texi (--enable-valgrind-interop): Document.
>       * doc/invoke.texi (-fvalgrind-annotations): Document.
>       * passes.def (pass_instrument_valgrind): Add.
>       * tree-pass.h (make_pass_instrument_valgrind): Declare.
>       * gimple-valgrind-interop.cc: New file.
> 
> libgcc/ChangeLog:
> 
>       * Makefile.in (LIB2ADD_ST): Add valgrind-interop.c.
>       * config.in: Regenerate.
>       * configure: Regenerate.
>       * configure.ac (--enable-valgrind-interop): New flag.
>       * libgcc2.h (__gcc_vgmc_make_mem_undefined): Declare.
>       * valgrind-interop.c: New file.
> 
> gcc/testsuite/ChangeLog:
> 
>       * g++.dg/valgrind-annotations-1.C: New test.
>       * g++.dg/valgrind-annotations-2.C: New test.
> 
> Co-authored-by: Alexander Monakov <amona...@ispras.ru>
> ---
> Changes in v2:
> 
> * Take new clobber kinds into account.
> * Do not link valgrind-interop.o into libgcc_s.so.
> 
>  gcc/Makefile.in                               |   1 +
>  gcc/builtins.def                              |   3 +
>  gcc/common.opt                                |   4 +
>  gcc/doc/install.texi                          |   5 +
>  gcc/doc/invoke.texi                           |  27 ++++
>  gcc/gimple-valgrind-interop.cc                | 125 ++++++++++++++++++
>  gcc/passes.def                                |   1 +
>  gcc/testsuite/g++.dg/valgrind-annotations-1.C |  22 +++
>  gcc/testsuite/g++.dg/valgrind-annotations-2.C |  12 ++
>  gcc/tree-pass.h                               |   1 +
>  libgcc/Makefile.in                            |   3 +
>  libgcc/config.in                              |   6 +
>  libgcc/configure                              |  22 ++-
>  libgcc/configure.ac                           |  15 ++-
>  libgcc/libgcc2.h                              |   2 +
>  libgcc/valgrind-interop.c                     |  40 ++++++
>  16 files changed, 287 insertions(+), 2 deletions(-)
>  create mode 100644 gcc/gimple-valgrind-interop.cc
>  create mode 100644 gcc/testsuite/g++.dg/valgrind-annotations-1.C
>  create mode 100644 gcc/testsuite/g++.dg/valgrind-annotations-2.C
>  create mode 100644 libgcc/valgrind-interop.c
> 
> diff --git a/gcc/Makefile.in b/gcc/Makefile.in
> index 9373800018..d027548203 100644
> --- a/gcc/Makefile.in
> +++ b/gcc/Makefile.in
> @@ -1507,6 +1507,7 @@ OBJS = \
>       gimple-ssa-warn-restrict.o \
>       gimple-streamer-in.o \
>       gimple-streamer-out.o \
> +     gimple-valgrind-interop.o \
>       gimple-walk.o \
>       gimple-warn-recursion.o \
>       gimplify.o \
> diff --git a/gcc/builtins.def b/gcc/builtins.def
> index f03df32f98..b05e20e062 100644
> --- a/gcc/builtins.def
> +++ b/gcc/builtins.def
> @@ -1194,6 +1194,9 @@ DEF_GCC_BUILTIN (BUILT_IN_LINE, "LINE", BT_FN_INT, 
> ATTR_NOTHROW_LEAF_LIST)
>  /* Control Flow Redundancy hardening out-of-line checker.  */
>  DEF_BUILTIN_STUB (BUILT_IN___HARDCFR_CHECK, "__builtin___hardcfr_check")
>  
> +/* Wrappers for Valgrind client requests.  */
> +DEF_EXT_LIB_BUILTIN (BUILT_IN_VALGRIND_MAKE_UNDEFINED, 
> "__gcc_vgmc_make_mem_undefined", BT_FN_VOID_PTR_SIZE, ATTR_NOTHROW_LEAF_LIST)
> +
>  /* Synchronization Primitives.  */
>  #include "sync-builtins.def"
>  
> diff --git a/gcc/common.opt b/gcc/common.opt
> index d263a959df..2be5b8d0a6 100644
> --- a/gcc/common.opt
> +++ b/gcc/common.opt
> @@ -3377,6 +3377,10 @@ Enum(auto_init_type) String(pattern) 
> Value(AUTO_INIT_PATTERN)
>  EnumValue
>  Enum(auto_init_type) String(zero) Value(AUTO_INIT_ZERO)
>  
> +fvalgrind-annotations
> +Common Var(flag_valgrind_annotations) Optimization
> +Annotate lifetime boundaries with Valgrind client requests.
> +
>  ; -fverbose-asm causes extra commentary information to be produced in
>  ; the generated assembly code (to make it more readable).  This option
>  ; is generally only of use to those who actually need to read the
> diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
> index d20b43a5b2..d6e5e5fdaf 100644
> --- a/gcc/doc/install.texi
> +++ b/gcc/doc/install.texi
> @@ -1563,6 +1563,11 @@ Disable TM clone registry in libgcc. It is enabled in 
> libgcc by default.
>  This option helps to reduce code size for embedded targets which do
>  not use transactional memory.
>  
> +@item --enable-valgrind-interop
> +Provide wrappers for Valgrind client requests in libgcc, which are used for
> +@option{-fvalgrind-annotations}.  Requires Valgrind header files for the
> +target (in the build-time sysroot if building a cross-compiler).
> +
>  @item --with-cpu=@var{cpu}
>  @itemx --with-cpu-32=@var{cpu}
>  @itemx --with-cpu-64=@var{cpu}
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index d272b9228d..bfbe6a8bd9 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -660,6 +660,7 @@ Objective-C and Objective-C++ Dialects}.
>  -fno-stack-limit  -fsplit-stack
>  -fstrub=disable  -fstrub=strict  -fstrub=relaxed
>  -fstrub=all  -fstrub=at-calls  -fstrub=internal
> +-fvalgrind-annotations
>  -fvtable-verify=@r{[}std@r{|}preinit@r{|}none@r{]}
>  -fvtv-counts  -fvtv-debug
>  -finstrument-functions  -finstrument-functions-once
> @@ -12975,6 +12976,9 @@ can use @option{-flifetime-dse=1}.  The default 
> behavior can be
>  explicitly selected with @option{-flifetime-dse=2}.
>  @option{-flifetime-dse=0} is equivalent to @option{-fno-lifetime-dse}.
>  
> +See @option{-fvalgrind-annotations} for instrumentation that allows to
> +detect violations of standard lifetime semantics using Valgrind.
> +
>  @opindex flive-range-shrinkage
>  @item -flive-range-shrinkage
>  Attempt to decrease register pressure through register live range
> @@ -18051,6 +18055,29 @@ function attributes that tell which mode was 
> selected for each function.
>  The primary use of this option is for testing, to exercise thoroughly
>  the @code{strub} machinery.
>  
> +@opindex fvalgrind-annotations
> +@item -fvalgrind-annotations
> +Emit Valgrind client requests annotating object lifetime boundaries.
> +This allows to detect attempts to access fields of a C++ object after
> +its destructor has completed (but storage was not deallocated yet), or
> +to initialize it in advance from @code{operator new} rather than the
> +constructor.
> +
> +This instrumentation relies on presence of 
> @code{__gcc_vgmc_make_mem_undefined}
> +function that wraps the corresponding Valgrind client request. It is provided
> +by libgcc when it is configured with @samp{--enable-valgrind-interop}.
> +Otherwise, you can implement it like this:
> +
> +@smallexample
> +#include <valgrind/memcheck.h>
> +
> +void
> +__gcc_vgmc_make_mem_undefined (void *addr, size_t size)
> +@{
> +  VALGRIND_MAKE_MEM_UNDEFINED (addr, size);
> +@}
> +@end smallexample
> +
>  @opindex fvtable-verify
>  @item -fvtable-verify=@r{[}std@r{|}preinit@r{|}none@r{]}
>  This option is only available when compiling C++ code.
> diff --git a/gcc/gimple-valgrind-interop.cc b/gcc/gimple-valgrind-interop.cc
> new file mode 100644
> index 0000000000..05d9bdc660
> --- /dev/null
> +++ b/gcc/gimple-valgrind-interop.cc
> @@ -0,0 +1,125 @@
> +/* Annotate lifetime boundaries for Valgrind.
> +   Copyright (C) 2023 Free Software Foundation, Inc.
> +
> +This file is part of GCC.
> +
> +GCC is free software; you can redistribute it and/or modify it
> +under the terms of the GNU General Public License as published by the
> +Free Software Foundation; either version 3, or (at your option) any
> +later version.
> +
> +GCC is distributed in the hope that it will be useful, but WITHOUT
> +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> +FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
> +for more details.
> +
> +You should have received a copy of the GNU General Public License
> +along with GCC; see the file COPYING3.  If not see
> +<http://www.gnu.org/licenses/>.  */
> +
> +#include "config.h"
> +#include "system.h"
> +#include "coretypes.h"
> +#include "tree.h"
> +#include "function.h"
> +#include "cfg.h"
> +#include "basic-block.h"
> +#include "gimple.h"
> +#include "gimple-iterator.h"
> +#include "tree-pass.h"
> +#include "gimplify-me.h"
> +#include "fold-const.h"
> +
> +namespace {
> +
> +/* Emit VALGRIND_MAKE_MEM_UNDEFINED annotation for the object given by VAR.  
> */
> +
> +bool
> +annotate_undef (gimple_stmt_iterator *gsi, tree var)
> +{
> +  tree size = arg_size_in_bytes (TREE_TYPE (var));
> +  if (size == size_zero_node)
> +    return false;
> +
> +  tree addr = build_fold_addr_expr (var);
> +  tree decl = builtin_decl_explicit (BUILT_IN_VALGRIND_MAKE_UNDEFINED);
> +  tree call = build_call_expr (decl, 2, addr, size);
> +
> +  force_gimple_operand_gsi (gsi, call, false, NULL_TREE, false, 
> GSI_NEW_STMT);
> +  return true;
> +}
> +
> +const pass_data pass_data_instrument_valgrind = {
> +  GIMPLE_PASS, /* type */
> +  "valgrind",  /* name */
> +  OPTGROUP_NONE, /* optinfo_flags */
> +  TV_NONE, /* tv_id */
> +  PROP_cfg, /* properties_required */
> +  0, /* properties_provided */
> +  0, /* properties_destroyed */
> +  0, /* todo_flags_start */
> +  0, /* todo_flags_finish */
> +};
> +
> +}
> +
> +class pass_instrument_valgrind : public gimple_opt_pass
> +{
> +public:
> +  pass_instrument_valgrind (gcc::context *ctxt)
> +    : gimple_opt_pass (pass_data_instrument_valgrind, ctxt)
> +  {
> +  }
> +
> +  unsigned int execute (function *) final override;
> +  bool gate (function *) final override;
> +};
> +
> +bool
> +pass_instrument_valgrind::gate (function *)
> +{
> +  return flag_valgrind_annotations;
> +}
> +
> +/* Scan for GIMPLE clobbers that mark object lifetime boundaries and
> +   make them known to Valgrind by emitting corresponding client requests.  */
> +
> +unsigned int
> +pass_instrument_valgrind::execute (function *fun)
> +{
> +  bool changed = false;
> +  basic_block bb;
> +  FOR_EACH_BB_FN (bb, fun)
> +    {
> +      for (gimple_stmt_iterator gsi = gsi_start_nondebug_bb (bb);
> +        !gsi_end_p (gsi); gsi_next_nondebug (&gsi))
> +     {
> +       gimple *stmt = gsi_stmt (gsi);
> +
> +       if (gimple_clobber_p (stmt))
> +         switch (CLOBBER_KIND (gimple_assign_rhs1 (stmt)))
> +           {
> +           case CLOBBER_UNDEF:
> +           case CLOBBER_OBJECT_BEGIN:
> +           case CLOBBER_OBJECT_END:
> +             changed |= annotate_undef (&gsi, gimple_assign_lhs (stmt));
> +             break;
> +           case CLOBBER_STORAGE_BEGIN:
> +           case CLOBBER_STORAGE_END:
> +             /* Leave these for ASan.  */
> +             break;
> +           case CLOBBER_LAST:
> +           default:
> +             gcc_unreachable ();
> +           }
> +     }
> +    }
> +
> +  return changed ? TODO_update_ssa : 0;
> +}
> +
> +gimple_opt_pass *
> +make_pass_instrument_valgrind (gcc::context *ctxt)
> +{
> +  return new pass_instrument_valgrind (ctxt);
> +}
> diff --git a/gcc/passes.def b/gcc/passes.def
> index 43b416f98f..2274304321 100644
> --- a/gcc/passes.def
> +++ b/gcc/passes.def
> @@ -57,6 +57,7 @@ along with GCC; see the file COPYING3.  If not see
>    PUSH_INSERT_PASSES_WITHIN (pass_build_ssa_passes)
>        NEXT_PASS (pass_fixup_cfg);
>        NEXT_PASS (pass_build_ssa);
> +      NEXT_PASS (pass_instrument_valgrind);
>        NEXT_PASS (pass_walloca, /*strict_mode_p=*/true);
>        NEXT_PASS (pass_warn_printf);
>        NEXT_PASS (pass_warn_nonnull_compare);
> diff --git a/gcc/testsuite/g++.dg/valgrind-annotations-1.C 
> b/gcc/testsuite/g++.dg/valgrind-annotations-1.C
> new file mode 100644
> index 0000000000..49dc5a9cf1
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/valgrind-annotations-1.C
> @@ -0,0 +1,22 @@
> +/* { dg-do compile { target c++11 } } */
> +/* { dg-options "-O2 -fvalgrind-annotations -fdump-tree-optimized" } */
> +
> +#include <new>
> +
> +struct Foo
> +{
> +  int val;
> +};
> +
> +struct Bar : Foo
> +{
> +  Bar() {}
> +};
> +
> +int main ()
> +{
> +  alignas(Bar) char buf [sizeof (Bar)];
> +  Bar *obj = new(buf) Bar;
> +}
> +
> +/* { dg-final { scan-tree-dump-times 
> "__builtin___gcc_vgmc_make_mem_undefined" 1 "optimized" } } */
> diff --git a/gcc/testsuite/g++.dg/valgrind-annotations-2.C 
> b/gcc/testsuite/g++.dg/valgrind-annotations-2.C
> new file mode 100644
> index 0000000000..a8b646d076
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/valgrind-annotations-2.C
> @@ -0,0 +1,12 @@
> +/* { dg-do compile { target c++11 } } */
> +/* { dg-options "-O2 -fvalgrind-annotations -fdump-tree-optimized" } */
> +
> +struct Foo
> +{
> +  char buf [1024];
> +  Foo () {}
> +};
> +
> +Foo Obj;
> +
> +/* { dg-final { scan-tree-dump-times 
> "__builtin___gcc_vgmc_make_mem_undefined" 1 "optimized" } } */
> diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
> index 52fd57fd4c..49de431bd8 100644
> --- a/gcc/tree-pass.h
> +++ b/gcc/tree-pass.h
> @@ -441,6 +441,7 @@ extern gimple_opt_pass *make_pass_omp_device_lower 
> (gcc::context *ctxt);
>  extern gimple_opt_pass *make_pass_object_sizes (gcc::context *ctxt);
>  extern gimple_opt_pass *make_pass_early_object_sizes (gcc::context *ctxt);
>  extern gimple_opt_pass *make_pass_warn_access (gcc::context *ctxt);
> +extern gimple_opt_pass *make_pass_instrument_valgrind (gcc::context *ctxt);
>  extern gimple_opt_pass *make_pass_warn_printf (gcc::context *ctxt);
>  extern gimple_opt_pass *make_pass_warn_recursion (gcc::context *ctxt);
>  extern gimple_opt_pass *make_pass_strlen (gcc::context *ctxt);
> diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in
> index 3f77283490..ea3ba705e9 100644
> --- a/libgcc/Makefile.in
> +++ b/libgcc/Makefile.in
> @@ -436,6 +436,9 @@ LIB2ADD += $(srcdir)/hardcfr.c
>  # Stack scrubbing infrastructure.
>  @HAVE_STRUB_SUPPORT@LIB2ADD += $(srcdir)/strub.c
>  
> +# Wrappers for Valgrind client requests.
> +LIB2ADD_ST += $(srcdir)/valgrind-interop.c
> +
>  # While emutls.c has nothing to do with EH, it is in LIB2ADDEH*
>  # instead of LIB2ADD because that's the way to be sure on some targets
>  # (e.g. *-*-darwin*) only one copy of it is linked.
> diff --git a/libgcc/config.in b/libgcc/config.in
> index 8f7dd437b0..a77e9411fc 100644
> --- a/libgcc/config.in
> +++ b/libgcc/config.in
> @@ -3,6 +3,9 @@
>  /* Define to the .hidden-like directive if it exists. */
>  #undef AS_HIDDEN_DIRECTIVE
>  
> +/* Build Valgrind request wrappers */
> +#undef ENABLE_VALGRIND_INTEROP
> +
>  /* Define to 1 if the assembler supports AVX. */
>  #undef HAVE_AS_AVX
>  
> @@ -64,6 +67,9 @@
>  /* Define to 1 if you have the <unistd.h> header file. */
>  #undef HAVE_UNISTD_H
>  
> +/* Define to 1 if you have the <valgrind/memcheck.h> header file. */
> +#undef HAVE_VALGRIND_MEMCHECK_H
> +
>  /* Define to 1 if __getauxval is available. */
>  #undef HAVE___GETAUXVAL
>  
> diff --git a/libgcc/configure b/libgcc/configure
> index 3671d9b1a1..431c028af9 100755
> --- a/libgcc/configure
> +++ b/libgcc/configure
> @@ -716,6 +716,7 @@ with_system_libunwind
>  enable_cet
>  enable_explicit_exception_frame_registration
>  enable_tm_clone_registry
> +enable_valgrind_interop
>  with_glibc_version
>  enable_tls
>  with_gcc_major_version_only
> @@ -1360,6 +1361,8 @@ Optional Features:
>                            start, for use e.g. for compatibility with
>                            installations without PT_GNU_EH_FRAME support
>    --disable-tm-clone-registry    disable TM clone registry
> +  --enable-valgrind-interop
> +                          build wrappers for Valgrind client requests
>    --enable-tls            Use thread-local storage [default=yes]
>  
>  Optional Packages:
> @@ -4467,7 +4470,8 @@ as_fn_arith $ac_cv_sizeof_long_double \* 8 && 
> long_double_type_size=$as_val
>  
>  for ac_header in inttypes.h stdint.h stdlib.h ftw.h \
>       unistd.h sys/stat.h sys/types.h \
> -     string.h strings.h memory.h sys/auxv.h sys/mman.h
> +     string.h strings.h memory.h sys/auxv.h sys/mman.h \
> +     valgrind/memcheck.h
>  do :
>    as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
>  ac_fn_c_check_header_preproc "$LINENO" "$ac_header" "$as_ac_Header"
> @@ -5025,6 +5029,22 @@ fi
>  
>  
>  
> +# Check whether --enable-valgrind-interop was given.
> +if test "${enable_valgrind_interop+set}" = set; then :
> +  enableval=$enable_valgrind_interop;
> +else
> +  enable_valgrind_interop=no
> +fi
> +
> +if test $enable_valgrind_interop != no; then
> +  if test $ac_cv_header_valgrind_memcheck_h = no; then
> +    as_fn_error $? "--enable-valgrind-interop: valgrind/memcheck.h not 
> found" "$LINENO" 5
> +  fi
> +
> +$as_echo "#define ENABLE_VALGRIND_INTEROP 1" >>confdefs.h
> +
> +fi
> +
>  { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU 
> ld" >&5
>  $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; }
>  if ${acl_cv_prog_gnu_ld+:} false; then :
> diff --git a/libgcc/configure.ac b/libgcc/configure.ac
> index 467f5e63ef..d19f5e7e84 100644
> --- a/libgcc/configure.ac
> +++ b/libgcc/configure.ac
> @@ -231,7 +231,8 @@ AC_SUBST(long_double_type_size)
>  
>  AC_CHECK_HEADERS(inttypes.h stdint.h stdlib.h ftw.h \
>       unistd.h sys/stat.h sys/types.h \
> -     string.h strings.h memory.h sys/auxv.h sys/mman.h)
> +     string.h strings.h memory.h sys/auxv.h sys/mman.h \
> +     valgrind/memcheck.h)
>  AC_HEADER_STDC
>  
>  # Check for decimal float support.
> @@ -303,6 +304,18 @@ esac
>  ])
>  AC_SUBST([use_tm_clone_registry])
>  
> +AC_ARG_ENABLE([valgrind-interop],
> +              [AC_HELP_STRING([--enable-valgrind-interop],
> +                              [build wrappers for Valgrind client 
> requests])],
> +              [],
> +              [enable_valgrind_interop=no])
> +if test $enable_valgrind_interop != no; then
> +  if test $ac_cv_header_valgrind_memcheck_h = no; then
> +    AC_MSG_ERROR([--enable-valgrind-interop: valgrind/memcheck.h not found])
> +  fi
> +  AC_DEFINE(ENABLE_VALGRIND_INTEROP, 1, [Build Valgrind request wrappers])
> +fi
> +
>  AC_LIB_PROG_LD_GNU
>  
>  AC_MSG_CHECKING([for thread model used by GCC])
> diff --git a/libgcc/libgcc2.h b/libgcc/libgcc2.h
> index 750670e8ca..ee4500adc1 100644
> --- a/libgcc/libgcc2.h
> +++ b/libgcc/libgcc2.h
> @@ -558,6 +558,8 @@ extern void __strub_enter (void **);
>  extern void __strub_update (void**);
>  extern void __strub_leave (void **);
>  
> +extern void __gcc_vgmc_make_mem_undefined (void *, size_t);
> +
>  #ifndef HIDE_EXPORTS
>  #pragma GCC visibility pop
>  #endif
> diff --git a/libgcc/valgrind-interop.c b/libgcc/valgrind-interop.c
> new file mode 100644
> index 0000000000..fdb8d41bc5
> --- /dev/null
> +++ b/libgcc/valgrind-interop.c
> @@ -0,0 +1,40 @@
> +/* Wrappers for Valgrind client requests.
> +   Copyright (C) 2023 Free Software Foundation, Inc.
> +
> +This file is part of GCC.
> +
> +GCC is free software; you can redistribute it and/or modify it under
> +the terms of the GNU General Public License as published by the Free
> +Software Foundation; either version 3, or (at your option) any later
> +version.
> +
> +GCC is distributed in the hope that it will be useful, but WITHOUT ANY
> +WARRANTY; without even the implied warranty of MERCHANTABILITY or
> +FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
> +for more details.
> +
> +Under Section 7 of GPL version 3, you are granted additional
> +permissions described in the GCC Runtime Library Exception, version
> +3.1, as published by the Free Software Foundation.
> +
> +You should have received a copy of the GNU General Public License and
> +a copy of the GCC Runtime Library Exception along with this program;
> +see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
> +<http://www.gnu.org/licenses/>.  */
> +
> +#include "tsystem.h"
> +#include "auto-target.h"
> +
> +#ifdef ENABLE_VALGRIND_INTEROP
> +
> +#include <valgrind/memcheck.h>
> +
> +/* Externally callable wrapper for Valgrind Memcheck client request:
> +   declare SIZE bytes of memory at address ADDR as uninitialized.  */
> +
> +void
> +__gcc_vgmc_make_mem_undefined (void *addr, size_t size)
> +{
> +  VALGRIND_MAKE_MEM_UNDEFINED (addr, size);
> +}
> +#endif
> 

Reply via email to