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.

-- >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);
-- 
2.43.2

Reply via email to