On Wed, 2025-08-13 at 11:24 +0200, Richard Biener wrote:
> On Wed, Jul 30, 2025 at 4:42 PM Qing Zhao <qing.z...@oracle.com> wrote:

[...snip...]

> 
> > 
> > 

> > diff --git a/gcc/diagnostic-context-rich-location.h 
> > b/gcc/diagnostic-context-rich-location.h
> > new file mode 100644
> > index 00000000000..676b9d23b05
> > --- /dev/null
> > +++ b/gcc/diagnostic-context-rich-location.h
> > @@ -0,0 +1,73 @@
> > +/* A rich_location subclass that lazily populates a diagnostic_path
> > +   with diagnostic context events, but only if the path is actually to be
> > +   used.

[...snip...]

> > +
> > +class lazy_diagnostic_context_path : public diagnostics::paths::lazy_path
> > +{
> > +public:
> > +  lazy_diagnostic_context_path (const tree_logical_location_manager
> > +                               &logical_loc_mgr,
> > +                               location_t location, gimple *stmt)
> > +  : diagnostics::paths::lazy_path (logical_loc_mgr),
> > +    m_logical_loc_mgr (logical_loc_mgr),
> > +    m_location (location), m_stmt (stmt)
> > +  {
> > +  }
> > +
> > +  std::unique_ptr<diagnostics::paths::path>
> > +  make_inner_path () const final override;
> > +  /* This method will be called on demand if a diagnostic is actually
> > +     emitted for this rich_location.  */
> > +
> > +  const tree_logical_location_manager &m_logical_loc_mgr;
> > +  location_t m_location;
> > +  gimple *m_stmt;
> > +};
> > +
> > +class rich_location_with_details : public gcc_rich_location
> > +{
> > +public:
> > +  rich_location_with_details (location_t location, gimple *stmt)
> > +  : gcc_rich_location (location),
> > +    m_lazy_diagnostic_context_path (m_logical_loc_mgr, location, stmt)
> > +  {
> > +    set_path (&m_lazy_diagnostic_context_path);
> > +  }
> > +
> > +  rich_location_with_details (location_t location, tree exp 
> > ATTRIBUTE_UNUSED)
> > +  : gcc_rich_location (location),
> > +    m_lazy_diagnostic_context_path (m_logical_loc_mgr, location, nullptr)
> > +  {
> > +  }

To answer your question below: note from the ctor here that
constructing a rich_location_with_details instance on the stack is, by
design, merely some field initializations, (for it, and for the
lazy_diagnostic_context_path stored within it).  There is no expensive
computation or heap allocation.

> > +
> > +private:
> > +  const tree_logical_location_manager m_logical_loc_mgr;
> > +  lazy_diagnostic_context_path m_lazy_diagnostic_context_path;
> > +};
> > +
> > +#endif // GCC_DIAGNOSTIC_CONTEXT_RICH_LOCATION_H

[...snip...]

> > diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
> > index 0f4aff6b59b..abfb8685ce7 100644
> > --- a/gcc/gimple-ssa-warn-access.cc
> > +++ b/gcc/gimple-ssa-warn-access.cc
> > @@ -57,6 +57,7 @@
> >  #include "pointer-query.h"
> >  #include "pretty-print-markup.h"
> >  #include "gcc-urlifier.h"
> > +#include "diagnostic-context-rich-location.h"
> > 
> >  /* Return true if tree node X has an associated location.  */
> > 
> > @@ -169,17 +170,19 @@ warn_string_no_nul (location_t loc, GimpleOrTree 
> > expr, const char *fname,
> >    if (expr)
> >      {
> >        tree func = get_callee_fndecl (expr);
> > +      rich_location_with_details richloc (loc, expr);
> > +
> >        if (bndrng)
> >         {
> >           if (wi::ltu_p (maxsiz, bndrng[0]))
> > -           warned = warning_at (loc, opt,
> > +           warned = warning_at (&richloc, opt,
> >                                  "%qD specified bound %s exceeds "
> >                                  "maximum object size %E",
> >                                  func, bndstr, maxobjsize);
> >           else
> >             {
> >               bool maybe = wi::to_wide (size) == bndrng[0];
> > -             warned = warning_at (loc, opt,
> > +             warned = warning_at (&richloc, opt,
> >                                    exact
> >                                    ? G_("%qD specified bound %s exceeds "
> >                                         "the size %E of unterminated array")
> > @@ -194,7 +197,7 @@ warn_string_no_nul (location_t loc, GimpleOrTree expr, 
> > const char *fname,
> >             }
> >         }
> >        else
> > -       warned = warning_at (loc, opt,
> > +       warned = warning_at (&richloc, opt,
> >                              "%qD argument missing terminating nul",
> >                              func);
> >      }
> > @@ -486,14 +489,16 @@ maybe_warn_nonstring_arg (tree fndecl, GimpleOrTree 
> > exp)
> >        tree maxobjsize = max_object_size ();
> >        if (tree_int_cst_lt (maxobjsize, bndrng[0]))
> >         {
> > +         rich_location_with_details richloc (loc, exp);
> > +
> 
> At which point do we perform the CFG walk to identify the control chain?
> My original idea was that we can stuff almost arbitrary compile-time into
> improving diagnostic output when we know we are going to emit it?  But
> I suppose this now happens unconditionally, before we know we are going
> to warn?  Maybe not in this instance, but as a general issue.  Or does the
> computation happen lazily when the rich location is "evaluated"?

Qing, please confirm, but I believe it happens lazily: constructing an
on-stack rich_location_with_details instance involves just initializing
some fields and pointers to vtables.  In particular, the
rich_location_with_details has a diagnostics::paths::lazy_path: the
inner path is only populated (with the CFG walk) if the the path is
actually used (when the diagnostic is emitted).

[...snip...]

Dave

Reply via email to