On Wed, Apr 22, 2026 at 04:29:41PM +0200, Richard Biener wrote:
> On Thu, Jan 1, 2026 at 6:03 PM Lewis Hyatt <[email protected]> wrote:
> >
> > After the previous changes in this series, the LTO front end always has an
> > appropriate linemap structure for interpreting diagnostic pragmas, so it is
> > straightforward to implement them, as is done here.
> >
> > The pragmas are streamed out in each linemap section; since all locations
> > from a given linemap section will be contiguous in the reconstructed
> > linemap, they are automatically ordered properly for the existing diagnostic
> > pragma infrastructure to work as-is.
> >
> > One wrinkle is that a single function may have been streamed out in multiple
> > sections. (For example, an inline function will be streamed out in all
> > partitions that need it.) In this case, when merging them, LTO keeps only
> > one of the sections, as directed by the linker resolution, so the diagnostic
> > pragmas that will be in force (in case they were not the same for the
> > different translation units) will be whichever were applicable to the
> > section LTO decided to keep.
> 
> LGTM if the rest of the series is approved.
> 
> Thanks,
> Richard.
> 

Hi Richard-

Firstly, thank you again for your time in reviewing these patches. I thought
everything was finally across the finish line, but as I was reviewing the
patches one more time before pushing them, I realized there is one small
problem with the new approach. Could I please ask you to look at one more
patch which addresses that? I attached it here as an incremental change to
the rest of the series, but I would propose to squash it into the other
patches before pushing.

What I missed was that the LTO front end has a mode of operation for
incremental linking. I had tested that my new approach works fine with
"ld -r" (provided that -frandom-seed is not used to remove uniqueness from
the section names), but the LTO front end version of that (which you get
when using, say, "gcc -r -flto") does more than just copy the sections; it
actually reads all the decls and then re-outputs a new object file with a
new identifier, which contains a new decls section plus copies of the
function and constructor sections. This means the linemap sections also need
to get copied into the output file, and also, it means that an input file to
the LTO front end could possibly contain more than one linemap, which was
not something I had considered. (I had anticipated that inputs contained
just one linemap, except that in LTRANS mode, there would also be one file
containing all necessary linemaps copied during WPA).

It wasn't too bad to adapt things to work fine in this case too, so the
attached patch is not too huge of a change as far as LTO. A lot of the patch
consists of changes to testsuite/lib/lto.exp to enable testing the
incremental link mode. There was not any test coverage previously for this
sort of operation:

g++ -flto -c t{1,2,3}.cc
g++ -flto -r -o t12.o t{1,2}.o
g++ -flto -o t t12.o t3.o

(i.e., partial linking of some files and then a final link of all of them
together), which is why I didn't see this problem initially. The patch adds
a new directive { dg-lto-do incr-link }, which tests a sequence like the
above, similar to how { dg-lto-do ar-link } already works. gccint was
missing documentation of ar-link, so I added something for that as well as
for incr-link.

I tested everything again on x86-64, aarch64 (cfarm425), amd64 (cfarm420),
sparc 32-bit (cfarm216), and ppc64be (cfarm121), including bootstrap with
bootstrap-lto, and it looks good. Please let me know if it looks OK, in
which case, I am ready to commit the series now. Thanks!

-Lewis
gcc/ChangeLog:

        * doc/sourcebuild.texi: Document ar-link and incr-link options to
        dg-lto-do directive.
        * lto-streamer-in.cc (create_loc_map): Handle incrementally-linked
        LTO files, which may contain more than one linemap section.
        (lto_location_cache::override_loc_map): Replace with new inline
        function set_linemap_offset().
        (lto_location_cache::input_location_and_block): Handle multiple
        input linemaps using linemap_offset member.
        (lto_read_body_or_constructor): Likewise.
        * lto-streamer-out.cc (location_output::record_location): Handle
        incremental linking location output the same way as WPA does.
        (copy_function_or_variable): Handle multiple linemaps when copying
        function bodies.
        (copy_linemap_section): Support multiple linemap sections when
        copying them for WPA and incremental linking.
        (lto_copy_linemaps): Likewise.
        (copy_linemap_sections): New function.
        (produce_asm_for_decls): Implement copying of linemaps for
        INCREMENTAL_LINK_LTO mode.
        * lto-streamer.h (lto_linemap_output_id): New function.

