On Fri, Jan 09, 2026 at 01:27:44PM +0800, Jason Merrill wrote:
> On 1/9/26 3:24 AM, Marek Polacek wrote:
> > On Tue, Dec 16, 2025 at 10:48:40PM +0700, Jason Merrill wrote:
> > > On 11/15/25 8:36 AM, Marek Polacek wrote:
> > > > +static tree
> > > > +get_info (const constexpr_ctx *ctx, tree call, int n, bool 
> > > > *non_constant_p,
> > > > +         bool *overflow_p, tree *jump_target)
> > > > +{
> > > > +  gcc_checking_assert (call_expr_nargs (call) > n);
> > > > +  tree info = get_nth_callarg (call, n);
> > > > +  gcc_checking_assert (REFLECTION_TYPE_P (TREE_TYPE (info)));
> > > > +  info = cxx_eval_constant_expression (ctx, info, vc_prvalue,
> > > > +                                      non_constant_p, overflow_p,
> > > > +                                      jump_target);
> > > > +  if (*jump_target)
> > > > +    return NULL_TREE;
> > > > +  if (!REFLECT_EXPR_P (info))
> > > > +    {
> > > > +      *non_constant_p = true;
> > > > +      return NULL_TREE;
> > > > +    }
> > > > +  return info;
> > > > +}
> > > > +
> > > > +/* Try to get the underlying FUNCTION_DECL from reflection if any,
> > > > +   otherwise return R.  */
> > > 
> > > Please say more about why get_first_fn isn't suitable (if it isn't).
> > 
> > The problem is that get_fns asserts that there was an overload set,
> > but often there won't be.  What I could do is to introduce
> > maybe_get_first_fn that uses maybe_get_fns.
> 
> Sounds good.

Posted a patch for this:
<https://gcc.gnu.org/pipermail/gcc-patches/2026-January/706367.html>
 
> > > > +static tree
> > > > +eval_is_override (tree r)
> > > > +{
> > > > +  r = maybe_get_reflection_fndecl (r);
> > > > +  if (TREE_CODE (r) == FUNCTION_DECL
> > > > +      && DECL_CLASS_SCOPE_P (r)
> > > > +      && !DECL_CONSTRUCTOR_P (r)
> > > > +      && (IDENTIFIER_VIRTUAL_P (DECL_NAME (r))
> > > > +         || DECL_CONV_FN_P (r))
> > > > +      && !DECL_STATIC_FUNCTION_P (r)
> > > 
> > > I'd think checking DECL_VIRTUAL_P could replace most of the above
> > > conditions.
> > 
> > Changed to use DECL_VIRTUAL_P in
> > <https://forge.sourceware.org/marek/gcc/commit/9a040fb9c52c963ac5cf5ecffa4f4a0769446b24>
> 
> Do we still need to check DECL_CONV_FN_P?

No, removed in
<https://forge.sourceware.org/marek/gcc/commit/7982d483b57952ca9005c0b131fbccb432ed2d80>

> > > > +/* Process std::meta::is_user_provided.
> > > > +   Returns: true if r represents a function that is user-provided.
> > > > +   Otherwise, false.  */
> > > > +
> > > > +static tree
> > > > +eval_is_user_provided (tree r)
> > > > +{
> > > > +  r = maybe_get_reflection_fndecl (r);
> > > > +  if (TREE_CODE (r) == FUNCTION_DECL
> > > > +      && user_provided_p (r)
> > > > +      // TODO: user_provided_p is false for non-members defaulted on
> > > > +      // first declaration.
> > > 
> > > Maybe we could set DECL_INITIALIZED_IN_CLASS_P for non-member functions, 
> > > too
> > > (and probably rename it).
> > 
> > I suppose, but I'd rather not do it as part of the Reflection patch.
> 
> Fair...
> 
> > > > +      && (!DECL_NAMESPACE_SCOPE_P (r) || !DECL_DELETED_FN (r)))
> 
> ...but then I'd rather not halfway work around the issue in the reflection
> patch, either.

I'm a little worried about changing DECL_INITIALIZED_IN_CLASS_P in
stage 4.  What if I opened an internal-improvement PR for this?

> > > > +  if (TREE_CODE (r) == CONST_DECL)
> > > > +    return boolean_true_node;
> > > > +  else
> > > > +    return boolean_false_node;
> > > > +}
> > > > +
> > > > +/* Process std::meta::has_internal_linkage.
> > > > +   Returns: true if r represents a variable, function, type, template, 
> > > > or
> > > > +   namespace whose name has internal linkage.  Otherwise, false.  */
> > > > +
> > > > +static tree
> > > > +eval_has_internal_linkage (tree r, reflect_kind kind)
> > > > +{
> > > > +  if (eval_is_variable (r, kind) == boolean_false_node
> > > > +      && eval_is_function (r) == boolean_false_node
> > > > +      && eval_is_type (r) == boolean_false_node
> > > > +      && eval_is_template (r) == boolean_false_node
> > > > +      && eval_is_namespace (r) == boolean_false_node)
> > > > +    return boolean_false_node;
> > > > +  r = maybe_get_reflection_fndecl (r);
> > > > +  r = STRIP_TEMPLATE (r);
> > > > +  if (TYPE_P (r))
> > > > +    {
> > > > +      if (TYPE_NAME (r) == NULL_TREE
> > > > +         || !DECL_P (TYPE_NAME (r))
> > > > +         || (!DECL_IMPLICIT_TYPEDEF_P (TYPE_NAME (r))
> > > > +             && TYPE_NAME (r) == TYPE_NAME (TYPE_MAIN_VARIANT (r))
> > > > +             && !TYPE_MAIN_DECL (r)))
> > > 
> > > It seems simpler to go directly to TYPE_NAME (TYPE_MAIN_VARIANT (r)) to 
> > > find
> > > the name with linkage, and probably also check OVERLOAD_TYPE_P.
> > 
> > I didn't understand this.
> 
> I was thinking type_linkage_name would be
> 
> if (!OVERLOAD_TYPE_P (t))
>   return NULL_TREE;
> return TYPE_NAME (TYPE_MAIN_VARIANT (t));

That breaks:

  struct cls { };
  using alias = cls;
  template<typename> struct cls_tmpl {};
  template<typename T> using cls_tmpl_alias = cls_tmpl<T>;

  static_assert (!has_linkage (^^alias));
  static_assert (!has_linkage (^^cls_tmpl_alias<int>));

Currently, for a RECORD_TYPE alias we return a TYPE_DECL alias,
but with this patch we return a TYPE_DECL cls (and same for the
alias template case).

Marek

Reply via email to