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