gcc/lto/ChangeLog:

        * lto-common.cc (linemap_section_id): New function.
        (create_subid_section_table): Record the number of linemap sections
        contained in each LTO input file.
        (lto_file_read): Set the order member to reflect how many linemap
        sections were found.

gcc/testsuite/ChangeLog:

        * gcc.dg/lto/README: Update to document ar-link and incr-link.
        * gcc.dg/lto/pr80922-2_0.c: Switch to incr-link mode.
        * lib/lto.exp: Support incr-link directive throughout.
---
 gcc/doc/sourcebuild.texi               |  9 ++++-
 gcc/lto-streamer-in.cc                 | 32 ++++------------
 gcc/lto-streamer-out.cc                | 51 ++++++++++++++++++--------
 gcc/lto-streamer.h                     | 17 ++++++++-
 gcc/lto/lto-common.cc                  | 27 +++++++++++++-
 gcc/testsuite/gcc.dg/lto/README        | 17 +++++----
 gcc/testsuite/gcc.dg/lto/pr80922-2_0.c |  2 +-
 gcc/testsuite/lib/lto.exp              | 41 +++++++++++++++------
 8 files changed, 132 insertions(+), 64 deletions(-)

diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 2396e327cda..5b8cf8eecb4 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -4112,12 +4112,19 @@ it is executed.  It is one of:
 Compile with @option{-c} to produce a relocatable object file.
 @item link
 Compile, assemble, and link to produce an executable file.
+@item ar-link
+Similar to @code{link}, but combine all but the first source file into
+an archive file before the final link.
+@item incr-link
+As with @code{ar-link}, but combine the files into an object file
+using incremental linking, rather than an archive file.  This enables
+testing the incremental linking features of the LTO front end.
 @item run
 Produce and run an executable file, which is expected to return
 an exit code of 0.
 @end table
 
-The default is @code{assemble}.  That can be overridden for a set of
+The default is @code{run}.  That can be overridden for a set of
 tests by redefining @code{dg-do-what-default} within the @code{.exp}
 file for those tests.
 
diff --git a/gcc/lto-streamer-in.cc b/gcc/lto-streamer-in.cc
index 72a09554dcd..bcf0c025ca0 100644
--- a/gcc/lto-streamer-in.cc
+++ b/gcc/lto-streamer-in.cc
@@ -526,8 +526,11 @@ create_loc_map (lto_file_decl_data *file_data, unsigned 
linemap_id)
                     "Ran out of locations while reading linemap section #%u",
                     linemap_id);
       loc_map->map[map_idx - 1] = map - line_table->info_ordinary.maps;
-      if (flag_wpa)
-       lto_register_linemap_for_output (map_idx, file_data->order + 1);
+      if (flag_wpa || flag_incremental_link == INCREMENTAL_LINK_LTO)
+       {
+         const auto out_id = lto_linemap_output_id (linemap_id, file_data);
+         lto_register_linemap_for_output (map_idx, out_id);
+       }
     }
 
   /* Process the diagnostics classification history.  */
@@ -588,20 +591,6 @@ get_loc_map (lto_file_decl_data *file_data, unsigned 
linemap_id)
 }
 
 
-/* Force the locations read from now on to be interpreted relative to a
-   different lto_loc_map than the one indicated in the LTO section data.
-   This allows function sections copied for LTRANS to find the linemap
-   section that goes with them.  */
-
-void
-lto_location_cache::override_loc_map (unsigned linemap_id)
-{
-  gcc_checking_assert (decl_data);
-  cur_loc_map = get_loc_map (decl_data, linemap_id);
-  loc_map_override_p = true;
-}
-
-
 /* Read a location bitpack from bit pack BP and either update *LOC directly or
    add it to the location cache.  It is necessary to call apply_location_cache
    to guarantee that *LOC has been updated.  */
