On Mon, Jul 08, 2024 at 02:24:14PM -0400, Jason Merrill wrote:
> On 7/6/24 10:13 PM, Nathaniel Shead wrote:
> > Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?
> > 
> > I have also been working on a patch that uses the locations of
> > using-decls in 'diagnose_name_conflict' and 'duplicate_decls' calls, but
> > that will need a fair bit more work that I'll probaby put off for the
> > meantime.  Otherwise, as far as I can tell there's no circumstance when
> > modules-imported namespace-scope USING_DECLs have their locations
> > printed (hence the lack of tests), so I'm happy to defer this patch
> > until I've made something I can actually test.
> > 
> > An alternative approach here (rather than giving locations to OVERLOADs)
> > would be to rewrite the modules handling to not using OVERLOADs
> > internally for non-function usings, that way we can attach the location
> > to those USING_DECLs.  I went this way because I felt having locations
> > in OVL_USING_P overloads would be useful anyway, but happy to try that
> > route instead if you're uncomfortable increasing the size of most
> > OVERLOADs for something largely unused.
> 
> That sounds better to me.

OK.  Just for some additional context, the diagnostics I was thinking of
were in regards to PR c++/106851; currently the 'conflicts with' for
such declarations just point to an apparently unrelated declaration in a
different namespace, and provides no indication of the using-declaration
that brought it into scope.  Ideally I'd like to add another "note: brought
into scope here" message for all such conflicts with using-decls, but
that means that we need to actually track this for function using-decls
too.

That said, I imagine we could do this by instead of having a flag on the
OVERLOAD, instead have the OVERLOAD wrap a USING_DECL that has this
location on it.  Which may be slightly less confusing, and should also
optimise for the (I expect?) common case of overloads not being usings.

Nathaniel