@@ -628,13 +617,7 @@ lto_location_cache::input_location_and_block (location_t 
*dest,
       if (linemap_change)
        {
          const unsigned linemap_id = bp_unpack_var_len_unsigned (bp);
-         if (loc_map_override_p)
-           /* We should only ever be overriding the loc map for functions
-              copied during WPA, and those would always have used just a single
-              linemap section.  */
-           gcc_assert (linemap_id == 0);
-         else
-           cur_loc_map = get_loc_map (decl_data, linemap_id);
+         cur_loc_map = get_loc_map (decl_data, linemap_id + linemap_offset);
        }
       bp_unpack_delta (bp, stream_map_idx);
       bp_unpack_delta (bp, stream_loc_offset);
@@ -1702,8 +1685,7 @@ lto_read_body_or_constructor (struct lto_file_decl_data 
*file_data, struct symta
       decl_state = lto_get_function_in_decl_state (file_data, fn_decl);
       gcc_assert (decl_state);
       file_data->current_decl_state = decl_state;
-      if (decl_state->linemap_id)
-       data_in->location_cache.override_loc_map (decl_state->linemap_id);
+      data_in->location_cache.set_linemap_offset (decl_state->linemap_id);
 
       /* Set up the struct function.  */
       from = data_in->reader_cache->nodes.length ();
diff --git a/gcc/lto-streamer-out.cc b/gcc/lto-streamer-out.cc
index f0d9dbdc5fe..230670da494 100644
--- a/gcc/lto-streamer-out.cc
+++ b/gcc/lto-streamer-out.cc
@@ -227,10 +227,10 @@ location_output::record_location (location_t loc)
 
   const auto map = linemap_check_ordinary (linemap_lookup (line_table, loc));
 
-  if (flag_wpa)
+  if (flag_wpa || flag_incremental_link == INCREMENTAL_LINK_LTO)
     {
-      /* In WPA, we don't create new locations, we only work with what was 
read,
-        so we will re-output it the same way.  */
+      /* In these modes, we don't create new locations, we only work with what
+        was read, so we will re-output the locations in the same way.  */
       gcc_checking_assert (orig_map_ids.length ()
                           == LINEMAPS_ORDINARY_USED (line_table));
       gcc_checking_assert (!map->m_range_bits);
@@ -2820,7 +2820,8 @@ copy_function_or_variable (struct symtab_node *node, int 
output_order)
   lto_end_section ();
 
   /* Make sure the reader knows which linemap section to use.  */
-  out_state->linemap_id = file_data->order + 1;
+  out_state->linemap_id = lto_linemap_output_id (in_state->linemap_id,
+                                                file_data);
 }
 
 /* Wrap symbol references in *TP inside a type-preserving MEM_REF.  */
@@ -2899,14 +2900,13 @@ produce_lto_section ()
    is also streamed out.  */
 
 static void
-copy_linemap_section (lto_file_decl_data *file_data)
+copy_linemap_section (lto_file_decl_data *file_data, unsigned order)
 {
   const auto in_section_name
-    = lto_get_section_name (LTO_section_linemap, nullptr, 0,
-                           file_data);
+    = lto_get_section_name (LTO_section_linemap, nullptr, order, file_data);
   const auto out_section_name
-    = lto_get_section_name (LTO_section_linemap, nullptr, file_data->order + 1,
-                           nullptr);
+    = lto_get_section_name (LTO_section_linemap, nullptr,
+                           lto_linemap_output_id (order, file_data), nullptr);
 
   if (streamer_dump_file)
     fprintf (streamer_dump_file, "Copying linemap section from %s to %s\n",
@@ -2914,7 +2914,7 @@ copy_linemap_section (lto_file_decl_data *file_data)
 
   size_t len;
   const auto data = lto_get_raw_section_data (file_data, LTO_section_linemap,
-                                             nullptr, 0, &len);
+                                             nullptr, order, &len);
   gcc_assert (data);
   lto_begin_section (out_section_name, false);
   free (in_section_name);
@@ -2925,6 +2925,12 @@ copy_linemap_section (lto_file_decl_data *file_data)
   lto_end_section ();
 }
 
+static void
+copy_linemap_sections (lto_file_decl_data *file_data)
+{
+  for (unsigned i = 0; i != file_data->num_linemap_sections; ++i)
+    copy_linemap_section (file_data, i);
+}
 
 /* Copy all the linemaps we read into an object file so LTRANS can find them
    later.  */
@@ -2935,9 +2941,15 @@ lto_copy_linemaps ()
   timevar_push (TV_IPA_LTO_LINEMAP_COPY);
   lto_streamer_init ();
   lto_push_out_decl_state (nullptr);
-  produce_lto_section ();
+
+  /* In WPA, we write these out to a standalone file; give it an LTO header
+     section.  */
+  if (flag_wpa)
+    produce_lto_section ();
+
   for (auto file_data = lto_get_file_decl_data (); *file_data; ++file_data)
-    copy_linemap_section (*file_data);
+    copy_linemap_sections (*file_data);
+
   lto_pop_out_decl_state ();
   timevar_pop (TV_IPA_LTO_LINEMAP_COPY);
 }
@@ -3714,8 +3726,15 @@ produce_asm_for_decls (void)
   if (lto_stream_offload_p)
     lto_write_mode_table ();
 
-  /* Write the linemap section.  During WPA, we copy all needed linemaps later,
-     and do not generate our own new one here.  */
-  if (!flag_wpa)
-    loc_output.produce_linemap_section ();
+  /* Copy or write the linemap section(s) as needed.  For incremental LTO, we
+     copy them into the output file now.  For WPA, we will copy them into a
+     dedicated file later.  Otherwise, we create a new one from scratch and
+     output it now.  */
+  if (flag_incremental_link == INCREMENTAL_LINK_LTO)
+    lto_copy_linemaps ();
+  else if (!flag_wpa)
+    {
+      gcc_checking_assert (!in_lto_p);
+      loc_output.produce_linemap_section ();
+    }
 }
diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h
index 13330267d79..27126a42185 100644
--- a/gcc/lto-streamer.h
+++ b/gcc/lto-streamer.h
@@ -287,7 +287,7 @@ public:
   void input_location_and_block (location_t *dest, struct bitpack_d *bp,
                                 class lto_input_block *ib,
                                 class data_in *data_in);
-  void override_loc_map (unsigned linemap_id);
+  void set_linemap_offset (unsigned offset) { linemap_offset = offset; }
 
   explicit lto_location_cache (lto_file_decl_data *loc_data)
     : decl_data{loc_data}
@@ -324,7 +324,7 @@ private:
   /* Which linemap section we are using.  */
   lto_file_decl_data *const decl_data;
   const lto_loc_map *cur_loc_map = nullptr;
-  bool loc_map_override_p = false;
+  unsigned linemap_offset = 0;
 
   /* The location cache.  */
   auto_vec<cached_location> loc_cache;
@@ -637,11 +637,24 @@ struct GTY(()) lto_file_decl_data
 
   unsigned mode_bits;
 
+  /* Number of linemap sections contained in this file.  There is typically 
only
+     1, but WPA and INCREMENTAL_LINK_LTO modes may create files with more than
+     one linemap.  */
+  unsigned num_linemap_sections;
+
   /* Location maps for locations streamed in this file.  */
   lto_file_decl_data *loc_map_decl_data;
   vec<lto_loc_map *, va_gc> *loc_maps;
 };
 
+/* Given an input linemap ID, compute how it will be known in the output, given
+   that the output could be the combination of multiple input files.  */
+inline unsigned
+lto_linemap_output_id (unsigned linemap_id, const lto_file_decl_data 
*file_data)
+{
+  return linemap_id + file_data->order;
+}
+
 typedef struct lto_file_decl_data *lto_file_decl_data_ptr;
 
 struct lto_char_ptr_base
diff --git a/gcc/lto/lto-common.cc b/gcc/lto/lto-common.cc
index 2c3f9930e30..c32db430de9 100644
--- a/gcc/lto/lto-common.cc
+++ b/gcc/lto/lto-common.cc
@@ -2206,6 +2206,25 @@ lto_section_with_id (const char *name, unsigned 
HOST_WIDE_INT *id)
   return sscanf (s, "." HOST_WIDE_INT_PRINT_HEX_PURE, id) == 1;
 }
 
+/* Return the linemap ID if NAME refers to an LTO linemap section,
+   otherwise -1U.  */
+
+static unsigned linemap_section_id (const char *name)
+{
+  const int prefix_len = strlen (section_name_prefix);
+  gcc_checking_assert (!strncmp (name, section_name_prefix, prefix_len));
+  name += prefix_len;
+  if (*name++ != '.')
+    return -1U;
+  const auto lm_name = lto_section_name[LTO_section_linemap];
+  const int lm_len = strlen (lm_name);
+  if (strncmp (name, lm_name, lm_len))
+    return -1U;
+  name += lm_len;
+  unsigned linemap_id;
+  return sscanf (name, ".%u", &linemap_id) == 1 ? linemap_id : -1U;
+}
+
 /* Create file_data of each sub file id.  */
 
 static int