> 
> > -- >8 --
> > 
> > This is used by module streaming to track locations of USING_DECLs (that
> > are internally wrapped and unwrapped as OVERLOADs for consistency with
> > function usings).  No testcases with this patch as there aren't any easy
> > ways to actually cause a diagnostic that uses this information yet;
> > that'll come in a later patch.
> > 
> > gcc/cp/ChangeLog:
> > 
> >     * cp-tree.h (OVL_SOURCE_LOCATION): New.
> >     (struct tree_overload): Add loc field.
> >     (class ovl_iterator): New member function.
> >     * module.cc (depset::hash::add_binding_entity): Add parameter.
> >     Track locations of usings.
> >     (depset::hash::find_dependencies): Note locations of usings.
> >     (module_state::write_cluster): Write locations of usings.
> >     (module_state::read_cluster): Read locations of usings.
> >     * name-lookup.cc (ovl_iterator::source_location): New.
> >     (walk_module_binding): Add parameter to callback.  Provide
> >     locations of usings.
> >     * name-lookup.h (walk_module_binding): Add parameter to
> >     callback.
> >     * ptree.cc (cxx_print_xnode): Write using location.
> >     * tree.cc (ovl_insert): Initialise source location for usings.
> >     (lookup_maybe_add): Propagate source location for usings.
> > 
> > Signed-off-by: Nathaniel Shead <nathanielosh...@gmail.com>
> > ---
> >   gcc/cp/cp-tree.h      |  6 ++++++
> >   gcc/cp/module.cc      | 29 +++++++++++++++++++----------
> >   gcc/cp/name-lookup.cc | 32 ++++++++++++++++++++++++++------
> >   gcc/cp/name-lookup.h  |  3 ++-
> >   gcc/cp/ptree.cc       |  6 ++++++
> >   gcc/cp/tree.cc        |  2 ++
> >   6 files changed, 61 insertions(+), 17 deletions(-)
> > 
> > diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> > index 8732b7dc71b..cc7c1947f9e 100644
> > --- a/gcc/cp/cp-tree.h
> > +++ b/gcc/cp/cp-tree.h
> > @@ -824,6 +824,10 @@ typedef struct ptrmem_cst * ptrmem_cst_t;
> >   /* The name of the overload set.  */
> >   #define OVL_NAME(NODE) DECL_NAME (OVL_FIRST (NODE))
> > +/* The source location of this OVL_USING_P overload.  */
> > +#define OVL_SOURCE_LOCATION(NODE) \
> > +  (((struct tree_overload*)OVERLOAD_CHECK (NODE))->loc)
> > +
> >   /* Whether this is a set of overloaded functions.  TEMPLATE_DECLS are
> >      always wrapped in an OVERLOAD, so we don't need to check them
> >      here.  */
> > @@ -838,6 +842,7 @@ typedef struct ptrmem_cst * ptrmem_cst_t;
> >   struct GTY(()) tree_overload {
> >     struct tree_common common;
> >     tree function;
> > +  location_t loc;
> >   };
> >   /* Iterator for a 1 dimensional overload.  Permits iterating over the
> > @@ -895,6 +900,7 @@ class ovl_iterator {
> >     }
> >     bool purview_p () const;
> >     bool exporting_p () const;
> > +  location_t source_location () const;
> >    public:
> >     tree remove_node (tree head)
> > diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
> > index f5966fc8c1c..5bb3e824acb 100644
> > --- a/gcc/cp/module.cc
> > +++ b/gcc/cp/module.cc
> > @@ -2581,7 +2581,7 @@ public:
> >       void add_namespace_context (depset *, tree ns);
> >     private:
> > -    static bool add_binding_entity (tree, WMB_Flags, void *);
> > +    static bool add_binding_entity (tree, WMB_Flags, void *, location_t);
> >     public:
> >       bool add_namespace_entities (tree ns, bitmap partitions);
> > @@ -13122,7 +13122,8 @@ struct add_binding_data
> >   /* Return true if we are, or contain something that is exported.  */
> >   bool
> > -depset::hash::add_binding_entity (tree decl, WMB_Flags flags, void *data_)
> > +depset::hash::add_binding_entity (tree decl, WMB_Flags flags, void *data_,
> > +                             location_t loc)
> >   {
> >     auto data = static_cast <add_binding_data *> (data_);
> >     decl = strip_using_decl (decl);
> > @@ -13185,7 +13186,6 @@ depset::hash::add_binding_entity (tree decl, 
> > WMB_Flags flags, void *data_)
> >             {
> >               if (!(flags & WMB_Hidden))
> >                 d->clear_hidden_binding ();
> > -             OVL_PURVIEW_P (d->get_entity ()) = true;
> >               if (flags & WMB_Export)
> >                 OVL_EXPORT_P (d->get_entity ()) = true;
> >               return bool (flags & WMB_Export);
> > @@ -13229,6 +13229,7 @@ depset::hash::add_binding_entity (tree decl, 
> > WMB_Flags flags, void *data_)
> >       OVL_PURVIEW_P (decl) = true;
> >       if (flags & WMB_Export)
> >         OVL_EXPORT_P (decl) = true;
> > +     OVL_SOURCE_LOCATION (decl) = loc;
> >     }
> >         depset *dep = data->hash->make_dependency
> > @@ -13616,7 +13617,10 @@ depset::hash::find_dependencies (module_state 
> > *module)
> >           dump.indent ();
> >           walker.begin ();
> >           if (current->get_entity_kind () == EK_USING)
> > -           walker.tree_node (OVL_FUNCTION (decl));
> > +           {
> > +             module->note_location (OVL_SOURCE_LOCATION (decl));
> > +             walker.tree_node (OVL_FUNCTION (decl));
> > +           }
> >           else if (TREE_VISITED (decl))
> >             /* A global tree.  */;
> >           else if (item->get_entity_kind () == EK_NAMESPACE)
> > @@ -15114,6 +15118,7 @@ module_state::write_cluster (elf_out *to, depset 
> > *scc[], unsigned size,
> >             depset *dep = b->deps[jx];
> >             tree bound = dep->get_entity ();
> >             unsigned flags = 0;
> > +           location_t loc = UNKNOWN_LOCATION;
> >             if (dep->get_entity_kind () == depset::EK_USING)
> >               {
> >                 tree ovl = bound;
> > @@ -15126,6 +15131,7 @@ module_state::write_cluster (elf_out *to, depset 
> > *scc[], unsigned size,
> >                   flags |= cbf_using;
> >                 if (OVL_EXPORT_P (ovl))
> >                   flags |= cbf_export;
> > +               loc = OVL_SOURCE_LOCATION (ovl);
> >               }
> >             else
> >               {
> > @@ -15140,6 +15146,8 @@ module_state::write_cluster (elf_out *to, depset 
> > *scc[], unsigned size,
> >             gcc_checking_assert (DECL_P (bound));
> >             sec.i (flags);
> > +           if (flags & cbf_using)
> > +             write_location (sec, loc);
> >             sec.tree_node (bound);
> >           }
> > @@ -15281,6 +15289,10 @@ module_state::read_cluster (unsigned snum)
> >                 && (flags & (cbf_using | cbf_export)))
> >               sec.set_overrun ();
> > +           location_t loc = UNKNOWN_LOCATION;
> > +           if (flags & cbf_using)
> > +             loc = read_location (sec);
> > +
> >             tree decl = sec.tree_node ();
> >             if (sec.get_overrun ())
> >               break;
> > @@ -15291,8 +15303,7 @@ module_state::read_cluster (unsigned snum)
> >                 if (type || !DECL_IMPLICIT_TYPEDEF_P (decl))
> >                   sec.set_overrun ();
> > -               type = build_lang_decl_loc (UNKNOWN_LOCATION,
> > -                                           USING_DECL,
> > +               type = build_lang_decl_loc (loc, USING_DECL,
> >                                             DECL_NAME (decl),
> >                                             NULL_TREE);
> >                 USING_DECL_DECLS (type) = decl;
> > @@ -15313,10 +15324,7 @@ module_state::read_cluster (unsigned snum)
> >                     if (decls)
> >                       sec.set_overrun ();
> > -                   /* FIXME: Propagate the location of the using-decl
> > -                      for use in diagnostics.  */
> > -                   decls = build_lang_decl_loc (UNKNOWN_LOCATION,
> > -                                                USING_DECL,
> > +                   decls = build_lang_decl_loc (loc, USING_DECL,
> >                                                  DECL_NAME (decl),
> >                                                  NULL_TREE);
> >                     USING_DECL_DECLS (decls) = decl;
> > @@ -15339,6 +15347,7 @@ module_state::read_cluster (unsigned snum)
> >                         OVL_PURVIEW_P (decls) = true;
> >                         if (flags & cbf_export)
> >                           OVL_EXPORT_P (decls) = true;
> > +                       OVL_SOURCE_LOCATION (decls) = loc;
> >                       }
> >                     if (flags & cbf_hidden)
> > diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc
> > index 96d7f938162..52c07e46d4f 100644
> > --- a/gcc/cp/name-lookup.cc
> > +++ b/gcc/cp/name-lookup.cc
> > @@ -4229,6 +4229,17 @@ ovl_iterator::exporting_p () const
> >     return OVL_EXPORT_P (ovl);
> >   }
> > +/* The declared source location of this using.  */
> > +
> > +location_t
> > +ovl_iterator::source_location () const
> > +{
> > +  gcc_checking_assert (using_p ());
> > +  if (TREE_CODE (ovl) == USING_DECL)
> > +    return DECL_SOURCE_LOCATION (ovl);
> > +  return OVL_SOURCE_LOCATION (ovl);
> > +}
> > +
> >   /* Given a namespace-level binding BINDING, walk it, calling CALLBACK
> >      for all decls of the current module.  When partitions are involved,
> >      decls might be mentioned more than once.   Return the accumulation of
> > @@ -4236,7 +4247,8 @@ ovl_iterator::exporting_p () const
> >   unsigned
> >   walk_module_binding (tree binding, bitmap partitions,
> > -                bool (*callback) (tree decl, WMB_Flags, void *data),
> > +                bool (*callback) (tree decl, WMB_Flags, void *data,
> > +                                  location_t loc),
> >                  void *data)
> >   {
> >     tree current = binding;
> > @@ -4249,6 +4261,7 @@ walk_module_binding (tree binding, bitmap partitions,
> >     if (tree type = MAYBE_STAT_TYPE (current))
> >       {
> >         WMB_Flags flags = WMB_None;
> > +      location_t loc = UNKNOWN_LOCATION;
> >         if (STAT_TYPE_HIDDEN_P (current))
> >     flags = WMB_Flags (flags | WMB_Hidden);
> >         if (TREE_CODE (type) == USING_DECL)
> > @@ -4258,8 +4271,9 @@ walk_module_binding (tree binding, bitmap partitions,
> >         flags = WMB_Flags (flags | WMB_Purview);
> >       if (DECL_MODULE_EXPORT_P (type))
> >         flags = WMB_Flags (flags | WMB_Export);
> > +     loc = DECL_SOURCE_LOCATION (type);
> >     }
> > -      count += callback (type, flags, data);
> > +      count += callback (type, flags, data, loc);
> >         decl_hidden = STAT_DECL_HIDDEN_P (current);
> >       }
> > @@ -4270,6 +4284,7 @@ walk_module_binding (tree binding, bitmap partitions,
> >         if (!(decl_hidden && DECL_IS_UNDECLARED_BUILTIN (*iter)))
> >     {
> >       WMB_Flags flags = WMB_None;
> > +     location_t loc = UNKNOWN_LOCATION;
> >       if (decl_hidden)
> >         flags = WMB_Flags (flags | WMB_Hidden);
> >       if (iter.using_p ())
> > @@ -4279,8 +4294,9 @@ walk_module_binding (tree binding, bitmap partitions,
> >             flags = WMB_Flags (flags | WMB_Purview);
> >           if (iter.exporting_p ())
> >             flags = WMB_Flags (flags | WMB_Export);
> > +         loc = iter.source_location ();
> >         }
> > -     count += callback (*iter, flags, data);
> > +     count += callback (*iter, flags, data, loc);
> >     }
> >         decl_hidden = false;
> >       }
> > @@ -4319,13 +4335,14 @@ walk_module_binding (tree binding, bitmap 
> > partitions,
> >                 WMB_Flags flags = WMB_None;
> >                 if (maybe_dups)
> >                   flags = WMB_Flags (flags | WMB_Dups);
> > -               count += callback (bind, flags, data);
> > +               count += callback (bind, flags, data, UNKNOWN_LOCATION);
> >               }
> >             else if (STAT_HACK_P (bind) && MODULE_BINDING_PARTITION_P 
> > (bind))
> >               {
> >                 if (tree btype = STAT_TYPE (bind))
> >                   {
> >                     WMB_Flags flags = WMB_None;
> > +                   location_t loc = UNKNOWN_LOCATION;
> >                     if (maybe_dups)
> >                       flags = WMB_Flags (flags | WMB_Dups);
> >                     if (STAT_TYPE_HIDDEN_P (bind))
> > @@ -4337,8 +4354,9 @@ walk_module_binding (tree binding, bitmap partitions,
> >                           flags = WMB_Flags (flags | WMB_Purview);
> >                         if (DECL_MODULE_EXPORT_P (btype))
> >                           flags = WMB_Flags (flags | WMB_Export);
> > +                       loc = DECL_SOURCE_LOCATION (btype);
> >                       }
> > -                   count += callback (btype, flags, data);
> > +                   count += callback (btype, flags, data, loc);
> >                   }
> >                 bool part_hidden = STAT_DECL_HIDDEN_P (bind);
> >                 for (ovl_iterator iter (MAYBE_STAT_DECL (STAT_DECL (bind)));
> > @@ -4350,6 +4368,7 @@ walk_module_binding (tree binding, bitmap partitions,
> >                       (!(part_hidden && DECL_IS_UNDECLARED_BUILTIN 
> > (*iter)));
> >                     WMB_Flags flags = WMB_None;
> > +                   location_t loc = UNKNOWN_LOCATION;
> >                     if (maybe_dups)
> >                       flags = WMB_Flags (flags | WMB_Dups);
> >                     if (part_hidden)
> > @@ -4361,8 +4380,9 @@ walk_module_binding (tree binding, bitmap partitions,
> >                           flags = WMB_Flags (flags | WMB_Purview);
> >                         if (iter.exporting_p ())
> >                           flags = WMB_Flags (flags | WMB_Export);
> > +                       loc = iter.source_location ();
> >                       }
> > -                   count += callback (*iter, flags, data);
> > +                   count += callback (*iter, flags, data, loc);
> >                     part_hidden = false;
> >                   }
> >               }
> > diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h
> > index 5cf6ae6374a..8183cd50159 100644
> > --- a/gcc/cp/name-lookup.h
> > +++ b/gcc/cp/name-lookup.h
> > @@ -499,7 +499,8 @@ enum WMB_Flags
> >   };
> >   extern unsigned walk_module_binding (tree binding, bitmap partitions,
> > -                                bool (*)(tree decl, WMB_Flags, void *data),
> > +                                bool (*)(tree decl, WMB_Flags, void *data,
> > +                                         location_t loc),
> >                                  void *data);
> >   extern tree add_imported_namespace (tree ctx, tree name, location_t,
> >                                 unsigned module,
> > diff --git a/gcc/cp/ptree.cc b/gcc/cp/ptree.cc
> > index 15e46752d01..4f7fc96cc74 100644
> > --- a/gcc/cp/ptree.cc
> > +++ b/gcc/cp/ptree.cc
> > @@ -299,6 +299,12 @@ cxx_print_xnode (FILE *file, tree node, int indent)
> >         print_node (file, "optype", BASELINK_OPTYPE (node), indent + 4);
> >         break;
> >       case OVERLOAD:
> > +      if (location_t loc = OVL_SOURCE_LOCATION (node))
> > +   {
> > +     expanded_location xloc = expand_location (loc);
> > +     indent_to (file, indent + 4);
> > +     fprintf (file, "%s:%d:%d", xloc.file, xloc.line, xloc.column);
> > +   }
> >         print_node (file, "function", OVL_FUNCTION (node), indent + 4);
> >         print_node (file, "next", OVL_CHAIN (node), indent + 4);
> >         break;
> > diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
> > index dfd4a3a948b..21d8e0de329 100644
> > --- a/gcc/cp/tree.cc
> > +++ b/gcc/cp/tree.cc
> > @@ -2387,6 +2387,7 @@ ovl_insert (tree fn, tree maybe_ovl, int 
> > using_or_hidden)
> >         OVL_PURVIEW_P (maybe_ovl) = true;
> >       if (using_or_hidden > 2)
> >         OVL_EXPORT_P (maybe_ovl) = true;
> > +     OVL_SOURCE_LOCATION (maybe_ovl) = input_location;
> >     }
> >       }
> >     else
> > @@ -2532,6 +2533,7 @@ lookup_maybe_add (tree fns, tree lookup, bool 
> > deduping)
> >               {
> >                 lookup = ovl_make (OVL_FUNCTION (fns), lookup);
> >                 OVL_USING_P (lookup) = true;
> > +               OVL_SOURCE_LOCATION (lookup) = OVL_SOURCE_LOCATION (fns);
> >               }
> >             else
> >               lookup = lookup_add (OVL_FUNCTION (fns), lookup);
> 

Reply via email to