@@ -2245,6 +2264,9 @@ create_subid_section_table (struct lto_section_slot *ls, 
splay_tree file_ids,
       list->last = file_data;
     }
 
+  file_data->num_linemap_sections = MAX (file_data->num_linemap_sections,
+                                        linemap_section_id (ls->name) + 1);
+
   /* Copy section into sub module hash table.  */
   new_name = XDUPVEC (char, ls->name, strlen (ls->name) + 1);
   s_slot.name = new_name;
@@ -2390,7 +2412,10 @@ lto_file_read (lto_file *file, FILE *resolution_file, 
int *count)
   static int order = 0;
   for (file_data = file_list.first; file_data != NULL;
        file_data = file_data->next)
-    lto_create_files_from_ids (file, file_data, count, order++);
+    {
+      lto_create_files_from_ids (file, file_data, count, order);
+      order += file_data->num_linemap_sections;
+    }
 
   splay_tree_delete (file_ids);
   htab_delete (section_hash_table);
diff --git a/gcc/testsuite/gcc.dg/lto/README b/gcc/testsuite/gcc.dg/lto/README
index 1ee8b00dee8..04c05a2ee1d 100644
--- a/gcc/testsuite/gcc.dg/lto/README
+++ b/gcc/testsuite/gcc.dg/lto/README
@@ -44,12 +44,15 @@ where there is a single file named 'foo_0.C'.
 
 === The dg-lto-do Directive ==
 
-The only supported dg-lto-do options are 'assemble', 'run' and 'link'.
-Additionally, these can only be used in the main file.  If
-'assemble' is used, only the individual object files are
-generated.  If 'link' is used, the final executable is generated
-but not executed (in this case, function main() needs to exist
-but it does not need to do anything).  If 'run' is used, the
-final executable is generated and the resulting binary executed.
+The supported dg-lto-do options are 'assemble', 'run', 'link', 'ar-link',
+and 'incr-link'.  This option can only be used in the main file.  If
+'assemble' is used, only the individual object files are generated.  If
+'link' is used, the final executable is generated but not executed (in
+this case, function main() needs to exist but it does not need to do
+anything).  If 'run' is used, the final executable is generated and the
+resulting binary executed.  'ar-link' and 'incr-link' are similar to
+'link', except that the non-main object files are combined together before
+the final link, into either an archive, in the former case, or an object
+file via incremental linking, in the latter.
 
 The default value for dg-lto-do is 'run'.
diff --git a/gcc/testsuite/gcc.dg/lto/pr80922-2_0.c 
b/gcc/testsuite/gcc.dg/lto/pr80922-2_0.c
index 660ddc1c014..2bc46209157 100644
--- a/gcc/testsuite/gcc.dg/lto/pr80922-2_0.c
+++ b/gcc/testsuite/gcc.dg/lto/pr80922-2_0.c
@@ -2,7 +2,7 @@
 /* This is similar to pr80922-1, but myfree() and myfree2() are split into
    separate objects, so that they use two different line maps.  */
 
-/* { dg-lto-do link } */
+/* { dg-lto-do incr-link } */
 /* { dg-lto-additional-options "-O2 -Wfree-nonheap-object" } */
 
 void myfree (void *ptr1, void *ptr2, void *ptr3, void *ptr4)
diff --git a/gcc/testsuite/lib/lto.exp b/gcc/testsuite/lib/lto.exp
index 54a52cea760..f74e1b19335 100644
--- a/gcc/testsuite/lib/lto.exp
+++ b/gcc/testsuite/lib/lto.exp
@@ -417,7 +417,9 @@ proc lto-link-and-maybe-run { testname objlist dest optall 
optfile optstr } {
     }
 
     # Check for diagnostics specified by directives
-    set comp_output [lto_handle_diagnostics $comp_output $optstr]
+    if { ! [string equal "incr-link" $optstr] } {
+       set comp_output [lto_handle_diagnostics $comp_output $optstr]
+    }
 
     # Prune unimportant visibility warnings before checking output.
     set comp_output [lto_prune_warns $comp_output]
@@ -432,7 +434,8 @@ proc lto-link-and-maybe-run { testname objlist dest optall 
optfile optstr } {
 
     # Return if we only needed to link.
     if { ![string compare "link" $compile_type] \
-        || ![string compare "ar-link" $compile_type] } {
+        || ![string compare "ar-link" $compile_type] \
+        || ![string compare "incr-link" $compile_type] } {
        return
     }
 
@@ -578,6 +581,8 @@ proc lto-get-options-main { src } {
                set compile_type "link"
            } elseif { ![string compare "ar-link" $dgdo] } {
                set compile_type "ar-link"
+           } elseif { ![string compare "incr-link" $dgdo] } {
+               set compile_type "incr-link"
            } else {
                warning "lto.exp does not support dg-lto-do $dgdo"
            }
@@ -772,8 +777,12 @@ proc lto-execute-1 { src1 sid } {
 
     # The test needs to build all but the main file into an archive and then
     # link them all together.
-    if { ![string compare "ar-link" $compile_type] } {
+    set is_incr_link [string equal "incr-link" $compile_type]
+    set is_ar_link [string equal "ar-link" $compile_type]
+    if { $is_ar_link } {
         set arname "${sid}_${base}.a"
+    } elseif { $is_incr_link } {
+        set arname "${sid}_${base}.o"
     }
 
     # Remove the $srcdir and $tmpdir prefixes from $src1.  (It would
@@ -842,13 +851,20 @@ proc lto-execute-1 { src1 sid } {
 
        # Bundle all but the main file into an archive. Update objlist to only
        # have the archive and the last file.
-       if { ![string compare "ar-link" $compile_type] } {
+       # Only attempt the incr-link mode if the linker plugin is explicitly in 
use.
+       set sav_compile_type "$compile_type"
+       set sav_obj_list "$obj_list"
+       if { $is_incr_link && [lsearch -exact "$option" "-fuse-linker-plugin"] 
< 0 } {
+           set compile_type "link"
+       } elseif { $is_incr_link || $is_ar_link } {
            set mainsrc [lindex $obj_list 0]
            set obj_list [lrange $obj_list 1 end]
-           lto-build-archive \
-               "[lindex $obj_list 1]-[lindex $obj_list end]" \
-               $obj_list $arname
-
+           set testname "[lindex $obj_list 1]-[lindex $obj_list end]"
+           if { $is_incr_link } {
+               lto-link-and-maybe-run $testname $obj_list $arname "-r" "" 
"incr-link"
+           } else {
+               lto-build-archive $testname $obj_list $arname
+           }
            set obj_list ""
            lappend obj_list $mainsrc
            lappend obj_list $arname
@@ -857,7 +873,7 @@ proc lto-execute-1 { src1 sid } {
 
        # Link (using the compiler under test), run, and clean up tests.
        if { ![string compare "run" $compile_type] \
-            || ![string compare "ar-link" $compile_type] \
+            || $is_ar_link || $is_incr_link \
             || ![string compare "link" $compile_type] } {
 
            # Filter out any link options we were asked to suppress.
@@ -874,7 +890,7 @@ proc lto-execute-1 { src1 sid } {
                $obj_list $execname $filtered "${additional-flags} 
${dg-extra-ld-options}" \
                    $filtered
 
-           if (![string compare "ar-link" $compile_type]) {
+           if { $is_ar_link || $is_incr_link } {
                file_on_host delete $arname
              }
        }
@@ -923,7 +939,7 @@ proc lto-execute-1 { src1 sid } {
        unset testname_with_flags
        
        if { ![string compare "run" $compile_type] \
-            || ![string compare "ar-link" $compile_type] \
+            || $is_ar_link || $is_incr_link \
             || ![string compare "link" $compile_type] } {
            file_on_host delete $execname
        }
@@ -931,6 +947,9 @@ proc lto-execute-1 { src1 sid } {
        if {$sid eq "f_lto"} {
            cleanup-modules ""
        }
+
+       set compile_type "$sav_compile_type"
+       set obj_list "$sav_obj_list"
     }
 }
 

Reply via email to